From be652b909eeb7736cc660cccbe15ecc2be083e0b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Jul 2023 13:36:14 +0200 Subject: [PATCH] :sparkles: Add stronger validationt to auth/register rpc methods --- backend/src/app/rpc/commands/auth.clj | 74 ++++++++++--------- backend/test/backend_tests/helpers.clj | 9 +++ backend/test/backend_tests/rpc_audit_test.clj | 12 +-- backend/test/backend_tests/rpc_file_test.clj | 5 +- .../test/backend_tests/rpc_profile_test.clj | 2 +- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index cbd8394a5..7281cfed2 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -8,9 +8,10 @@ (:require [app.auth :as auth] [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.exceptions :as ex] [app.common.logging :as l] - [app.common.spec :as us] + [app.common.schema :as sm] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -26,18 +27,13 @@ [app.tokens :as tokens] [app.util.services :as sv] [app.util.time :as dt] - [clojure.spec.alpha :as s] [cuerdas.core :as str])) -(s/def ::email ::us/email) -(s/def ::fullname ::us/not-empty-string) -(s/def ::lang ::us/string) -(s/def ::path ::us/string) -(s/def ::password ::us/not-empty-string) -(s/def ::old-password ::us/not-empty-string) -(s/def ::theme ::us/string) -(s/def ::invitation-token ::us/not-empty-string) -(s/def ::token ::us/not-empty-string) +(def schema:password + [::sm/word-string {:max 500}]) + +(def schema:token + [::sm/word-string {:max 1000}]) ;; ---- COMMAND: login with password @@ -101,22 +97,22 @@ (rph/with-meta {::audit/props (audit/profile->props profile) ::audit/profile-id (:id profile)})))))) -(s/def ::login-with-password - (s/keys :req-un [::email ::password] - :opt-un [::invitation-token])) +(def schema:login-with-password + [:map {:title "login-with-password"} + [:email ::sm/email] + [:password schema:password] + [:invitation-token {:optional true} schema:token]]) (sv/defmethod ::login-with-password "Performs authentication using penpot password." {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:login-with-password} [cfg params] (login-with-password cfg params)) ;; ---- COMMAND: Logout -(s/def ::logout - (s/keys :opt [::rpc/profile-id])) - (sv/defmethod ::logout "Clears the authentication cookie and logout the current session." {::rpc/auth false @@ -141,13 +137,15 @@ (update-password conn)) nil))) -(s/def ::token ::us/not-empty-string) -(s/def ::recover-profile - (s/keys :req-un [::token ::password])) +(def schema:recover-profile + [:map {:title "recover-profile"} + [:token schema:token] + [:password schema:password]]) (sv/defmethod ::recover-profile {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:recover-profile} [cfg params] (recover-profile cfg params)) @@ -228,13 +226,16 @@ (with-meta {:token token} {::audit/profile-id uuid/zero}))) -(s/def ::prepare-register-profile - (s/keys :req-un [::email ::password] - :opt-un [::invitation-token])) +(def schema:prepare-register-profile + [:map {:title "prepare-register-profile"} + [:email ::sm/email] + [:password schema:password] + [:invitation-token {:optional true} schema:token]]) (sv/defmethod ::prepare-register-profile {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:prepare-register-profile} [cfg params] (prepare-register cfg params)) @@ -244,7 +245,7 @@ "Create the profile entry on the database with limited set of input attrs (all the other attrs are filled with default values)." [conn {:keys [email] :as params}] - (us/assert! ::us/email email) + (dm/assert! ::sm/email email) (let [id (or (:id params) (uuid/next)) props (-> (audit/extract-utm-params params) (merge (:props params)) @@ -391,12 +392,16 @@ {::audit/replace-props (audit/profile->props profile) ::audit/profile-id (:id profile)}))))) -(s/def ::register-profile - (s/keys :req-un [::token ::fullname])) + +(def schema:register-profile + [:map {:title "register-profile"} + [:token schema:token] + [:fullname [::sm/word-string {:max 100}]]]) (sv/defmethod ::register-profile {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:register-profile} [{:keys [::db/pool] :as cfg} params] (db/with-atomic [conn pool] (-> (assoc cfg ::db/conn conn) @@ -448,12 +453,15 @@ (create-recovery-token) (send-email-notification conn)))))) -(s/def ::request-profile-recovery - (s/keys :req-un [::email])) + +(def schema:request-profile-recovery + [:map {:title "request-profile-recovery"} + [:email ::sm/email]]) (sv/defmethod ::request-profile-recovery {::rpc/auth false - ::doc/added "1.15"} + ::doc/added "1.15" + ::sm/params schema:request-profile-recovery} [cfg params] (request-profile-recovery cfg params)) diff --git a/backend/test/backend_tests/helpers.clj b/backend/test/backend_tests/helpers.clj index ac8b0ce45..d2edaeec9 100644 --- a/backend/test/backend_tests/helpers.clj +++ b/backend/test/backend_tests/helpers.clj @@ -14,6 +14,7 @@ [app.common.pages :as cp] [app.common.pprint :as pp] [app.common.spec :as us] + [app.common.schema :as sm] [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] @@ -414,6 +415,14 @@ (println (us/pretty-explain data)) + (= :params-validation (:code data)) + (app.common.pprint/pprint + (sm/humanize-data (::sm/explain data))) + + (= :data-validation (:code data)) + (app.common.pprint/pprint + (sm/humanize-data (::sm/explain data))) + (= :service-error (:type data)) (print-error! (.getCause ^Throwable error)) diff --git a/backend/test/backend_tests/rpc_audit_test.clj b/backend/test/backend_tests/rpc_audit_test.clj index df860ca03..233728dac 100644 --- a/backend/test/backend_tests/rpc_audit_test.clj +++ b/backend/test/backend_tests/rpc_audit_test.clj @@ -39,8 +39,8 @@ params {::th/type :push-audit-events ::rpc/profile-id (:id prof) :events [{:name "navigate" - :props {:project-id proj-id - :team-id team-id + :props {:project-id (str proj-id) + :team-id (str team-id) :route "dashboard-files"} :context {:engine "blink"} :profile-id (:id prof) @@ -71,8 +71,8 @@ params {::th/type :push-audit-events ::rpc/profile-id (:id prof) :events [{:name "navigate" - :props {:project-id proj-id - :team-id team-id + :props {:project-id (str proj-id) + :team-id (str team-id) :route "dashboard-files"} :context {:engine "blink"} :profile-id uuid/zero @@ -91,6 +91,8 @@ (t/is (= 1 (count rows))) (t/is (= (:id prof) (:profile-id row))) (t/is (= "navigate" (:name row))) - (t/is (= "frontend" (:source row))))))) + (t/is (= "frontend" (:source row)))) + + ))) diff --git a/backend/test/backend_tests/rpc_file_test.clj b/backend/test/backend_tests/rpc_file_test.clj index 743bbdb40..d39fd2d39 100644 --- a/backend/test/backend_tests/rpc_file_test.clj +++ b/backend/test/backend_tests/rpc_file_test.clj @@ -252,6 +252,7 @@ :components-v2 true :changes changes} out (th/command! params)] + ;; (th/print-result! out) (t/is (nil? (:error out))) (:result out)))] @@ -278,7 +279,7 @@ [{:type :add-obj :page-id page-id :id shid - :parent-id uuid/zero + :parent-id uuid/zero :frame-id uuid/zero :components-v2 true :obj {:id shid @@ -286,7 +287,7 @@ :frame-id uuid/zero :parent-id uuid/zero :type :image - :metadata {:id (:id fmo1)}}}]) + :metadata {:id (:id fmo1) :width 200 :height 200 :mtype "image/jpeg"}}}]) ;; Check that reference storage objects on filemediaobjects ;; are the same because of deduplication feature. diff --git a/backend/test/backend_tests/rpc_profile_test.clj b/backend/test/backend_tests/rpc_profile_test.clj index 846c5e1e9..a28f186c8 100644 --- a/backend/test/backend_tests/rpc_profile_test.clj +++ b/backend/test/backend_tests/rpc_profile_test.clj @@ -278,7 +278,7 @@ (let [error (:error out)] (t/is (th/ex-info? error)) (t/is (th/ex-of-type? error :validation)) - (t/is (th/ex-of-code? error :spec-validation)))) + (t/is (th/ex-of-code? error :params-validation)))) ;; try correct register (let [data {::th/type :register-profile