zitadel/internal/api/scim/resources/resource_handler.go
Lars df8bac8a28
feat: bulk scim v2 endpoint (#9256)
# Which Problems Are Solved
* Adds support for the bulk SCIM v2 endpoint

# How the Problems Are Solved
* Adds support for the bulk SCIM v2 endpoint under `POST
/scim/v2/{orgID}/Bulk`

# Additional Context
Part of #8140

Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
2025-01-29 14:23:56 +00:00

75 lines
2.4 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/resources/patch"
"github.com/zitadel/zitadel/internal/api/scim/schemas"
"github.com/zitadel/zitadel/internal/domain"
)
type ResourceHandler[T ResourceHolder] interface {
SchemaType() schemas.ScimSchemaType
ResourceNameSingular() schemas.ScimResourceTypeSingular
ResourceNamePlural() schemas.ScimResourceTypePlural
NewResource() T
Create(ctx context.Context, resource T) (T, error)
Replace(ctx context.Context, id string, resource T) (T, error)
Update(ctx context.Context, id string, operations patch.OperationCollection) 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 {
ID string `json:"-"`
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 {
SchemasHolder
GetResource() *Resource
}
type SchemasHolder interface {
GetSchemas() []schemas.ScimSchemaType
}
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{
ID: details.ID,
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.ResourceNamePlural(), details.ID),
},
}
}
func buildLocation(ctx context.Context, resourceName schemas.ScimResourceTypePlural, id string) string {
return http.DomainContext(ctx).Origin() + path.Join(schemas.HandlerPrefix, authz.GetCtxData(ctx).OrgID, string(resourceName), id)
}