From 38c9e3e7cc320410367af460a08101f57b3eb5d8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 9 Aug 2024 14:16:16 +0200 Subject: [PATCH 01/12] :bug: Fix error handling issue on login with oidc happens when no oidc backend is configured on backend --- frontend/src/app/main/ui/auth/login.cljs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/main/ui/auth/login.cljs b/frontend/src/app/main/ui/auth/login.cljs index 389a901f5d..26004f0a60 100644 --- a/frontend/src/app/main/ui/auth/login.cljs +++ b/frontend/src/app/main/ui/auth/login.cljs @@ -55,14 +55,15 @@ (.replace js/location redirect-uri) (log/error :hint "unexpected response from OIDC method" :resp (pr-str rsp)))) - (fn [{:keys [type code] :as error}] - (cond - (and (= type :restriction) - (= code :provider-not-configured)) - (st/emit! (msg/error (tr "errors.auth-provider-not-configured"))) + (fn [cause] + (let [{:keys [type code] :as error} (ex-data cause)] + (cond + (and (= type :restriction) + (= code :provider-not-configured)) + (st/emit! (msg/error (tr "errors.auth-provider-not-configured"))) - :else - (st/emit! (msg/error (tr "errors.generic")))))))) + :else + (st/emit! (msg/error (tr "errors.generic"))))))))) (s/def ::email ::us/email) (s/def ::password ::us/not-empty-string) From 314742a563e3891f5876621de927ed0fcb78513f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 12 Aug 2024 11:05:32 +0200 Subject: [PATCH 02/12] :sparkles: Add `:params` prop to `:not-found` exception --- backend/src/app/db.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/app/db.clj b/backend/src/app/db.clj index 097ada50a1..a4e7adb458 100644 --- a/backend/src/app/db.clj +++ b/backend/src/app/db.clj @@ -407,6 +407,7 @@ (ex/raise :type :not-found :code :object-not-found :table table + :params params :hint "database object not found")) row)) From ec56a4149b2b8ca81bbe79c52c1c1f09e23b200d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 12 Aug 2024 11:45:01 +0200 Subject: [PATCH 03/12] :bug: Fix unhandled exception on try to reuse registration token --- backend/src/app/rpc/commands/auth.clj | 38 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index ff8bfdb8f4..268588a0ff 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -355,16 +355,22 @@ profile (if-let [profile-id (:profile-id claims)] (profile/get-profile conn profile-id) - (let [is-active (or (boolean (:is-active claims)) - (not (contains? cf/flags :email-verification))) - params (-> params - (assoc :is-active is-active) - (update :password #(profile/derive-password cfg %)))] - (->> (create-profile! conn params) - (create-profile-rels! conn)))) + ;; NOTE: we first try to match existing profile + ;; by email, that in normal circumstances will + ;; not return anything, but when a user tries to + ;; reuse the same token multiple times, we need + ;; to detect if the profile is already registered + (or (profile/get-profile-by-email conn (:email claims)) + (let [is-active (or (boolean (:is-active claims)) + (not (contains? cf/flags :email-verification))) + params (-> params + (assoc :is-active is-active) + (update :password #(profile/derive-password cfg %))) + profile (->> (create-profile! conn params) + (create-profile-rels! conn))] + (vary-meta profile assoc :created true)))) - ;; When no profile-id comes on claims means a new register - created? (not (:profile-id claims)) + created? (-> profile meta :created true?) invitation (when-let [token (:invitation-token params)] (tokens/verify (::setup/props cfg) {:token token :iss :team-invitation})) @@ -422,13 +428,13 @@ ::audit/profile-id (:id profile)}))) :else - (let [elapsed? (elapsed-verify-threshold? profile) - complaints? (eml/has-reports? conn (:email profile)) - action (if complaints? - "ignore-because-complaints" - (if elapsed? - "resend-email-verification" - "ignore"))] + (let [elapsed? (elapsed-verify-threshold? profile) + reports? (eml/has-reports? conn (:email profile)) + action (if reports? + "ignore-because-complaints" + (if elapsed? + "resend-email-verification" + "ignore"))] (l/wrn :hint "repeated registry detected" :profile-id (str (:id profile)) From e07c1bba7a0764b6e0ce983b4e7d4f4f519ba7ec Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 12 Aug 2024 16:20:26 +0200 Subject: [PATCH 04/12] :bug: Disable ipv6 from docker nginx resolver --- docker/images/files/nginx.conf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docker/images/files/nginx.conf b/docker/images/files/nginx.conf index 8d0fff0a24..fee0e3fca6 100644 --- a/docker/images/files/nginx.conf +++ b/docker/images/files/nginx.conf @@ -38,7 +38,10 @@ http { gzip_types text/plain text/css text/javascript application/javascript application/json application/transit+json; - resolver $PENPOT_INTERNAL_RESOLVER; + proxy_buffer_size 16k; + proxy_busy_buffers_size 24k; # essentially, proxy_buffer_size + 2 small buffers of 4k + proxy_buffers 32 4k; + resolver $PENPOT_INTERNAL_RESOLVER ipv6=off; map $http_upgrade $connection_upgrade { default upgrade; From 91435bf3723277882c30ea5d8ff23ebd81d13af6 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 13 Aug 2024 11:13:09 +0200 Subject: [PATCH 05/12] :bug: Backport storage backend naming changes from develop for properly handle backward comaptibility when two versions are running over a single database --- backend/src/app/main.clj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index a6a2bcebe1..4ec0f18b4f 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -449,7 +449,9 @@ {::db/pool (ig/ref ::db/pool) ::sto/backends {:assets-s3 (ig/ref [::assets :app.storage.s3/backend]) - :assets-fs (ig/ref [::assets :app.storage.fs/backend])}} + :assets-fs (ig/ref [::assets :app.storage.fs/backend]) + :s3 (ig/ref [::assets :app.storage.s3/backend]) + :fs (ig/ref [::assets :app.storage.fs/backend])}} [::assets :app.storage.s3/backend] {::sto.s3/region (cf/get :storage-assets-s3-region) From 6b80f19e5f4cf98df1d3ef63b01a057af42326e9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 13 Aug 2024 12:21:16 +0200 Subject: [PATCH 06/12] :bug: Update storage specs --- backend/src/app/storage.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/app/storage.clj b/backend/src/app/storage.clj index c818b03fa1..9bdb934626 100644 --- a/backend/src/app/storage.clj +++ b/backend/src/app/storage.clj @@ -27,7 +27,7 @@ ;; Storage Module State ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(s/def ::id #{:assets-fs :assets-s3}) +(s/def ::id #{:assets-fs :assets-s3 :s3 :fs}) (s/def ::s3 ::ss3/backend) (s/def ::fs ::sfs/backend) (s/def ::type #{:fs :s3}) From 3df45d697d91214a1b3dd9dfbe136e67cf75dd27 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 14 Aug 2024 11:07:00 +0200 Subject: [PATCH 07/12] :sparkles: Make explicit test-openldap devenv docker ulimits --- docker/devenv/docker-compose.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/devenv/docker-compose.yaml b/docker/devenv/docker-compose.yaml index bd1a3167b3..80252ba16f 100644 --- a/docker/devenv/docker-compose.yaml +++ b/docker/devenv/docker-compose.yaml @@ -125,3 +125,7 @@ services: ports: - "10389:10389" - "10636:10636" + ulimits: + nofile: + soft: "1024" + hard: "1024" \ No newline at end of file From b0af94415fbdb2b5d27748663d74c9078e6c0c41 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Fri, 16 Aug 2024 10:28:01 +0200 Subject: [PATCH 08/12] :tada: Test A/B for starting with light theme --- backend/src/app/rpc/commands/auth.clj | 13 +++++++++---- frontend/src/app/main/data/users.cljs | 4 +++- frontend/src/app/main/ui/auth.cljs | 7 ++++++- frontend/src/app/main/ui/auth/register.cljs | 4 +++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index 268588a0ff..abb0fcf262 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -282,6 +282,7 @@ is-demo (:is-demo params false) is-muted (:is-muted params false) is-active (:is-active params false) + theme (:theme params nil) email (str/lower email) params {:id id @@ -292,6 +293,7 @@ :password password :deleted-at (:deleted-at params) :props props + :theme theme :is-active is-active :is-muted is-muted :is-demo is-demo}] @@ -347,11 +349,13 @@ :extra-data ptoken}))) (defn register-profile - [{:keys [::db/conn] :as cfg} {:keys [token fullname] :as params}] - (let [claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register}) + [{:keys [::db/conn] :as cfg} {:keys [token fullname theme] :as params}] + (let [theme (when (= theme "light") theme) + claims (tokens/verify (::setup/props cfg) {:token token :iss :prepared-register}) params (-> claims (into params) - (assoc :fullname fullname)) + (assoc :fullname fullname) + (assoc :theme theme)) profile (if-let [profile-id (:profile-id claims)] (profile/get-profile conn profile-id) @@ -456,7 +460,8 @@ (def schema:register-profile [:map {:title "register-profile"} [:token schema:token] - [:fullname [::sm/word-string {:max 100}]]]) + [:fullname [::sm/word-string {:max 100}]] + [:theme {:optional true} [:string {:max 10}]]]) (sv/defmethod ::register-profile {::rpc/auth false diff --git a/frontend/src/app/main/data/users.cljs b/frontend/src/app/main/data/users.cljs index 375119931f..fe5f12aba8 100644 --- a/frontend/src/app/main/data/users.cljs +++ b/frontend/src/app/main/data/users.cljs @@ -19,6 +19,7 @@ [app.main.data.websocket :as ws] [app.main.features :as features] [app.main.repo :as rp] + [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] [app.util.router :as rt] [app.util.storage :refer [storage]] @@ -135,7 +136,8 @@ (swap! storage assoc :profile profile) (i18n/set-locale! (:lang profile)) (when (not= previous-email email) - (set-current-team! nil))))))) + (set-current-team! nil)) + (dom/set-html-theme-color (or (:theme profile) "default"))))))) (defn fetch-profile [] diff --git a/frontend/src/app/main/ui/auth.cljs b/frontend/src/app/main/ui/auth.cljs index 4d24070cc3..a47ecd150b 100644 --- a/frontend/src/app/main/ui/auth.cljs +++ b/frontend/src/app/main/ui/auth.cljs @@ -49,11 +49,16 @@ (not= section :auth-register-success)) params (:query-params route) error (:error params) - hide-image-auth? (cf/external-feature-flag "signup-01" "test")] + hide-image-auth? (cf/external-feature-flag "signup-01" "test") + default-light? (cf/external-feature-flag "onboarding-02" "test")] (mf/with-effect [] (dom/set-html-title (tr "title.default"))) + (mf/with-effect [default-light?] + (when default-light? + (dom/set-html-theme-color "light"))) + (mf/with-effect [error] (when error (st/emit! (du/show-redirect-error error)))) diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index f7625c55ed..dff7daa6a5 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -227,6 +227,7 @@ :initial params) submitted? (mf/use-state false) + theme (when (cf/external-feature-flag "onboarding-02" "test") "light") on-success (mf/use-fn @@ -245,7 +246,8 @@ (mf/use-fn (fn [form _] (reset! submitted? true) - (let [params (:clean-data @form)] + (let [params (cond-> (:clean-data @form) + (some? theme) (assoc :theme theme))] (->> (rp/cmd! :register-profile params) (rx/finalize #(reset! submitted? false)) (rx/subs! on-success on-error)))))] From 5efc56eb5a48de690290070271a8ad63e1b00122 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 19 Aug 2024 10:22:01 +0200 Subject: [PATCH 09/12] Revert ":sparkles: Add a/b testing for signup image" This reverts commit 5ac6f0485763cacace119ced31f16bb471193aa2. --- frontend/src/app/main/ui/auth.cljs | 12 ++++-------- frontend/src/app/main/ui/auth.scss | 31 ------------------------------ 2 files changed, 4 insertions(+), 39 deletions(-) diff --git a/frontend/src/app/main/ui/auth.cljs b/frontend/src/app/main/ui/auth.cljs index a47ecd150b..c9773fee9f 100644 --- a/frontend/src/app/main/ui/auth.cljs +++ b/frontend/src/app/main/ui/auth.cljs @@ -49,7 +49,6 @@ (not= section :auth-register-success)) params (:query-params route) error (:error params) - hide-image-auth? (cf/external-feature-flag "signup-01" "test") default-light? (cf/external-feature-flag "onboarding-02" "test")] (mf/with-effect [] @@ -63,17 +62,14 @@ (when error (st/emit! (du/show-redirect-error error)))) - [:main {:class (stl/css-case :auth-section (not hide-image-auth?) - :auth-section-hide-image hide-image-auth?)} + [:main {:class (stl/css :auth-section)} (when show-login-icon [:h1 {:class (stl/css :logo-container)} [:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]) - (when (not hide-image-auth?) - [:div {:class (stl/css :login-illustration)} - i/login-illustration]) + [:div {:class (stl/css :login-illustration)} + i/login-illustration] - [:section {:class (stl/css-case :auth-content (not hide-image-auth?) - :auth-content-hide-image hide-image-auth?)} + [:section {:class (stl/css :auth-content)} (case section :auth-register diff --git a/frontend/src/app/main/ui/auth.scss b/frontend/src/app/main/ui/auth.scss index ff1a096a7b..8f7e2087db 100644 --- a/frontend/src/app/main/ui/auth.scss +++ b/frontend/src/app/main/ui/auth.scss @@ -24,24 +24,6 @@ } } -// A-B text signup-01 -.auth-section-hide-image { - position: relative; - align-items: center; - background: var(--panel-background-color); - display: grid; - gap: $s-32; - height: 100%; - padding: $s-32; - width: 100%; - overflow: auto; - - @media (max-width: 992px) { - display: flex; - justify-content: center; - } -} - .logo-container { position: absolute; top: $s-20; @@ -83,19 +65,6 @@ width: 100%; } -// A-B text signup-01 -.auth-content-hide-image { - display: grid; - grid-template-rows: 1fr auto; - gap: $s-24; - height: fit-content; - margin: auto; - max-width: $s-412; - padding-block-end: $s-8; - position: relative; - width: 100%; -} - .logo-btn { svg { width: $s-120; From cd51f2f6522cf763229d480ee67874241168bc1b Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 19 Aug 2024 15:42:54 +0200 Subject: [PATCH 10/12] :sparkles: Improve disabled registry flows --- CHANGES.md | 6 ++ backend/src/app/rpc/commands/auth.clj | 9 +- backend/src/app/rpc/commands/verify_token.clj | 18 ++-- .../test/backend_tests/rpc_profile_test.clj | 91 +++++++++++++++---- frontend/src/app/main/ui/auth/register.cljs | 3 +- version.txt | 2 +- 6 files changed, 99 insertions(+), 30 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5544b031e2..0aa485362f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,12 @@ ### :bug: Bugs fixed +- Don't allow registry with email and password, if password login is disabled (invitation workflow) [Github #4975](https://github.com/penpot/penpot/issues/4975) + +## 2.1.2 + +### :bug: Bugs fixed + - User switch language to "zh_hant" will get 400 [Github #4884](https://github.com/penpot/penpot/issues/4884) - Smtp config ignoring port if ssl is set [Github #4872](https://github.com/penpot/penpot/issues/4872) - Ability to let users to authenticate with a private oidc provider only [Github #4963](https://github.com/penpot/penpot/issues/4963) diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index abb0fcf262..33cf52b7d5 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -180,10 +180,11 @@ (defn- validate-register-attempt! [cfg params] - (when-not (contains? cf/flags :registration) - (when-not (contains? params :invitation-token) - (ex/raise :type :restriction - :code :registration-disabled))) + (when (or + (not (contains? cf/flags :registration)) + (not (contains? cf/flags :login-with-password))) + (ex/raise :type :restriction + :code :registration-disabled)) (when (contains? params :invitation-token) (let [invitation (tokens/verify (::setup/props cfg) diff --git a/backend/src/app/rpc/commands/verify_token.clj b/backend/src/app/rpc/commands/verify_token.clj index 14c9024bc8..a5c96ddd8f 100644 --- a/backend/src/app/rpc/commands/verify_token.clj +++ b/backend/src/app/rpc/commands/verify_token.clj @@ -8,6 +8,7 @@ (:require [app.common.exceptions :as ex] [app.common.spec :as us] + [app.config :as cf] [app.db :as db] [app.db.sql :as-alias sql] [app.http.session :as session] @@ -152,11 +153,12 @@ (us/verify! ::team-invitation-claims claims) - (let [invitation (db/get* conn :team-invitation - {:team-id team-id :email-to member-email}) - profile (db/get* conn :profile - {:id profile-id} - {:columns [:id :email]})] + (let [invitation (db/get* conn :team-invitation + {:team-id team-id :email-to member-email}) + profile (db/get* conn :profile + {:id profile-id} + {:columns [:id :email]}) + registration-disabled? (not (contains? cf/flags :registration))] (when (nil? invitation) (ex/raise :type :validation :code :invalid-token @@ -185,12 +187,12 @@ :hint "logged-in user does not matches the invitation")) ;; If we have not logged-in user, and invitation comes with member-id we - ;; redirect user to login, if no memeber-id is present in the invitation - ;; token, we redirect user the the register page. + ;; redirect user to login, if no memeber-id is present and in the invitation + ;; token and registration is enabled, we redirect user the the register page. {:invitation-token token :iss :team-invitation - :redirect-to (if member-id :auth-login :auth-register) + :redirect-to (if (or member-id registration-disabled?) :auth-login :auth-register) :state :pending}))) ;; --- Default diff --git a/backend/test/backend_tests/rpc_profile_test.clj b/backend/test/backend_tests/rpc_profile_test.clj index 7a90c9a817..1bd49db485 100644 --- a/backend/test/backend_tests/rpc_profile_test.clj +++ b/backend/test/backend_tests/rpc_profile_test.clj @@ -505,6 +505,54 @@ (t/is (nil? (:error out))) (t/is (= 0 (:call-count @mock)))))))) +(t/deftest prepare-and-register-with-invitation-and-enabled-registration-1 + (let [sprops (:app.setup/props th/*system*) + itoken (tokens/generate sprops + {:iss :team-invitation + :exp (dt/in-future "48h") + :role :editor + :team-id uuid/zero + :member-email "user@example.com"}) + data {::th/type :prepare-register-profile + :invitation-token itoken + :email "user@example.com" + :password "foobar"} + + {:keys [result error] :as out} (th/command! data)] + (t/is (nil? error)) + (t/is (map? result)) + (t/is (string? (:token result))) + + (let [rtoken (:token result) + data {::th/type :register-profile + :token rtoken + :fullname "foobar"} + + {:keys [result error] :as out} (th/command! data)] + ;; (th/print-result! out) + (t/is (nil? error)) + (t/is (map? result)) + (t/is (string? (:invitation-token result)))))) + +(t/deftest prepare-and-register-with-invitation-and-enabled-registration-2 + (let [sprops (:app.setup/props th/*system*) + itoken (tokens/generate sprops + {:iss :team-invitation + :exp (dt/in-future "48h") + :role :editor + :team-id uuid/zero + :member-email "user2@example.com"}) + + data {::th/type :prepare-register-profile + :invitation-token itoken + :email "user@example.com" + :password "foobar"} + out (th/command! data)] + + (t/is (not (th/success? out))) + (let [edata (-> out :error ex-data)] + (t/is (= :restriction (:type edata))) + (t/is (= :email-does-not-match-invitation (:code edata)))))) (t/deftest prepare-and-register-with-invitation-and-disabled-registration-1 (with-redefs [app.config/flags [:disable-registration]] @@ -519,22 +567,12 @@ :invitation-token itoken :email "user@example.com" :password "foobar"} + out (th/command! data)] - {:keys [result error] :as out} (th/command! data)] - (t/is (nil? error)) - (t/is (map? result)) - (t/is (string? (:token result))) - - (let [rtoken (:token result) - data {::th/type :register-profile - :token rtoken - :fullname "foobar"} - - {:keys [result error] :as out} (th/command! data)] - ;; (th/print-result! out) - (t/is (nil? error)) - (t/is (map? result)) - (t/is (string? (:invitation-token result))))))) + (t/is (not (th/success? out))) + (let [edata (-> out :error ex-data)] + (t/is (= :restriction (:type edata))) + (t/is (= :registration-disabled (:code edata))))))) (t/deftest prepare-and-register-with-invitation-and-disabled-registration-2 (with-redefs [app.config/flags [:disable-registration]] @@ -555,7 +593,28 @@ (t/is (not (th/success? out))) (let [edata (-> out :error ex-data)] (t/is (= :restriction (:type edata))) - (t/is (= :email-does-not-match-invitation (:code edata))))))) + (t/is (= :registration-disabled (:code edata))))))) + +(t/deftest prepare-and-register-with-invitation-and-disabled-login-with-password + (with-redefs [app.config/flags [:disable-login-with-password]] + (let [sprops (:app.setup/props th/*system*) + itoken (tokens/generate sprops + {:iss :team-invitation + :exp (dt/in-future "48h") + :role :editor + :team-id uuid/zero + :member-email "user2@example.com"}) + + data {::th/type :prepare-register-profile + :invitation-token itoken + :email "user@example.com" + :password "foobar"} + out (th/command! data)] + + (t/is (not (th/success? out))) + (let [edata (-> out :error ex-data)] + (t/is (= :restriction (:type edata))) + (t/is (= :registration-disabled (:code edata))))))) (t/deftest prepare-register-with-registration-disabled (with-redefs [app.config/flags #{}] diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index dff7daa6a5..6c0ba1a19a 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -136,7 +136,8 @@ (when login/show-alt-login-buttons? [:& login/login-buttons {:params params}]) [:hr {:class (stl/css :separator)}] - [:& register-form {:params params :on-success-callback on-success-callback}]]) + (when (contains? cf/flags :login-with-password) + [:& register-form {:params params :on-success-callback on-success-callback}])]) (mf/defc register-page {::mf/props :obj} diff --git a/version.txt b/version.txt index eca07e4c1a..ac2cdeba01 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.1.2 +2.1.3 From c86afca1d050614bbe9ff9f3cc7e9142ecf12812 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 16 Aug 2024 12:48:03 +0200 Subject: [PATCH 11/12] :bug: Fix deleted fonts on file load --- frontend/src/app/main/data/workspace.cljs | 2 - .../data/workspace/fix_bool_contents.cljs | 95 ------------ .../data/workspace/fix_deleted_fonts.cljs | 146 +++++++++--------- 3 files changed, 74 insertions(+), 169 deletions(-) delete mode 100644 frontend/src/app/main/data/workspace/fix_bool_contents.cljs diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 5faee0a0c7..f2cafd5de1 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -47,7 +47,6 @@ [app.main.data.workspace.collapse :as dwco] [app.main.data.workspace.drawing :as dwd] [app.main.data.workspace.edition :as dwe] - [app.main.data.workspace.fix-bool-contents :as fbc] [app.main.data.workspace.fix-broken-shapes :as fbs] [app.main.data.workspace.fix-deleted-fonts :as fdf] [app.main.data.workspace.groups :as dwg] @@ -129,7 +128,6 @@ (when (and (not (boolean (-> state :profile :props :v2-info-shown))) (features/active-feature? state "components/v2")) (modal/show :v2-info {})) - (fbc/fix-bool-contents) (fdf/fix-deleted-fonts) (fbs/fix-broken-shapes))))) diff --git a/frontend/src/app/main/data/workspace/fix_bool_contents.cljs b/frontend/src/app/main/data/workspace/fix_bool_contents.cljs deleted file mode 100644 index 5cb1c493af..0000000000 --- a/frontend/src/app/main/data/workspace/fix_bool_contents.cljs +++ /dev/null @@ -1,95 +0,0 @@ -;; 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 - -(ns app.main.data.workspace.fix-bool-contents - (:require - [app.common.data :as d] - [app.common.geom.shapes :as gsh] - [app.main.data.changes :as dch] - [app.main.data.workspace.shapes :as dwsh] - [app.main.data.workspace.state-helpers :as wsh] - [beicon.v2.core :as rx] - [potok.v2.core :as ptk])) - -;; This event will update the file so the boolean data has a pre-generated path data -;; to increase performance. -;; For new shapes this will be generated in the :reg-objects but we need to do this for -;; old files. - -;; FIXME: Remove me after June 2022 - -(defn fix-bool-contents - "This event will calculate the bool content and update the page. This is kind of a 'addhoc' migration - to fill the optional value 'bool-content'" - [] - - (letfn [(should-migrate-shape? [shape] - (and (= :bool (:type shape)) (not (contains? shape :bool-content)))) - - (should-migrate-component? [component] - (->> (:objects component) - (vals) - (d/seek should-migrate-shape?))) - - (update-shape [shape objects] - (cond-> shape - (should-migrate-shape? shape) - (assoc :bool-content (gsh/calc-bool-content shape objects)))) - - (migrate-component [component] - (-> component - (update - :objects - (fn [objects] - (d/mapm #(update-shape %2 objects) objects))))) - - (update-library - [library] - (-> library - (d/update-in-when - [:data :components] - (fn [components] - (d/mapm #(migrate-component %2) components)))))] - - (ptk/reify ::fix-bool-contents - ptk/UpdateEvent - (update [_ state] - ;; Update (only-local) the imported libraries - (-> state - (d/update-when - :workspace-libraries - (fn [libraries] (d/mapm #(update-library %2) libraries))))) - - ptk/WatchEvent - (watch [it state _] - (let [objects (wsh/lookup-page-objects state) - - ids (into #{} - (comp (filter should-migrate-shape?) (map :id)) - (vals objects)) - - components (->> (wsh/lookup-local-components state) - (vals) - (filter should-migrate-component?)) - - component-changes - (into [] - (map (fn [component] - {:type :mod-component - :id (:id component) - :objects (-> component migrate-component :objects)})) - components)] - - (rx/of (dwsh/update-shapes ids #(update-shape % objects) {:reg-objects? false - :save-undo? false - :ignore-tree true})) - - (if (empty? component-changes) - (rx/empty) - (rx/of (dch/commit-changes {:origin it - :redo-changes component-changes - :undo-changes [] - :save-undo? false})))))))) diff --git a/frontend/src/app/main/data/workspace/fix_deleted_fonts.cljs b/frontend/src/app/main/data/workspace/fix_deleted_fonts.cljs index f79db68675..75f7c83d2f 100644 --- a/frontend/src/app/main/data/workspace/fix_deleted_fonts.cljs +++ b/frontend/src/app/main/data/workspace/fix_deleted_fonts.cljs @@ -6,11 +6,9 @@ (ns app.main.data.workspace.fix-deleted-fonts (:require - [app.common.data :as d] [app.common.files.helpers :as cfh] [app.common.text :as txt] [app.main.data.changes :as dwc] - [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.state-helpers :as wsh] [app.main.fonts :as fonts] [beicon.v2.core :as rx] @@ -22,14 +20,7 @@ ;; - Moving files from one team to another in the same instance ;; - Custom fonts are explicitly deleted in the team area -(defn has-invalid-font-family - [node] - (let [fonts (deref fonts/fontsdb)] - (and - (some? (:font-family node)) - (nil? (get fonts (:font-id node)))))) - -(defn calculate-alternative-font-id +(defn- calculate-alternative-font-id [value] (let [fonts (deref fonts/fontsdb)] (->> (vals fonts) @@ -37,39 +28,44 @@ (first) :id))) -(defn should-fix-deleted-font-shape? +(defn- has-invalid-font-family? + [node] + (let [fonts (deref fonts/fontsdb) + font-family (:font-family node) + alternative-font-id (calculate-alternative-font-id font-family)] + (and (some? font-family) + (nil? (get fonts (:font-id node))) + (some? alternative-font-id)))) + +(defn- should-fix-deleted-font-shape? [shape] (let [text-nodes (txt/node-seq txt/is-text-node? (:content shape))] - (and (cfh/text-shape? shape) (some has-invalid-font-family text-nodes)))) + (and (cfh/text-shape? shape) + (some has-invalid-font-family? text-nodes)))) -(defn should-fix-deleted-font-component? +(defn- should-fix-deleted-font-component? [component] - (->> (:objects component) - (vals) - (d/seek should-fix-deleted-font-shape?))) + (let [xf (comp (map val) + (filter should-fix-deleted-font-shape?))] + (first (sequence xf (:objects component))))) -(defn should-fix-deleted-font-typography? - [typography] - (let [fonts (deref fonts/fontsdb)] - (nil? (get fonts (:font-id typography))))) - -(defn fix-deleted-font +(defn- fix-deleted-font [node] (let [alternative-font-id (calculate-alternative-font-id (:font-family node))] (cond-> node (some? alternative-font-id) (assoc :font-id alternative-font-id)))) -(defn fix-deleted-font-shape +(defn- fix-deleted-font-shape [shape] - (let [transform (partial txt/transform-nodes has-invalid-font-family fix-deleted-font)] + (let [transform (partial txt/transform-nodes has-invalid-font-family? fix-deleted-font)] (update shape :content transform))) -(defn fix-deleted-font-component +(defn- fix-deleted-font-component [component] (update component :objects (fn [objects] - (d/mapm #(fix-deleted-font-shape %2) objects)))) + (update-vals objects fix-deleted-font-shape)))) (defn fix-deleted-font-typography [typography] @@ -77,54 +73,60 @@ (cond-> typography (some? alternative-font-id) (assoc :font-id alternative-font-id)))) +(defn- generate-deleted-font-shape-changes + [{:keys [objects id]}] + (sequence + (comp (map val) + (filter should-fix-deleted-font-shape?) + (map (fn [shape] + {:type :mod-obj + :id (:id shape) + :page-id id + :operations [{:type :set + :attr :content + :val (:content (fix-deleted-font-shape shape))} + {:type :set + :attr :position-data + :val nil}]}))) + objects)) + +(defn- generate-deleted-font-components-changes + [state] + (sequence + (comp (map val) + (filter should-fix-deleted-font-component?) + (map (fn [component] + {:type :mod-component + :id (:id component) + :objects (-> (fix-deleted-font-component component) :objects)}))) + (wsh/lookup-local-components state))) + +(defn- generate-deleted-font-typography-changes + [state] + (sequence + (comp (map val) + (filter has-invalid-font-family?) + (map (fn [typography] + {:type :mod-typography + :typography (fix-deleted-font-typography typography)}))) + (get-in state [:workspace-data :typographies]))) + (defn fix-deleted-fonts [] (ptk/reify ::fix-deleted-fonts ptk/WatchEvent (watch [it state _] - (let [objects (wsh/lookup-page-objects state) - - ids (into #{} - (comp (filter should-fix-deleted-font-shape?) (map :id)) - (vals objects)) - - components (->> (wsh/lookup-local-components state) - (vals) - (filter should-fix-deleted-font-component?)) - - component-changes - (into [] - (map (fn [component] - {:type :mod-component - :id (:id component) - :objects (-> (fix-deleted-font-component component) :objects)})) - components) - - typographies (->> (get-in state [:workspace-data :typographies]) - (vals) - (filter should-fix-deleted-font-typography?)) - - typography-changes - (into [] - (map (fn [typography] - {:type :mod-typography - :typography (fix-deleted-font-typography typography)})) - typographies)] - - (rx/concat - (rx/of (dwsh/update-shapes ids #(fix-deleted-font-shape %) {:reg-objects? false - :save-undo? false - :ignore-tree true})) - (if (empty? component-changes) - (rx/empty) - (rx/of (dwc/commit-changes {:origin it - :redo-changes component-changes - :undo-changes [] - :save-undo? false}))) - - (if (empty? typography-changes) - (rx/empty) - (rx/of (dwc/commit-changes {:origin it - :redo-changes typography-changes - :undo-changes [] - :save-undo? false})))))))) + (let [data (get state :workspace-data) + shape-changes (mapcat generate-deleted-font-shape-changes (vals (:pages-index data))) + components-changes (generate-deleted-font-components-changes state) + typography-changes (generate-deleted-font-typography-changes state) + changes (concat shape-changes + components-changes + typography-changes)] + (if (seq changes) + (rx/of (dwc/commit-changes + {:origin it + :redo-changes (vec changes) + :undo-changes [] + :save-undo? false})) + (rx/empty)))))) From df255b5a6f64d031b223ba8f356ed28454ed0e20 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 22 Aug 2024 15:09:57 +0200 Subject: [PATCH 12/12] :bug: Fix render of some texts without position data --- .../shapes/text/viewport_texts_html.cljs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs index 681dffd372..3879ba5072 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs @@ -64,24 +64,25 @@ [{:keys [grow-type id migrate] :as shape} node] ;; Check if we need to update the size because it's auto-width or auto-height ;; Update the position-data of every text fragment - (p/let [position-data (tsp/calc-position-data id)] - ;; At least one paragraph needs to be inside the bounding box - (when (gsht/overlaps-position-data? shape position-data) - (st/emit! (dwt/update-position-data id position-data))) + (->> (tsp/calc-position-data id) + (p/fmap (fn [position-data] + ;; At least one paragraph needs to be inside the bounding box + (when (gsht/overlaps-position-data? shape position-data) + (st/emit! (dwt/update-position-data id position-data))) - (when (contains? #{:auto-height :auto-width} grow-type) - (let [{:keys [width height]} - (-> (dom/query node ".paragraph-set") - (dom/get-bounding-rect)) + (when (contains? #{:auto-height :auto-width} grow-type) + (let [{:keys [width height]} + (-> (dom/query node ".paragraph-set") + (dom/get-bounding-rect)) - width (mth/ceil width) - height (mth/ceil height)] - (when (and (not (mth/almost-zero? width)) - (not (mth/almost-zero? height)) - (not migrate)) - (st/emit! (dwt/resize-text id width height))))) + width (mth/ceil width) + height (mth/ceil height)] + (when (and (not (mth/almost-zero? width)) + (not (mth/almost-zero? height)) + (not migrate)) + (st/emit! (dwt/resize-text id width height))))) - (st/emit! (dwt/clean-text-modifier id)))) + (st/emit! (dwt/clean-text-modifier id)))))) (defn- update-text-modifier [{:keys [grow-type id] :as shape} node]