mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 17:17:25 +00:00

# Which Problems Are Solved * Adds support for the patch user SCIM v2 endpoint # How the Problems Are Solved * Adds support for the patch user SCIM v2 endpoint under `PATCH /scim/v2/{orgID}/Users/{id}` # Additional Context Part of #8140
74 lines
2.5 KiB
Go
74 lines
2.5 KiB
Go
package patch
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/zitadel/logging"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/scim/resources/filter"
|
|
"github.com/zitadel/zitadel/internal/api/scim/serrors"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
)
|
|
|
|
func applyRemovePatch(patcher ResourcePatcher, op *Operation, value interface{}) error {
|
|
// the root cannot be removed
|
|
if op.Path == nil {
|
|
logging.Info("SCIM: remove patch without path")
|
|
return serrors.ThrowNoTarget(zerrors.ThrowInvalidArgument(nil, "SCIM-ozzy54", "Remove patch without path is not supported"))
|
|
}
|
|
|
|
result, err := patcher.FilterEvaluator().Evaluate(reflect.ValueOf(value), op.Path)
|
|
if err != nil {
|
|
return serrors.ThrowInvalidPath(zerrors.ThrowInvalidArgument(err, "SCIM-sd41", "Failed to evaluate path"))
|
|
}
|
|
|
|
switch filterResult := result.(type) {
|
|
case *filter.SimpleValueEvaluationResult:
|
|
return applyRemovePatchSimple(patcher, filterResult)
|
|
case *filter.FilteredValuesEvaluationResult:
|
|
return applyRemovePatchFiltered(patcher, filterResult)
|
|
}
|
|
|
|
logging.Errorf("SCIM remove patch: unsupported filter type %T", result)
|
|
return serrors.ThrowInvalidPath(zerrors.ThrowInvalidArgument(err, "SCIM-12syw", "Invalid patch path"))
|
|
}
|
|
|
|
func applyRemovePatchSimple(patcher ResourcePatcher, filterResult *filter.SimpleValueEvaluationResult) error {
|
|
filterResult.Value.Set(reflect.Zero(filterResult.Value.Type()))
|
|
return patcher.Removed(filterResult.PathSegments)
|
|
}
|
|
|
|
func applyRemovePatchFiltered(patcher ResourcePatcher, filterResult *filter.FilteredValuesEvaluationResult) error {
|
|
if len(filterResult.Matches) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// if a subattribute is selected, set that one to nil instead of removing the elements from the slice
|
|
if len(filterResult.PathSegments) > 1 {
|
|
for _, match := range filterResult.Matches {
|
|
match.Value.Set(reflect.Zero(match.Value.Type()))
|
|
}
|
|
|
|
return patcher.Removed(filterResult.PathSegments)
|
|
}
|
|
|
|
slice := filterResult.Source
|
|
sliceLen := slice.Len()
|
|
|
|
// if all elements are matched, set the field to nil
|
|
if sliceLen == len(filterResult.Matches) {
|
|
filterResult.Source.Set(reflect.Zero(slice.Type()))
|
|
return patcher.Removed(filterResult.PathSegments)
|
|
}
|
|
|
|
// start at the very last matched value to keep correct indexing
|
|
for i := len(filterResult.Matches) - 1; i >= 0; i-- {
|
|
match := filterResult.Matches[i]
|
|
slice = reflect.AppendSlice(slice.Slice(0, match.SourceIndex), slice.Slice(match.SourceIndex+1, sliceLen))
|
|
sliceLen--
|
|
}
|
|
|
|
filterResult.Source.Set(slice)
|
|
return patcher.Removed(filterResult.PathSegments)
|
|
}
|