mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-02 20:31:45 +00:00

# Which Problems Are Solved - Adds support for the list users SCIM v2 endpoint # How the Problems Are Solved - Adds support for the list users SCIM v2 endpoints under `GET /scim/v2/{orgID}/Users` and `POST /scim/v2/{orgID}/Users/.search` # Additional Changes - adds a new function `SearchUserMetadataForUsers` to the query layer to query a metadata keyset for given user ids - adds a new function `NewUserMetadataExistsQuery` to the query layer to query a given metadata key value pair exists - adds a new function `CountUsers` to the query layer to count users without reading any rows - handle `ErrorAlreadyExists` as scim errors `uniqueness` - adds `NumberLessOrEqual` and `NumberGreaterOrEqual` query comparison methods - adds `BytesQuery` with `BytesEquals` and `BytesNotEquals` query comparison methods # Additional Context Part of #8140 Supported fields for scim filters: * `meta.created` * `meta.lastModified` * `id` * `username` * `name.familyName` * `name.givenName` * `emails` and `emails.value` * `active` only eq and ne * `externalId` only eq and ne
66 lines
2.1 KiB
Go
66 lines
2.1 KiB
Go
package resources
|
|
|
|
import (
|
|
"context"
|
|
"path"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
|
"github.com/zitadel/zitadel/internal/api/http"
|
|
"github.com/zitadel/zitadel/internal/api/scim/schemas"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
)
|
|
|
|
type ResourceHandler[T ResourceHolder] interface {
|
|
ResourceNameSingular() schemas.ScimResourceTypeSingular
|
|
ResourceNamePlural() schemas.ScimResourceTypePlural
|
|
SchemaType() schemas.ScimSchemaType
|
|
NewResource() T
|
|
|
|
Create(ctx context.Context, resource T) (T, error)
|
|
Replace(ctx context.Context, id string, resource T) (T, error)
|
|
Delete(ctx context.Context, id string) error
|
|
Get(ctx context.Context, id string) (T, error)
|
|
List(ctx context.Context, request *ListRequest) (*ListResponse[T], error)
|
|
}
|
|
|
|
type Resource struct {
|
|
Schemas []schemas.ScimSchemaType `json:"schemas"`
|
|
Meta *ResourceMeta `json:"meta"`
|
|
}
|
|
|
|
type ResourceMeta struct {
|
|
ResourceType schemas.ScimResourceTypeSingular `json:"resourceType"`
|
|
Created time.Time `json:"created"`
|
|
LastModified time.Time `json:"lastModified"`
|
|
Version string `json:"version"`
|
|
Location string `json:"location"`
|
|
}
|
|
|
|
type ResourceHolder interface {
|
|
GetResource() *Resource
|
|
}
|
|
|
|
func buildResource[T ResourceHolder](ctx context.Context, handler ResourceHandler[T], details *domain.ObjectDetails) *Resource {
|
|
created := details.CreationDate.UTC()
|
|
if created.IsZero() {
|
|
created = details.EventDate.UTC()
|
|
}
|
|
|
|
return &Resource{
|
|
Schemas: []schemas.ScimSchemaType{handler.SchemaType()},
|
|
Meta: &ResourceMeta{
|
|
ResourceType: handler.ResourceNameSingular(),
|
|
Created: created,
|
|
LastModified: details.EventDate.UTC(),
|
|
Version: strconv.FormatUint(details.Sequence, 10),
|
|
Location: buildLocation(ctx, handler, details.ID),
|
|
},
|
|
}
|
|
}
|
|
|
|
func buildLocation[T ResourceHolder](ctx context.Context, handler ResourceHandler[T], id string) string {
|
|
return http.DomainContext(ctx).Origin() + path.Join(schemas.HandlerPrefix, authz.GetCtxData(ctx).OrgID, string(handler.ResourceNamePlural()), id)
|
|
}
|