From f292fcc28410baa144e67cff308c4e743222715f Mon Sep 17 00:00:00 2001 From: Tim Smith Date: Thu, 1 Oct 2020 14:50:03 -0700 Subject: [PATCH 1/2] make skip unknown schemas optional, default to false --- src/scim_patch/core.clj | 38 +++++++++++++++++++---------------- test/scim_patch/core_test.clj | 5 ++++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/scim_patch/core.clj b/src/scim_patch/core.clj index ba98911..05c3977 100644 --- a/src/scim_patch/core.clj +++ b/src/scim_patch/core.clj @@ -24,12 +24,13 @@ (update resource attr-key #(handle-attr-path-levels (:type schema') (or % {}) update-fn attrs)))))) (defn handle-attr-path - [schema resource uri attr subattr update-fn] + [schema resource uri attr subattr skip-unknown? update-fn] (let [patching-schema (if (s/blank? uri) (:id schema) uri) patchable-schemas (:schemas schema)] - (if (or (nil? patching-schema) + (if (or (not skip-unknown?) + (nil? patching-schema) (nil? patchable-schemas) (some #{patching-schema} patchable-schemas)) ;; The schema is patchable @@ -41,24 +42,24 @@ resource))) (defn handle-operation - [schema resource {:keys [path value]} attr-path-fn value-path-fn] + [schema resource {:keys [path value]} skip-unknown? attr-path-fn value-path-fn] (try (if (s/blank? path) ;; no path, so handle each attribute separately (reduce (fn [r [k v]] - (handle-operation schema r {:path (name k) :value v} attr-path-fn value-path-fn)) + (handle-operation schema r {:path (name k) :value v} skip-unknown? attr-path-fn value-path-fn)) resource value) ;; path provided (let [[_ xs] (paths/parse path)] (case (first xs) :attrPath (let [[uri attr subattr] (paths/extract-attr-path xs)] - (handle-attr-path schema resource uri attr subattr + (handle-attr-path schema resource uri attr subattr skip-unknown? (partial attr-path-fn value))) :valuePath (let [[_ attr-path value-filter subattr2] xs [uri attr subattr] (paths/extract-attr-path attr-path)] - (handle-attr-path schema resource uri attr subattr + (handle-attr-path schema resource uri attr subattr skip-unknown? (partial value-path-fn value value-filter subattr2)))))) (catch ExceptionInfo e (throw (ex-info (.getMessage e) @@ -100,7 +101,7 @@ old-val))) (defn op-add - [schema resource opr] + [schema resource opr skip-unknown?] (letfn [(add-attr-path [value res attr sch] (try @@ -123,7 +124,7 @@ (catch ExceptionInfo e (throw (ex-info (.getMessage e) (assoc (ex-data e) :path (:path opr)))))))] - (handle-operation schema resource opr add-attr-path add-value-path))) + (handle-operation schema resource opr skip-unknown? add-attr-path add-value-path))) (defn filter-and-remove [schema value-filter subattr] @@ -142,7 +143,7 @@ (conj acc old-val)))) (defn op-remove - [schema resource opr] + [schema resource opr skip-unknown?] (when (s/blank? (:path opr)) (throw (ex-info "Missing path for remove operation" {:status 400 @@ -163,7 +164,7 @@ (dissoc res attr-key) (assoc res attr-key new-val))))] - (handle-operation schema resource opr remove-attr-path remove-value-path))) + (handle-operation schema resource opr skip-unknown? remove-attr-path remove-value-path))) (defn value-for-replace [schema value] @@ -194,7 +195,7 @@ {:replaced? replaced? :value (conj value old-val)}))) (defn op-replace - [schema resource opr] + [schema resource opr skip-unknown?] (letfn [(replace-attr-path [value res attr sch] (assoc res (keyword attr) (value-for-replace sch value))) @@ -214,21 +215,24 @@ {:status 400 :scimType :noTarget}))))))] - (handle-operation schema resource opr replace-attr-path replace-value-path))) + (handle-operation schema resource opr skip-unknown? replace-attr-path replace-value-path))) (defn patch - [schema resource op] + [schema resource op & {:keys [skip-unknown-schemas]}] + (if (and skip-unknown-schemas (not (:schemas schema))) + (throw (ex-info "Option 'skip-unknown-schemas' requires :schemas in schema" + {:status 400 :scimType :invalidSyntax}))) (cond ;; single patch operation (map? op) (case (:op op) - "add" (op-add schema resource op) - "remove" (op-remove schema resource op) - "replace" (op-replace schema resource op) + "add" (op-add schema resource op skip-unknown-schemas) + "remove" (op-remove schema resource op skip-unknown-schemas) + "replace" (op-replace schema resource op skip-unknown-schemas) (throw (ex-info (str "Invalid operation") {:status 400 :scimType :invalidSyntax :op (:op op)}))) ;; sequence of operations (sequential? op) - (reduce #(patch schema %1 %2) resource op))) + (reduce #(patch schema %1 %2 :skip-unknown-schemas skip-unknown-schemas) resource op))) diff --git a/test/scim_patch/core_test.clj b/test/scim_patch/core_test.clj index afcefc1..3d8e49b 100644 --- a/test/scim_patch/core_test.clj +++ b/test/scim_patch/core_test.clj @@ -754,6 +754,9 @@ (is (= {:status 400 :scimType :invalidPath :path "urn:ietf:params:scim:schemas:core:2.0:Group:displayName"} (get-ex-data (sut/patch schema user patch))))) + (testing "throws an exception if told to filter but not given a filter list" + (is (= {:status 400 :scimType :invalidSyntax} + (get-ex-data (sut/patch schema user patch :skip-unknown-schemas true))))) (testing "ignores unknown schema if there is a schema filter" (is (= (assoc user :userName "bar") - (sut/patch schema' user patch)))))) + (sut/patch schema' user patch :skip-unknown-schemas true)))))) From 37123c50775a71ab8a328eb74af88aceabb0d5ac Mon Sep 17 00:00:00 2001 From: Tim Smith Date: Fri, 2 Oct 2020 12:01:28 -0700 Subject: [PATCH 2/2] check for nil schemas happens earlier --- src/scim_patch/core.clj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/scim_patch/core.clj b/src/scim_patch/core.clj index 05c3977..f6cc8ef 100644 --- a/src/scim_patch/core.clj +++ b/src/scim_patch/core.clj @@ -31,7 +31,6 @@ patchable-schemas (:schemas schema)] (if (or (not skip-unknown?) (nil? patching-schema) - (nil? patchable-schemas) (some #{patching-schema} patchable-schemas)) ;; The schema is patchable (as-> [attr] $