Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
load("@rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "transform",
srcs = [
"filter.go",
"map.go",
],
importpath = "github.com/lestrrat-go/jwx/v3/transform",
visibility = ["//visibility:public"],
deps = [
"@com_github_lestrrat_go_blackmagic//:blackmagic",
],
)
go_test(
name = "transform_test",
srcs = [
"map_test.go",
],
deps = [
":transform",
"//jwt",
"@com_github_stretchr_testify//require",
],
)
alias(
name = "go_default_library",
actual = ":transform",
visibility = ["//visibility:public"],
)
+115
View File
@@ -0,0 +1,115 @@
package transform
import "sync"
// FilterLogic is an interface that defines the logic for filtering objects.
type FilterLogic interface {
Apply(key string, object any) bool
}
// FilterLogicFunc is a function type that implements the FilterLogic interface.
type FilterLogicFunc func(key string, object any) bool
func (f FilterLogicFunc) Apply(key string, object any) bool {
return f(key, object)
}
// Filterable is an interface that must be implemented by objects that can be filtered.
type Filterable[T any] interface {
// Keys returns the names of all fields in the object.
Keys() []string
// Clone returns a deep copy of the object.
Clone() (T, error)
// Remove removes a field from the object.
Remove(string) error
}
// Apply is a standalone function that provides type-safe filtering based on
// specified filter logic.
//
// It returns a new object with only the fields that match the result of `logic.Apply`.
func Apply[T Filterable[T]](object T, logic FilterLogic) (T, error) {
return filterWith(object, logic, true)
}
// Reject is a standalone function that provides type-safe filtering based on
// specified filter logic.
//
// It returns a new object with only the fields that DO NOT match the result
// of `logic.Apply`.
func Reject[T Filterable[T]](object T, logic FilterLogic) (T, error) {
return filterWith(object, logic, false)
}
// filterWith is an internal function used by both Apply and Reject functions
// to apply the filtering logic to an object. If include is true, only fields
// matching the logic are included. If include is false, fields matching
// the logic are excluded.
func filterWith[T Filterable[T]](object T, logic FilterLogic, include bool) (T, error) {
var zero T
result, err := object.Clone()
if err != nil {
return zero, err
}
for _, k := range result.Keys() {
if ok := logic.Apply(k, object); (include && ok) || (!include && !ok) {
continue
}
if err := result.Remove(k); err != nil {
return zero, err
}
}
return result, nil
}
// NameBasedFilter is a filter that filters fields based on their field names.
type NameBasedFilter[T Filterable[T]] struct {
names map[string]struct{}
mu sync.RWMutex
logic FilterLogic
}
// NewNameBasedFilter creates a new NameBasedFilter with the specified field names.
//
// NameBasedFilter is the underlying implementation of the
// various filters in jwe, jwk, jws, and jwt packages. You normally do not
// need to use this directly.
func NewNameBasedFilter[T Filterable[T]](names ...string) *NameBasedFilter[T] {
nameMap := make(map[string]struct{}, len(names))
for _, name := range names {
nameMap[name] = struct{}{}
}
nf := &NameBasedFilter[T]{
names: nameMap,
}
nf.logic = FilterLogicFunc(nf.filter)
return nf
}
func (nf *NameBasedFilter[T]) filter(k string, _ any) bool {
_, ok := nf.names[k]
return ok
}
// Filter returns a new object with only the fields that match the specified names.
func (nf *NameBasedFilter[T]) Filter(object T) (T, error) {
nf.mu.RLock()
defer nf.mu.RUnlock()
return Apply(object, nf.logic)
}
// Reject returns a new object with only the fields that DO NOT match the specified names.
func (nf *NameBasedFilter[T]) Reject(object T) (T, error) {
nf.mu.RLock()
defer nf.mu.RUnlock()
return Reject(object, nf.logic)
}
+46
View File
@@ -0,0 +1,46 @@
package transform
import (
"errors"
"fmt"
"github.com/lestrrat-go/blackmagic"
)
// Mappable is an interface that defines methods required when converting
// a jwx structure into a map[string]any.
//
// EXPERIMENTAL: This API is experimental and its interface and behavior is
// subject to change in future releases. This API is not subject to semver
// compatibility guarantees.
type Mappable interface {
Get(key string, dst any) error
Keys() []string
}
// AsMap takes the specified Mappable object and populates the map
// `dst` with the key-value pairs from the Mappable object.
// Many objects in jwe, jwk, jws, and jwt packages including
// `jwt.Token`, `jwk.Key`, `jws.Header`, etc.
//
// EXPERIMENTAL: This API is experimental and its interface and behavior is
// subject to change in future releases. This API is not subject to semver
// compatibility guarantees.
func AsMap(m Mappable, dst map[string]any) error {
if dst == nil {
return fmt.Errorf("transform.AsMap: destination map cannot be nil")
}
for _, k := range m.Keys() {
var val any
if err := m.Get(k, &val); err != nil {
// Allow invalid value errors. Assume they are just nil values.
if !errors.Is(err, blackmagic.InvalidValueError()) {
return fmt.Errorf(`transform.AsMap: failed to get key %q: %w`, k, err)
}
}
dst[k] = val
}
return nil
}