Skip to content

rkaippully/scim-patch

Repository files navigation

License: MPL 2.0 Build Status codecov Clojars Project

[org.clojars.rkaippully/scim-patch "1.0.0"]

A Clojure library that implements patch operations as specified by SCIM RFC.

Usage

It is straightforward to patch a SCIM resource given its schema and patch operations.

First you need to define the schema like in the example below. Refer RFC7643 for more information about the SCIM schema.

(def schema {:attributes
             {:userName
              {:type :string}

              :name
              {:type
               {:attributes
                {:formatted
                 {:type :string}
                 :honorificPrefix
                 {:type         :string
                  :multi-valued true}}}}

              :phoneNumbers
              {:multi-valued true
               :type
               {:attributes
                {:value
                 {:type :string}
                 :display
                 {:type :string}
                 :type
                 {:type :string}
                 :primary
                 {:type :boolean}}}}

              :x509Certificates
              {:multi-valued true
               :type
               {:attributes
                {:value
                 {:type :binary}
                 :display
                 {:type :string}
                 :primary
                 {:type :boolean}}}}

              :urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
              {:type
               {:attributes
                {:employeeNumber
                 {:type :string}
                 :manager
                 {:type
                  {:attributes
                   {:displayName
                    {:type :string}}}}}}}}})

Once you have such a schema, you can perform patch operations as shown below:

user=> (require '[scim-patch.core :as p])
user=> (def resource {:userName "foo"
                      :phoneNumbers [{:type  "work"
                                      :value "555-555-1111"}
                                     {:type  "home"
                                      :value "555-555-2222"}]})

user=> (p/patch schema resource {:op    "replace"
                                 :path  "userName"
                                 :value "bar"})
{:userName "bar",
 :phoneNumbers
 [{:type "work", :value "555-555-1111"}
  {:type "home", :value "555-555-2222"}]}

You can also pass multiple operations in a single invocation of patch function:

user=> (p/patch schema resource [{:op    "replace"
                                  :path  "userName"
                                  :value "bar"}
                                 {:op    "add"
                                  :path  "phoneNumbers[type eq \"work\"].display"
                                  :value "+1-555-555-1111"}])
{:userName "bar",
 :phoneNumbers
 ({:type "work", :value "555-555-1111", :display "+1-555-555-1111"}
  {:type "home", :value "555-555-2222"})}

Errors are reported as exceptions generated via ex-info.

user=> (try
         (p/patch schema resource {:op    "replace"
                                   :path  "userNames"
                                   :value "bar"})
         (catch Exception e
           (ex-data e)))
{:status 400, :scimType :invalidPath}

You can define a list of schemas you would like to restrict the operations to. For example, the below schema declares that the URI of the primary schema is "urn:ietf:params:scim:schemas:core:2.0:User" and you are only interested in processing patches to "urn:ietf:params:scim:schemas:core:2.0:User" and "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User".

(def schema
  {;; the primary schema URI
   :id      "urn:ietf:params:scim:schemas:core:2.0:User"

   ;; Allowed schemas
   :schemas ["urn:ietf:params:scim:schemas:core:2.0:User"
             "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]

   :attributes
   {:userName
    {:type :string}

    :name
    {:type
     {:attributes
      {:formatted
       {:type :string}
       :honorificPrefix
       {:type         :string
        :multi-valued true}}}}

    :phoneNumbers
    {:multi-valued true
     :type
     {:attributes
      {:value
       {:type :string}
       :display
       {:type :string}
       :type
       {:type :string}
       :primary
       {:type :boolean}}}}

    :x509Certificates
    {:multi-valued true
     :type
     {:attributes
      {:value
       {:type :binary}
       :display
       {:type :string}
       :primary
       {:type :boolean}}}}

    :urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
    {:type
     {:attributes
      {:employeeNumber
       {:type :string}
       :manager
       {:type
        {:attributes
         {:displayName
          {:type :string}}}}}}}}})

The following patch will now pass instead of failing with an invalid path error:

user=> (p/patch schema resource [{:op    "replace"
                                  :path  "userName"
                                  :value "bar"}
                                 {:op    "replace"
                                  :path  "urn:ietf:params:scim:schemas:core:2.0:Group:displayName"
                                  :value "Administrators"}])
{:userName "bar",
 :phoneNumbers
 [{:type "work", :value "555-555-1111"}
  {:type "home", :value "555-555-2222"}]}

Contributors

  • Raghu Kaippully @rkaippully [email protected]
  • Tim Smith @smithtim
  • Jason Stiefel @JasonStiefel
  • Quest Yarbrough @Quezion

License

Copyright © 2019-2020, Raghu Kaippully and the scim-patch contributors.

Distributed under the Mozilla Public License version 2.0.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •