From 188a9cb29e2ceed7b08e160aec0436b1803be06f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 17 Aug 2026 12:01:49 +0000 Subject: [PATCH] :zap: Optimize demo user setup for performance tests Use UUID-based demo emails to prevent concurrent profile collisions.\nUse fast PBKDF2 hashing for demo profiles while keeping regular user hashing unchanged.\nAdd focused coverage for hashing, email uniqueness, and the feature flag.\n\nAI-assisted-by: gpt-5.6-luna --- backend/src/app/auth.clj | 9 +++++ backend/src/app/rpc/commands/demo.clj | 10 ++--- backend/test/backend_tests/rpc_demo_test.clj | 40 ++++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 backend/test/backend_tests/rpc_demo_test.clj diff --git a/backend/src/app/auth.clj b/backend/src/app/auth.clj index 1f978f357c..11347e6908 100644 --- a/backend/src/app/auth.clj +++ b/backend/src/app/auth.clj @@ -14,10 +14,19 @@ :iterations 3 :parallelism 2}) +(def ^:private weak-options + {:alg :pbkdf2+sha256 + :iterations 100}) + (defn derive-password [password] (hashers/derive password default-options)) +(defn derive-password-weak + "Derives a password with a fast algorithm for demo users." + [password] + (hashers/derive password weak-options)) + (defn verify-password [attempt password] (try diff --git a/backend/src/app/rpc/commands/demo.clj b/backend/src/app/rpc/commands/demo.clj index 13b7a2f374..fd0a71149f 100644 --- a/backend/src/app/rpc/commands/demo.clj +++ b/backend/src/app/rpc/commands/demo.clj @@ -7,9 +7,10 @@ (ns app.rpc.commands.demo "A demo specific mutations." (:require - [app.auth :refer [derive-password]] + [app.auth :refer [derive-password-weak]] [app.common.exceptions :as ex] [app.common.time :as ct] + [app.common.uuid :as uuid] [app.config :as cf] [app.db :as db] [app.loggers.audit :as audit] @@ -34,8 +35,8 @@ :code :demo-users-not-allowed :hint "Demo users are disabled by config.")) - (let [sem (System/currentTimeMillis) - email (str "demo-" sem ".demo@example.com") + (let [sem (uuid/next) + email (str "demo-" sem "@demo.example.com") fullname (str "Demo User " sem) password (-> (bn/random-bytes 16) @@ -47,7 +48,7 @@ :is-active true :is-demo true :deleted-at (ct/in-future (cf/get-deletion-delay)) - :password (derive-password password) + :password (derive-password-weak password) :props {}} profile (db/tx-run! cfg (fn [cfg] (->> (auth/create-profile cfg params) @@ -55,4 +56,3 @@ (with-meta {:email email :password password} {::audit/profile-id (:id profile)}))) - diff --git a/backend/test/backend_tests/rpc_demo_test.clj b/backend/test/backend_tests/rpc_demo_test.clj new file mode 100644 index 0000000000..d990ec8a32 --- /dev/null +++ b/backend/test/backend_tests/rpc_demo_test.clj @@ -0,0 +1,40 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC Sucursal en EspaƱa SL + +(ns backend-tests.rpc-demo-test + (:require + [app.auth :as auth] + [app.config :as cf] + [backend-tests.helpers :as th] + [clojure.test :as t])) + +(t/use-fixtures :once th/state-init) +(t/use-fixtures :each th/database-reset) + +;; Capture the real verifier before the shared test fixture replaces it. +(def verify-password* auth/verify-password) + +(t/deftest weak-password-hash-verifies + (let [password "DemoPassword123!" + hashed (auth/derive-password-weak password)] + (t/is (:valid (verify-password* password hashed))))) + +(t/deftest create-demo-profile-uses-unique-uuid-email + (with-redefs [cf/flags (conj cf/flags :demo-users)] + (let [first-result (th/command! {::th/type :create-demo-profile}) + second-result (th/command! {::th/type :create-demo-profile}) + first-profile (:result first-result) + second-profile (:result second-result)] + (t/is (nil? (:error first-result))) + (t/is (nil? (:error second-result))) + (t/is (re-matches #"demo-[0-9a-fA-F-]+@demo\.example\.com" + (:email first-profile))) + (t/is (not= (:email first-profile) (:email second-profile)))))) + +(t/deftest create-demo-profile-requires-feature-flag + (with-redefs [cf/flags (disj cf/flags :demo-users)] + (let [{:keys [error]} (th/command! {::th/type :create-demo-profile})] + (t/is (th/ex-of-code? error :demo-users-not-allowed)))))