From 071911ca934fed51c3c3728453103712ea314045 Mon Sep 17 00:00:00 2001 From: khaled basbous Date: Thu, 28 Sep 2023 08:56:19 +0200 Subject: [PATCH] wip --- code/src/sixsq/nuvla/db/es/binding.clj | 164 ++++++-- .../sixsq/nuvla/server/resources/module.clj | 2 +- code/src/sixsq/nuvla/server/util/response.clj | 28 +- .../test/sixsq/nuvla/db/binding_lifecycle.clj | 54 ++- .../user_username_password_lifecycle_test.clj | 387 +++++++++--------- .../sixsq/nuvla/server/util/response_test.clj | 2 +- 6 files changed, 394 insertions(+), 243 deletions(-) diff --git a/code/src/sixsq/nuvla/db/es/binding.clj b/code/src/sixsq/nuvla/db/es/binding.clj index 38a0cf938..a4e91f3fe 100644 --- a/code/src/sixsq/nuvla/db/es/binding.clj +++ b/code/src/sixsq/nuvla/db/es/binding.clj @@ -33,6 +33,7 @@ [client options] (spandex/sniffer client (or options {}))) +<<<<<<< Updated upstream (defn create-index [client index] @@ -71,8 +72,63 @@ (let [{:keys [status body] :as _response} (ex-data e) error (:error body)] (log/warn index "mapping could not be updated (" status "). " (or error e)))))) +======= +(defn get-error + [ex] + (let [response (ex-data ex)] + (or (-> response r/get-body :error) ex))) +>>>>>>> Stashed changes +(defn document-missing? + [ex] + (-> (ex-data ex) + r/get-body + (get-in [:root_cause 0 :type]) + (= "document_missing_exception"))) + +(defn create-index + [client index] + (try + (let [response (spandex/request client {:url [index], :method :head})] + (if (r/status-ok? response) + (log/debug index "index already exists") + (log/error "unexpected status code when checking" + index "index (" (r/get-status response) ")"))) + (catch Exception e + (let [response (ex-data e) + body (r/get-body response) + status (r/get-status response)] + (try + (if (r/status-not-found? response) + (let [{:keys [acknowledged shards_acknowledged]} + (r/get-body (spandex/request + client + {:url [index], :method :put}))] + (if (and acknowledged shards_acknowledged) + (log/info index "index created") + (log/warn index "index may or may not have been created"))) + (log/error "unexpected status code when checking" index "index (" status "). " body)) + (catch Exception e + (log/error "unexpected status code when creating" index "index (" status "). " + (get-error e)))))))) + +(defn set-index-mapping + [client index mapping] + (try + (let [response (spandex/request client {:url [index :_mapping] + :method :put + :body mapping}) + status (r/get-status response) + body (r/get-body response)] + (if (r/status-ok? response) + (log/info index "mapping updated") + (log/warn index "mapping could not be updated (" status "). " body))) + (catch Exception e + (let [response (ex-data e)] + (log/warn index "mapping could not be updated (" + (r/get-status response) "). " (get-error e)))))) + (defn add-data [client {:keys [id] :as data}] (try @@ -85,16 +141,19 @@ :query-string {:refresh true} :method :put :body updated-doc}) +<<<<<<< Updated upstream success? (pos? (get-in response [:body :_shards :successful]))] +======= + success? (shards-successful? response)] +>>>>>>> Stashed changes (if success? (r/response-created id) - (r/response-conflict id))) + (throw (r/ex-conflict id)))) (catch Exception e - (let [{:keys [status body] :as _response} (ex-data e) - error (:error body)] - (if (= 409 status) - (r/response-conflict id) - (r/response-error (str "unexpected exception: " (or error e)))))))) + (let [response (ex-data e)] + (if (r/status-conflict? response) + (throw (r/ex-conflict id)) + (throw (r/ex-unexpected (get-error e)))))))) (defn update-data @@ -109,15 +168,39 @@ :query-string {:refresh true} :method :put :body updated-doc}) +<<<<<<< Updated upstream success? (pos? (get-in response [:body :_shards :successful]))] +======= + success? (shards-successful? response)] +>>>>>>> Stashed changes (if success? (r/json-response data) - (r/response-conflict id))) + (throw (r/ex-conflict id)))) (catch Exception e - (let [{:keys [body] :as _response} (ex-data e) - error (:error body)] - (r/response-error (str "unexpected exception updating " id ": " (or error e))))))) - + (if (r/status-not-found? (ex-data e)) + (throw (r/ex-not-found id)) + (throw (r/ex-unexpected (get-error e))))))) + +<<<<<<< Updated upstream +======= +(defn scripted-update-data + [client id options] + (try + (let [[collection-id uuid] (cu/split-id id) + index (escu/collection-id->index collection-id) + response (spandex/request client {:url [index :_update uuid] + :query-string {:refresh true} + :method :post + :body options}) + success? (shards-successful? response)] + (if success? + (r/response-updated id) + (throw (r/ex-conflict id)))) + (catch Exception e + (if (r/status-not-found? (ex-data e)) + (throw (r/ex-not-found id)) + (throw (r/ex-unexpected (get-error e))))))) +>>>>>>> Stashed changes (defn find-data [client id] @@ -126,15 +209,15 @@ index (escu/collection-id->index collection-id) response (spandex/request client {:url [index :_doc uuid] :method :get}) - found? (get-in response [:body :found])] + body (r/get-body response) + found? (:found body)] (if found? - (-> response :body :_source) + (:_source body) (throw (r/ex-not-found id)))) (catch Exception e - (let [{:keys [status] :as _response} (ex-data e)] - (if (= 404 status) - (throw (r/ex-not-found id)) - (throw e)))))) + (if (r/status-not-found? (ex-data e)) + (throw (r/ex-not-found id)) + (throw (r/ex-unexpected (get-error e))))))) (defn delete-data @@ -144,11 +227,16 @@ response (spandex/request client {:url [index :_doc uuid] :query-string {:refresh true} :method :delete}) +<<<<<<< Updated upstream success? (pos? (get-in response [:body :_shards :successful])) deleted? (= "deleted" (get-in response [:body :result]))] +======= + success? (shards-successful? response) + deleted? (= "deleted" (-> response r/get-body :result))] +>>>>>>> Stashed changes (if (and success? deleted?) (r/response-deleted id) - (r/response-error (str "could not delete document " id))))) + (throw (r/ex-unexpected (str "could not delete document " id)))))) (defn query-data @@ -164,6 +252,7 @@ response (spandex/request client {:url [index :_search] :method :post :body body}) +<<<<<<< Updated upstream success? (-> response :body :_shards :successful pos?) count-before-pagination (-> response :body :hits :total :value) aggregations (-> response :body :aggregations) @@ -171,14 +260,20 @@ aggregations (assoc :aggregations aggregations)) hits (->> response :body :hits :hits (map :_source))] (if success? +======= + body (r/get-body response) + body-hits (:hits body) + count-before-pagination (-> body-hits :total :value) + aggregations (:aggregations body) + meta (cond-> {:count count-before-pagination} + aggregations (assoc :aggregations aggregations)) + hits (->> body-hits :hits (map :_source))] + (if (shards-successful? response) +>>>>>>> Stashed changes [meta hits] - (let [msg (str "error when querying: " (:body response))] - (throw (r/ex-response msg 500))))) + (throw (r/ex-unexpected (str "error when querying: " body))))) (catch Exception e - (let [{:keys [body] :as _response} (ex-data e) - error (:error body) - msg (str "unexpected exception querying: " (or error e))] - (throw (r/ex-response msg 500)))))) + (throw (r/ex-unexpected (str "unexpected exception querying: " (get-error e))))))) (defn bulk-edit-data @@ -197,13 +292,9 @@ success? (-> body-response :failures empty?)] (if success? body-response - (let [msg (str "error when updating by query: " body-response)] - (throw (r/ex-response msg 500))))) + (throw (r/ex-unexpected (str "error when updating by query: " body-response))))) (catch Exception e - (let [{:keys [body] :as _response} (ex-data e) - error (:error body) - msg (str "unexpected exception updating by query: " (or error e))] - (throw (r/ex-response msg 500)))))) + (throw (r/ex-unexpected (str "error when updating by query: " (get-error e))))))) (defn bulk-delete-data [client collection-id {:keys [cimi-params] :as options}] @@ -218,13 +309,9 @@ success? (-> body-response :failures empty?)] (if success? body-response - (let [msg (str "error when deleting by query: " body-response)] - (throw (r/ex-response msg 500))))) + (throw (r/ex-unexpected (str "error when deleting by query: " body-response))))) (catch Exception e - (let [{:keys [body] :as _response} (ex-data e) - error (:error body) - msg (str "unexpected exception delete by query: " (or error e))] - (throw (r/ex-response msg 500)))))) + (throw (r/ex-unexpected (str "error when deleting by query: " (get-error e))))))) (deftype ElasticsearchRestBinding [client sniffer] @@ -236,23 +323,18 @@ (create-index client index) (set-index-mapping client index mapping))) - (add [_ data _options] (add-data client data)) - (add [_ _collection-id data _options] (add-data client data)) - (retrieve [_ id _options] (find-data client id)) - (delete [_ {:keys [id]} _options] (delete-data client id)) - (edit [_ data _options] (update-data client data)) diff --git a/code/src/sixsq/nuvla/server/resources/module.clj b/code/src/sixsq/nuvla/server/resources/module.clj index 13bc9ee0d..8c0472854 100644 --- a/code/src/sixsq/nuvla/server/resources/module.clj +++ b/code/src/sixsq/nuvla/server/resources/module.clj @@ -288,7 +288,7 @@ component, or application. :resource-type resource-type} :body resource) edit-impl)] - (if (r/status-200? response) + (if (r/status-ok? response) response (throw (r/ex-response (str error-message ": " response) 500))))) diff --git a/code/src/sixsq/nuvla/server/util/response.clj b/code/src/sixsq/nuvla/server/util/response.clj index 9cc6f721b..fa3205113 100644 --- a/code/src/sixsq/nuvla/server/util/response.clj +++ b/code/src/sixsq/nuvla/server/util/response.clj @@ -165,6 +165,13 @@ (let [query (str "?error=" (codec/url-encode msg))] (ex-response msg 303 id (str redirect-url query)))) +(defn ex-unexpected + "Provides an ExceptionInfo exception when an unexpected exception happens. + This is a 500 status code. Information from the request and the action + are used to provide a reasonable message." + [msg] + (ex-response (str "unexpected exception: " msg) 500)) + (defn rethrow-response [{{:keys [resource-id status message]} :body :as response}] (if (and (r/response? response) @@ -173,9 +180,22 @@ (let [msg "rethrow-response bad argument"] (throw (ex-info msg (response-error msg)))))) -(defn status-200? +(defn get-status [{:keys [status] :as _response}] - (= status 200)) + status) + +(defn get-body + [{:keys [body] :as _response}] + body) + +(defn status? + [expected-status response] + (= (get-status response) expected-status)) + +(def status-ok? (partial status? 200)) +(def status-created? (partial status? 201)) +(def status-not-found? (partial status? 404)) +(def status-conflict? (partial status? 409)) (defn configurable-check-response [response-ok? on-success on-error] @@ -186,7 +206,7 @@ (def throw-response-not-200 (configurable-check-response - status-200? identity rethrow-response)) + status-ok? identity rethrow-response)) (defn response-body [response] @@ -194,4 +214,4 @@ (def ignore-response-not-200 (configurable-check-response - status-200? identity (constantly nil))) + status-ok? identity (constantly nil))) diff --git a/code/test/sixsq/nuvla/db/binding_lifecycle.clj b/code/test/sixsq/nuvla/db/binding_lifecycle.clj index 56ee6a64d..1a8eaf76f 100644 --- a/code/test/sixsq/nuvla/db/binding_lifecycle.clj +++ b/code/test/sixsq/nuvla/db/binding_lifecycle.clj @@ -4,8 +4,13 @@ [clojure.test :refer [is]] [sixsq.nuvla.auth.utils :as auth] [sixsq.nuvla.db.binding :as db] +<<<<<<< Updated upstream [sixsq.nuvla.db.filter.parser :as parser] [sixsq.nuvla.server.resources.spec.acl-resource :as acl-resource])) +======= + [sixsq.nuvla.server.resources.spec.acl-resource :as acl-resource] + [sixsq.nuvla.server.util.response :as r])) +>>>>>>> Stashed changes (s/def ::id string?) @@ -28,6 +33,13 @@ (def admin-acl {:owners ["group/nuvla-admin"]}) +(defn try-call + [f] + (try + (f) + (catch Exception e + (ex-data e)))) + (defn check-binding-lifecycle [db-impl] (with-open [db db-impl] @@ -43,7 +55,7 @@ my-data-with-acl (assoc my-data :acl admin-acl :more "hi") response (db/add db my-data-with-acl nil)] (is (s/valid? ::resource my-data-with-acl)) - (is (= 201 (:status response))) + (is (r/status-created? response)) (is (= my-id (get-in response [:headers "Location"]))) ;; ensure that the entry can be retrieved @@ -61,7 +73,7 @@ my-data-2-with-acl (assoc my-data-2 :acl admin-acl) response (db/add db my-data-2-with-acl nil)] (is (s/valid? ::resource my-data-2-with-acl)) - (is (= 201 (:status response))) + (is (r/status-created? response)) (is (= my-id-2 (get-in response [:headers "Location"]))) ;; ensure that is can be retrieved (and flush index for elasticsearch) @@ -73,6 +85,7 @@ (is (= 2 (:count query-meta))) (is (= #{my-id my-id-2} (set (map :id query-hits))))) +<<<<<<< Updated upstream ;; adding the same entry again must fail (let [response (db/add db {:id my-id} nil)] (is (= 409 (:status response)))) @@ -81,16 +94,33 @@ (let [updated-data (assoc my-data-with-acl :two "3") response (db/edit db updated-data nil)] (is (= 200 (:status response))) +======= + (testing "adding the same entry again must fail" + (is (r/status-conflict? (try-call #(db/add db {:id my-id} nil))))) + + (testing "update the entry" + (let [updated-data (assoc my-data-with-acl :two "3") + response (db/edit db updated-data nil)] + (is (r/status-ok? response)) +>>>>>>> Stashed changes ;; make sure that the update was applied (let [retrieved-data (db/retrieve db my-id nil)] (is (= updated-data retrieved-data))) +<<<<<<< Updated upstream +======= + (testing "updating the entry by script (partial update)" + (let [options {:doc {:two "4"}} + response (db/scripted-edit db my-id options)] + (is (r/status-ok? response)) +>>>>>>> Stashed changes ;; delete the first entry (let [response (db/delete db updated-data nil)] (is (= 200 (:status response)))) +<<<<<<< Updated upstream ;; delete the second entry (let [response (db/delete db {:id my-id-2} nil)] (is (= 200 (:status response)))) @@ -110,3 +140,23 @@ (catch Exception e (let [response (ex-data e)] (is (= 404 (:status response))))))))))) +======= + (testing "delete the first entry" + (let [response (db/delete db {:id my-id} nil)] + (is (r/status-ok? response)))) + + (testing "updating a deleted entry by script" + (let [options {:doc {:two "4"}}] + (is (r/status-not-found? (try-call #(db/scripted-edit db my-id options)))))) + + (testing "delete the second entry" + (let [response (db/delete db {:id my-id-2} nil)] + (is (r/status-ok? response)))) + + (testing "deleting the first one a second time should give a 404" + (is (r/status-not-found? (try-call #(db/delete db {:id my-id} nil))))) + + (testing "also retrieving it should do the same" + (is (r/status-not-found? (try-call #(db/retrieve db my-id nil)))) + )))))) +>>>>>>> Stashed changes diff --git a/code/test/sixsq/nuvla/server/resources/user_username_password_lifecycle_test.clj b/code/test/sixsq/nuvla/server/resources/user_username_password_lifecycle_test.clj index b3f14c461..0d379a346 100644 --- a/code/test/sixsq/nuvla/server/resources/user_username_password_lifecycle_test.clj +++ b/code/test/sixsq/nuvla/server/resources/user_username_password_lifecycle_test.clj @@ -26,211 +26,210 @@ (deftest lifecycle - (let [template-href (str user-tpl/resource-type "/" username-password/registration-method) - - template-url (str p/service-context template-href) - - session (-> (ltu/ring-app) - session - (content-type "application/json")) - session-admin (header session authn-info-header "group/nuvla-admin group/nuvla-admin group/nuvla-user group/nuvla-anon") - session-user (header session authn-info-header "user/jane user/jane group/nuvla-user group/nuvla-anon") - session-anon (header session authn-info-header "user/unknown user/unknown group/nuvla-anon")] - - #_{:clj-kondo/ignore [:redundant-let]} - (let [template (-> session-admin - (request template-url) - (ltu/body->edn) - (ltu/is-status 200) - (get-in [:response :body])) - - description-attr "description" - tags-attr ["one", "two"] - plaintext-password "Plaintext-password-1" - - no-href-create {:template (ltu/strip-unwanted-attrs (assoc template - :password plaintext-password - :username "alice"))} - href-create {:description description-attr - :tags tags-attr - :template {:href template-href - :password plaintext-password - :username "user/jane"}} - - invalid-create (assoc-in href-create [:template :href] "user-template/unknown-template") - - bad-params-create (assoc-in href-create [:template :invalid] "BAD")] - - - ;; user collection query should succeed but be empty for all users - (doseq [session [session-anon session-user session-admin]] - (-> session - (request (str base-uri "?filter=name!='super'")) - (ltu/body->edn) - (ltu/is-status 200) - (ltu/is-count zero?) - (ltu/is-operation-present :add) - (ltu/is-operation-absent :delete) - (ltu/is-operation-absent :edit))) - - ;; create a new user; fails without reference - (doseq [session [session-anon session-user session-admin]] - (-> session - (request base-uri - :request-method :post - :body (json/write-str no-href-create)) - (ltu/body->edn) - (ltu/is-status 400))) - - ;; create with invalid template fails - (doseq [session [session-anon session-user session-admin]] - (-> session - (request base-uri - :request-method :post - :body (json/write-str invalid-create)) - (ltu/body->edn) - (ltu/is-status 404))) - - ;; create with bad parameters fails - (doseq [session [session-anon session-user session-admin]] - (-> session - (request base-uri - :request-method :post - :body (json/write-str bad-params-create)) - (ltu/body->edn) - (ltu/is-status 400))) - - ;; create user, username-password template is only accessible by admin - (let [resp (-> session-admin - (request base-uri - :request-method :post - :body (json/write-str href-create)) - (ltu/body->edn) - (ltu/is-status 201)) - user-id (get-in resp [:response :body :resource-id]) - - username-id (get-in href-create [:template :username]) - - session-created-user (header session authn-info-header (str user-id " " user-id " group/nuvla-user group/nuvla-anon")) - - {:keys [credential-password] - :as user} (-> session-created-user - (request (str p/service-context user-id)) - (ltu/body->edn) - (ltu/is-status 200) - (get-in [:response :body]))] - - ;; verify the ACL of the user - (let [user-acl (:acl user)] - (is (some #{"group/nuvla-admin"} (:owners user-acl))) - - ;; user should have all rights - (doseq [right [:view-meta :view-data :view-acl - :edit-meta :edit-data :edit-acl - :manage :delete]] - (is (some #{user-id} (right user-acl))))) - - ;; verify name attribute (should default to username) - (is (= "user/jane" (:name user))) - - ; credential password is created and visible by the created user - (-> session-created-user - (request (str p/service-context credential-password)) - (ltu/body->edn) - (ltu/is-status 200)) - (-> session-user - (request (str p/service-context credential-password)) - (ltu/body->edn) - (ltu/is-status 403)) - - ; 1 identifier for the username is visible for the created user; find by identifier - (-> session-created-user - (content-type "application/x-www-form-urlencoded") - (request (str p/service-context user-identifier/resource-type) - :request-method :put - :body (rc/form-encode {:filter (format "identifier='%s'" username-id)})) - (ltu/body->edn) - (ltu/is-status 200) - (ltu/is-count 1)) - - ;; find identifiers by parent - (-> session-created-user + (let [template-href (str user-tpl/resource-type "/" username-password/registration-method) + + template-url (str p/service-context template-href) + + session (-> (ltu/ring-app) + session + (content-type "application/json")) + session-admin (header session authn-info-header "group/nuvla-admin group/nuvla-admin group/nuvla-user group/nuvla-anon") + session-user (header session authn-info-header "user/jane user/jane group/nuvla-user group/nuvla-anon") + session-anon (header session authn-info-header "user/unknown user/unknown group/nuvla-anon") + template (-> session-admin + (request template-url) + (ltu/body->edn) + (ltu/is-status 200) + (get-in [:response :body])) + + description-attr "description" + tags-attr ["one", "two"] + plaintext-password "Plaintext-password-1" + + no-href-create {:template (ltu/strip-unwanted-attrs (assoc template + :password plaintext-password + :username "alice"))} + href-create {:description description-attr + :tags tags-attr + :template {:href template-href + :password plaintext-password + :username "user/jane"}} + + invalid-create (assoc-in href-create [:template :href] "user-template/unknown-template") + + bad-params-create (assoc-in href-create [:template :invalid] "BAD")] + + + ;; user collection query should succeed but be empty for all users + (doseq [session [session-anon session-user session-admin]] + (-> session + (request (str base-uri "?filter=name!='super'")) + (ltu/body->edn) + (ltu/is-status 200) + (ltu/is-count zero?) + (ltu/is-operation-present :add) + (ltu/is-operation-absent :delete) + (ltu/is-operation-absent :edit))) + + ;; create a new user; fails without reference + (doseq [session [session-anon session-user session-admin]] + (-> session + (request base-uri + :request-method :post + :body (json/write-str no-href-create)) + (ltu/body->edn) + (ltu/is-status 400))) + + ;; create with invalid template fails + (doseq [session [session-anon session-user session-admin]] + (-> session + (request base-uri + :request-method :post + :body (json/write-str invalid-create)) + (ltu/body->edn) + (ltu/is-status 404))) + + ;; create with bad parameters fails + (doseq [session [session-anon session-user session-admin]] + (-> session + (request base-uri + :request-method :post + :body (json/write-str bad-params-create)) + (ltu/body->edn) + (ltu/is-status 400))) + + ;; create user, username-password template is only accessible by admin + (let [resp (-> session-admin + (request base-uri + :request-method :post + :body (json/write-str href-create)) + (ltu/body->edn) + (ltu/is-status 201)) + user-id (get-in resp [:response :body :resource-id]) + + username-id (get-in href-create [:template :username]) + + session-created-user (header session authn-info-header (str user-id " " user-id " group/nuvla-user group/nuvla-anon")) + + {:keys [credential-password] + :as user} (-> session-created-user + (request (str p/service-context user-id)) + (ltu/body->edn) + (ltu/is-status 200) + (get-in [:response :body]))] + + ;; verify the ACL of the user + (let [user-acl (:acl user)] + (is (some #{"group/nuvla-admin"} (:owners user-acl))) + + ;; user should have all rights + (doseq [right [:view-meta :view-data :view-acl + :edit-meta :edit-data :edit-acl + :manage :delete]] + (is (some #{user-id} (right user-acl))))) + + ;; verify name attribute (should default to username) + (is (= "user/jane" (:name user))) + + ; credential password is created and visible by the created user + (-> session-created-user + (request (str p/service-context credential-password)) + (ltu/body->edn) + (ltu/is-status 200)) + + (-> session-user + (request (str p/service-context credential-password)) + (ltu/body->edn) + (ltu/is-status 403)) + + ; 1 identifier for the username is visible for the created user; find by identifier + (-> session-created-user + (content-type "application/x-www-form-urlencoded") + (request (str p/service-context user-identifier/resource-type) + :request-method :put + :body (rc/form-encode {:filter (format "identifier='%s'" username-id)})) + (ltu/body->edn) + (ltu/is-status 200) + (ltu/is-count 1)) + + ;; find identifiers by parent + (-> session-created-user + (content-type "application/x-www-form-urlencoded") + (request (str p/service-context user-identifier/resource-type) + :request-method :put + :body (rc/form-encode {:filter (format "parent='%s'" user-id)})) + (ltu/body->edn) + (ltu/is-status 200) + (ltu/is-count 1)) + + (-> session-admin + (request (str p/service-context user-id)) + (ltu/body->edn) + (ltu/is-status 200)) + + (let [{:keys [state]} (-> session-created-user + (request (str p/service-context user-id)) + (ltu/body->edn) + (ltu/body))] + (is (= "ACTIVE" state))) + + ;; try to create a second user with the same identifier + ;; this must fail and all created supporting resources must be cleaned up + (let [resp (-> session-admin + (request base-uri + :request-method :post + :body (json/write-str (assoc-in href-create [:template :username] "user/jane"))) + (ltu/body->edn) + (ltu/is-status 409)) + user-id (ltu/body-resource-id resp)] + + ; no dangling credentials + (-> session-admin (content-type "application/x-www-form-urlencoded") - (request (str p/service-context user-identifier/resource-type) + (request (str p/service-context credential/resource-type) :request-method :put :body (rc/form-encode {:filter (format "parent='%s'" user-id)})) (ltu/body->edn) (ltu/is-status 200) - (ltu/is-count 1)) + (ltu/is-count 0)) + ; no dangling identifiers (-> session-admin - (request (str p/service-context user-id)) - (ltu/body->edn) - (ltu/is-status 200)) - - (let [{:keys [state]} (-> session-created-user - (request (str p/service-context user-id)) - (ltu/body->edn) - (ltu/body))] - (is (= "ACTIVE" state))) - - ;; try to create a second user with the same identifier - ;; this must fail and all created supporting resources must be cleaned up - (let [resp (-> session-admin - (request base-uri - :request-method :post - :body (json/write-str (assoc-in href-create [:template :username] "user/jane"))) - (ltu/body->edn) - (ltu/is-status 409)) - user-id (ltu/body-resource-id resp)] - - ; no dangling credentials - (-> session-admin - (content-type "application/x-www-form-urlencoded") - (request (str p/service-context credential/resource-type) - :request-method :put - :body (rc/form-encode {:filter (format "parent='%s'" user-id)})) - (ltu/body->edn) - (ltu/is-status 200) - (ltu/is-count 0)) - - ; no dangling identifiers - (-> session-admin - (content-type "application/x-www-form-urlencoded") - (request (str p/service-context user-identifier/resource-type) - :request-method :put - :body (rc/form-encode {:filter (format "parent='%s'" user-id)})) - (ltu/body->edn) - (ltu/is-status 200) - (ltu/is-count 0))) - - - ;; user can delete his account - (-> session-created-user - (request (str p/service-context user-id) - :request-method :delete) - (ltu/body->edn) - (ltu/is-status 200)) - - ;; password credential is gone - (-> session-created-user - (request (str p/service-context credential-password)) - (ltu/body->edn) - (ltu/is-status 404)) - - ;; all identifiers pointing to user are gone - (-> session-created-user (content-type "application/x-www-form-urlencoded") (request (str p/service-context user-identifier/resource-type) :request-method :put :body (rc/form-encode {:filter (format "parent='%s'" user-id)})) (ltu/body->edn) (ltu/is-status 200) - (ltu/is-count 0)) - - ;; the user resource is gone as well - (-> session-created-user - (request (str p/service-context user-id)) - (ltu/body->edn) - (ltu/is-status 404)))))) + (ltu/is-count 0))) + + + ;; user can delete his account + (-> session-created-user + (request (str p/service-context user-id) + :request-method :delete) + (ltu/body->edn) + (ltu/is-status 200)) + + ;; password credential is gone + (-> session-created-user + (request (str p/service-context credential-password)) + (ltu/body->edn) + (ltu/is-status 404)) + + ;; all identifiers pointing to user are gone + (-> session-created-user + (content-type "application/x-www-form-urlencoded") + (request (str p/service-context user-identifier/resource-type) + :request-method :put + :body (rc/form-encode {:filter (format "parent='%s'" user-id)})) + (ltu/body->edn) + (ltu/is-status 200) + (ltu/is-count 0)) + + ;; the user resource is gone as well + (-> session-created-user + (request (str p/service-context user-id)) + (ltu/body->edn) + (ltu/is-status 404))))) diff --git a/code/test/sixsq/nuvla/server/util/response_test.clj b/code/test/sixsq/nuvla/server/util/response_test.clj index 1e4bd0721..9896f2dda 100644 --- a/code/test/sixsq/nuvla/server/util/response_test.clj +++ b/code/test/sixsq/nuvla/server/util/response_test.clj @@ -288,7 +288,7 @@ (deftest status-200? (are [expect response] - (= expect (t/status-200? response)) + (= expect (t/status-ok? response)) true {:status 200} false {:status 100} false {:status 201}