elimity-com / scim

Golang Implementation of the SCIM v2 Specification
MIT License
177 stars 55 forks source link

how to filter for patch #157

Closed suqin-haha closed 3 months ago

suqin-haha commented 1 year ago

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".

icamys commented 8 months ago

For those who have difficulties with filters in the patch, here's a working example.

  1. 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",
                }),
            },
        }),
    },
    }
  2. 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
  1. The application output will contain this:
    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]]}]
suqin-haha commented 8 months ago

@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.

icamys commented 8 months ago

@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.

suqin-haha commented 8 months ago

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.

ivixvi commented 3 months ago

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

Original text before translation `scim.PatchOperation.Path.ValueExpression` に、Patchリクエストで指定されたフィルターの条件が `filter.Expression`として入っています。 ※`filter`の実態は`"github.com/scim2/filter-parser/v2"`です これを用いて、論理式として展開・論理演算をすることでPatchの対象となる要素を取得することができます。 元リポジトリのテストでは、以下のようなコードがありますので、これを出力ではなく論理演算に変えるのが早そうです。 https://github.com/scim2/filter-parser/blob/master/filter_test.go#L50
ivixvi commented 3 months ago

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

Original text before translation 私もPATCH実装を試行錯誤している一人ではあります……。 素朴な実装でメンテナンス性が微妙かもしれませんが以下のリポジトリで実装を進めています。 EntraIDの無難な設定ではそこそこ動くようになってきました。 https://github.com/ivixvi/scim-patch 最近は以下のリポジトリを参考に修正を進めようかなと考えています。 https://github.com/IzumiSy/go-scimpatch