Closed suqin-haha closed 3 months ago
For those who have difficulties with filters in the patch, here's a working example.
Set up a simple user schema with a multi-values emails
attribute:
userSchema := schema.Schema{
ID: "urn:ietf:params:scim:schemas:core:2.0:User",
Name: optional.NewString("User"),
Description: optional.NewString("User Account"),
Attributes: []schema.CoreAttribute{
schema.ComplexCoreAttribute(schema.ComplexParams{
MultiValued: true,
Name: "emails",
SubAttributes: []schema.SimpleParams{
schema.SimpleStringParams(schema.StringParams{
Name: "value",
}),
schema.SimpleStringParams(schema.StringParams{
CanonicalValues: []string{"work", "home", "other"},
Name: "type",
}),
schema.SimpleBooleanParams(schema.BooleanParams{
Name: "primary",
}),
},
}),
},
}
Write a simple patch handler implementation:
type UserResourceHandler struct{} // implements scim.ResourceHandler interface
func (u UserResourceHandler) Patch(r http.Request, id string, operations []scim.PatchOperation) (scim.Resource, error) { log.Println(fmt.Sprintf("Patch user %s with operations: %+v", id, operations))
return scim.Resource{}, nil
}
3. Send a PATCH HTTP request:
```bash
#!/bin/bash
REQUEST_BODY='{ "schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations":[ {"op":"Replace","path":"emails[value eq \"existing@mail.com\"]","value":{"value": "changed@mail.com", "type":"work", "primary": true} } ] }'
curl -v -X PATCH \
-d ${REQUEST_BODY} \
-H "Content-Type: application/json" http://localhost:7643/scim/v2/Users/1
2024/03/08 18:44:36 Patch user 1 with operations: [{Op:replace Path:emails[value eq "existing@mail.com"] Value:[map[primary:true type:work value:changed@mail.com]]}]
@icamys Could I know how do you perform the patch actions? Cause I don't have a good idea to do patch as in RFC with resources that the handler or arguments provided.
@suqin-haha Perhaps you are looking for the jsonpatch package + after applying the patch you can validate the resulting structure against schema using Schema.Validate() function.
I checked this repo before. um... it might works in someway but patch in RFC works together with the 'Characters', like, using the repo cannot check 'mutamility', And the repo use '/' in path while RFC use '.'. Indeed, it's possible to make it works with some adjustment.
The filter conditions specified in the Patch request are contained in scim.PatchOperation.Path.ValueExpression
as filter.Expression
.
※ The actual implementation of filter is "github.com/scim2/filter-parser/v2".
Using this, you can expand and perform logical operations to obtain the elements that are the target of the Patch. In the original repository's test, there is code like the one below, so it seems quicker to change this to logical operations instead of output.
https://github.com/scim2/filter-parser/blob/master/filter_test.go#L50
I am also one of those who are experimenting with PATCH implementation. Although it might be a simple implementation with questionable maintainability, I am working on it in the following repository. It has started to work reasonably well with a straightforward EntraID configuration. https://github.com/ivixvi/scim-patch
Recently, I have been considering making modifications based on the following repository: https://github.com/IzumiSy/go-scimpatch
looks there is no filter for the value in patch path. Like, how do you guys check
type == "work"
? for"addresses[type eq \"work\"].streetAddress"
.