diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index 226bc0b..2152466 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -659,55 +659,26 @@ (s/coll-of ::agent :kind vector? :into [] :gen-max 3)) (s/def ::identified-group - (s/keys :req [:group/objectType - (or :group/mbox + (s/with-gen + (s/and + (s/conformer + (partial conform-ns-map "group") + unform-ns-map) + (s/keys :req [:group/objectType + (or :group/mbox + :group/mbox_sha1sum + :group/openid + :group/account)] + :opt [:group/name + :group/member]) + (restrict-keys :group/mbox :group/mbox_sha1sum :group/openid - :group/account)] - :opt [:group/name - :group/member])) - -(s/def ::anonymous-group - (s/and - (s/keys :req [:group/objectType - :group/member] - :opt [:group/name]) - #(-> % :group/member seq))) - -(def identified-group? - (comp - some? - (some-fn :group/mbox - :group/mbox_sha1sum - :group/openid - :group/account))) - -(defmulti group-type #(if (identified-group? %) - :group/identified - :group/anonymous)) - -(defmethod group-type :group/identified [_] - ::identified-group) - -(defmethod group-type :group/anonymous [_] - ::anonymous-group) - - -(s/def ::group - (s/with-gen (s/and - (s/conformer - (partial conform-ns-map "group") - unform-ns-map) - (s/multi-spec group-type (fn [gen-val _] - gen-val)) - (restrict-keys :group/mbox - :group/mbox_sha1sum - :group/openid - :group/account - :group/name - :group/objectType - :group/member) - max-one-ifi) + :group/account + :group/name + :group/objectType + :group/member) + max-one-ifi) #(sgen/fmap unform-ns-map (s/gen (s/or :ifi-mbox @@ -729,12 +700,47 @@ (s/keys :req [:group/account] :opt [:group/member :group/name - :group/objectType]) - :anon - (s/keys :req [:group/member] - :opt [:group/name :group/objectType])))))) +(s/def ::anonymous-group + (s/with-gen + (s/and + (s/conformer + (partial conform-ns-map "group") + unform-ns-map) + (s/keys :req [:group/objectType + :group/member] + :opt [:group/name]) + (restrict-keys :group/objectType + :group/member + :group/name) + #(-> % :group/member not-empty)) + #(sgen/fmap + unform-ns-map + (s/gen (s/keys :req [:group/member] + :opt [:group/name + :group/objectType]))))) + +(defn identified-group? + [group] + (-> group + (select-keys ["mbox" "mbox_sha1sum" "openid" "account"]) + not-empty + boolean)) + +(defmulti group-type #(if (identified-group? %) + :group/identified + :group/anonymous)) + +(defmethod group-type :group/identified [_] + ::identified-group) + +(defmethod group-type :group/anonymous [_] + ::anonymous-group) + +(s/def ::group + (s/multi-spec group-type (fn [gen-val _] gen-val))) + ;; Actor (defmulti actor-type (fn [a] diff --git a/src/xapi_schema/spec/resources.cljc b/src/xapi_schema/spec/resources.cljc index d9e94ab..92625d4 100644 --- a/src/xapi_schema/spec/resources.cljc +++ b/src/xapi_schema/spec/resources.cljc @@ -58,9 +58,12 @@ ;; xAPI Resources ;; common + (s/def :xapi.common.param/agent (json - (s/nonconforming ::xs/actor))) + (s/nonconforming + ;; except for statement queries, groups are not allowed as agent params + ::xs/agent))) ;; Statements ;; GET https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Communication.md#213-get-statements @@ -71,7 +74,12 @@ :statement/id) (s/def :xapi.statements.GET.request.params/agent - :xapi.common.param/agent) + (json + (s/nonconforming + ;; anonymous groups are not allowed as agent params + ;; identified gorups, on the other hand, are allowed + (s/or :agent ::xs/agent + :group ::xs/identified-group)))) (s/def :xapi.statements.GET.request.params/verb ::xs/iri) @@ -194,8 +202,7 @@ :activity/id) (s/def :xapi.document.params/agent - (json - (s/nonconforming ::xs/agent))) + :xapi.common.param/agent) (s/def :xapi.document.params/registration ::xs/uuid) @@ -249,7 +256,7 @@ ;; Agents https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Communication.md#24-agents-resource (s/def :xapi.agents.GET.request.params/agent - :xapi.document.params/agent) + :xapi.common.param/agent) (s/def :xapi.agents.GET.request/params (s/keys :req-un [:xapi.agents.GET.request.params/agent])) diff --git a/test/xapi_schema/spec/resources_test.cljc b/test/xapi_schema/spec/resources_test.cljc index e3f7ec8..f3e3cf8 100644 --- a/test/xapi_schema/spec/resources_test.cljc +++ b/test/xapi_schema/spec/resources_test.cljc @@ -1,5 +1,5 @@ (ns xapi-schema.spec.resources-test - (:require [clojure.test :refer [deftest is testing] :include-macros true] + (:require [clojure.test :refer [deftest is] :include-macros true] [clojure.spec.alpha :as s :include-macros true] [xapi-schema.spec.resources :as xsr :refer [*read-json-fn* *write-json-fn* @@ -30,8 +30,7 @@ {"foo" "bar"}))) (is (= "{\"foo\":\"bar\"}" (s/unform json-string-conformer - "{\"foo\":\"bar\"}"))) - ) + "{\"foo\":\"bar\"}")))) (deftest agent-param-test (is (s/valid? :xapi.common.param/agent @@ -39,9 +38,23 @@ (is (not (s/valid? :xapi.common.param/agent "{\"mbox\":\"milt@yetanalytics.com\"}"))) (is (not (s/valid? :xapi.common.param/agent - "{\"email\":\"mailto:milt@yetanalytics.com\"}")))) + "{\"email\":\"mailto:milt@yetanalytics.com\"}"))) + (is (not (s/valid? :xapi.common.param/agent + "{\"objectType\": \"Group\", + \"mbox\": \"mailto:group@example.com\", + \"member\": [{\"mbox\": \"mailto:foo@example.com\"}]}"))) + (is (not (s/valid? :xapi.common.param/agent + "{\"objectType\": \"Group\", + \"member\": [{\"mbox\": \"mailto:foo@example.com\"}]}")))) (deftest statements-get-params-test + (is (s/valid? :xapi.statements.GET.request.params/agent + "{\"objectType\": \"Group\", + \"mbox\": \"mailto:group@example.com\", + \"member\": [{\"mbox\": \"mailto:foo@example.com\"}]}")) + (is (not (s/valid? :xapi.statements.GET.request.params/agent + "{\"objectType\": \"Group\", + \"member\": [{\"mbox\": \"mailto:foo@example.com\"}]}"))) (is (s/valid? :xapi.statements.GET.request/params {:statementId (str #?(:clj (java.util.UUID/randomUUID) :cljs (random-uuid)))