mirror of
https://github.com/penpot/penpot.git
synced 2025-07-23 00:27:19 +02:00
♻️ Refactor email validations & tokens service.
This commit is contained in:
parent
dda6a96407
commit
7d9fdc34be
20 changed files with 369 additions and 398 deletions
|
@ -146,10 +146,7 @@
|
|||
on-success identity}} (meta data)]
|
||||
(->> (rp/mutation :register-profile data)
|
||||
(rx/tap on-success)
|
||||
(rx/map #(login data))
|
||||
(rx/catch (fn [err]
|
||||
(on-error err)
|
||||
(rx/empty))))))))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
||||
;; --- Request Account Deletion
|
||||
|
|
|
@ -114,10 +114,7 @@
|
|||
on-success identity}} (meta data)]
|
||||
(->> (rp/mutation :request-email-change data)
|
||||
(rx/tap on-success)
|
||||
(rx/map (constantly fetch-profile))
|
||||
(rx/catch (fn [err]
|
||||
(on-error err)
|
||||
(rx/empty))))))))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
;; --- Cancel Email Change
|
||||
|
||||
|
|
|
@ -9,23 +9,23 @@
|
|||
|
||||
(ns app.main.ui.auth
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[beicon.core :as rx]
|
||||
[rumext.alpha :as mf]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.data.auth :as da]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.auth.login :refer [login-page]]
|
||||
[app.main.ui.auth.recovery :refer [recovery-page]]
|
||||
[app.main.ui.auth.recovery-request :refer [recovery-request-page]]
|
||||
[app.main.ui.auth.register :refer [register-page]]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.timers :as ts]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.forms :as fm]
|
||||
[app.util.i18n :as i18n :refer [tr t]]
|
||||
[app.util.router :as rt]))
|
||||
[app.util.router :as rt]
|
||||
[app.util.timers :as ts]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(mf/defc goodbye-page
|
||||
[{:keys [locale] :as props}]
|
||||
|
@ -50,24 +50,30 @@
|
|||
:auth-recovery [:& recovery-page {:locale locale
|
||||
:params (:query-params route)}])]]))
|
||||
|
||||
(defn- handle-email-verified
|
||||
(defmulti handle-token (fn [token] (:iss token)))
|
||||
|
||||
(defmethod handle-token :verify-email
|
||||
[data]
|
||||
(let [msg (tr "settings.notifications.email-verified-successfully")]
|
||||
(ts/schedule 100 #(st/emit! (dm/success msg)))
|
||||
(st/emit! (rt/nav :settings-profile)
|
||||
du/fetch-profile)))
|
||||
(st/emit! (rt/nav :auth-login))))
|
||||
|
||||
(defn- handle-email-changed
|
||||
(defmethod handle-token :change-email
|
||||
[data]
|
||||
(let [msg (tr "settings.notifications.email-changed-successfully")]
|
||||
(ts/schedule 100 #(st/emit! (dm/success msg)))
|
||||
(st/emit! (rt/nav :settings-profile)
|
||||
du/fetch-profile)))
|
||||
|
||||
(defn- handle-authentication
|
||||
(defmethod handle-token :auth
|
||||
[tdata]
|
||||
(st/emit! (da/login-from-token tdata)))
|
||||
|
||||
(defmethod handle-token :default
|
||||
[tdata]
|
||||
(js/console.log "Unhandled token:" (pr-str tdata))
|
||||
(st/emit! (rt/nav :auth-login)))
|
||||
|
||||
(mf/defc verify-token
|
||||
[{:keys [route] :as props}]
|
||||
(let [token (get-in route [:query-params :token])]
|
||||
|
@ -76,21 +82,22 @@
|
|||
(->> (rp/mutation :verify-profile-token {:token token})
|
||||
(rx/subs
|
||||
(fn [tdata]
|
||||
(case (:type tdata)
|
||||
:verify-email (handle-email-verified tdata)
|
||||
:change-email (handle-email-changed tdata)
|
||||
:authentication (handle-authentication tdata)
|
||||
nil))
|
||||
(handle-token tdata))
|
||||
(fn [error]
|
||||
(case (:code error)
|
||||
:app.services.mutations.profile/email-already-exists
|
||||
:email-already-exists
|
||||
(let [msg (tr "errors.email-already-exists")]
|
||||
(ts/schedule 100 #(st/emit! (dm/error msg)))
|
||||
(st/emit! (rt/nav :settings-profile)))
|
||||
(st/emit! (rt/nav :auth-login)))
|
||||
|
||||
:email-already-validated
|
||||
(let [msg (tr "errors.email-already-validated")]
|
||||
(ts/schedule 100 #(st/emit! (dm/warn msg)))
|
||||
(st/emit! (rt/nav :auth-login)))
|
||||
|
||||
(let [msg (tr "errors.generic")]
|
||||
(ts/schedule 100 #(st/emit! (dm/error msg)))
|
||||
(st/emit! (rt/nav :settings-profile)))))))))
|
||||
(st/emit! (rt/nav :auth-login)))))))))
|
||||
|
||||
[:div.verify-token
|
||||
i/loader-pencil]))
|
||||
|
|
|
@ -9,21 +9,22 @@
|
|||
|
||||
(ns app.main.ui.auth.register
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[app.config :as cfg]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.data.auth :as uda]
|
||||
[app.main.store :as st]
|
||||
[app.main.data.auth :as da]
|
||||
[app.main.data.auth :as uda]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.forms :refer [input submit-button form]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.messages :as msgs]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.forms :as fm]
|
||||
[app.util.i18n :refer [tr t]]
|
||||
[app.util.router :as rt]))
|
||||
|
||||
[app.util.router :as rt]
|
||||
[app.util.timers :as tm]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(mf/defc demo-warning
|
||||
[_]
|
||||
|
@ -43,14 +44,20 @@
|
|||
(defn- on-error
|
||||
[form error]
|
||||
(case (:code error)
|
||||
:app.services.mutations.profile/registration-disabled
|
||||
(st/emit! (tr "errors.registration-disabled"))
|
||||
:registration-disabled
|
||||
(st/emit! (dm/error (tr "errors.registration-disabled")))
|
||||
|
||||
:app.services.mutations.profile/email-already-exists
|
||||
:email-already-exists
|
||||
(swap! form assoc-in [:errors :email]
|
||||
{:message "errors.email-already-exists"})
|
||||
|
||||
(st/emit! (tr "errors.unexpected-error"))))
|
||||
(st/emit! (dm/error (tr "errors.unexpected-error")))))
|
||||
|
||||
(defn- on-success
|
||||
[form data]
|
||||
(let [msg (tr "auth.notifications.validation-email-sent" (:email data))]
|
||||
(st/emit! (rt/nav :auth-login)
|
||||
(dm/success msg))))
|
||||
|
||||
(defn- validate
|
||||
[data]
|
||||
|
@ -61,7 +68,8 @@
|
|||
(defn- on-submit
|
||||
[form event]
|
||||
(let [data (with-meta (:clean-data form)
|
||||
{:on-error (partial on-error form)})]
|
||||
{:on-error (partial on-error form)
|
||||
:on-success (partial on-success form)})]
|
||||
(st/emit! (uda/register data))))
|
||||
|
||||
(mf/defc register-form
|
||||
|
|
|
@ -51,51 +51,33 @@
|
|||
(= "drafts" project-id)
|
||||
(assoc :project-id (:default-project-id profile)))))
|
||||
|
||||
(declare global-notifications)
|
||||
|
||||
|
||||
(mf/defc dashboard
|
||||
[{:keys [route] :as props}]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
page (get-in route [:data :name])
|
||||
{:keys [search-term team-id project-id] :as params}
|
||||
(parse-params route profile)]
|
||||
[:*
|
||||
[:& global-notifications {:profile profile}]
|
||||
[:section.dashboard-layout
|
||||
[:div.main-logo
|
||||
[:a {:on-click #(st/emit! (rt/nav :dashboard-team {:team-id team-id}))}
|
||||
i/logo-icon]]
|
||||
[:& profile-section {:profile profile}]
|
||||
[:& sidebar {:team-id team-id
|
||||
:project-id project-id
|
||||
:section page
|
||||
:search-term search-term}]
|
||||
[:div.dashboard-content
|
||||
(case page
|
||||
:dashboard-search
|
||||
[:& search-page {:team-id team-id :search-term search-term}]
|
||||
page (get-in route [:data :name])
|
||||
{:keys [search-term team-id project-id] :as params} (parse-params route profile)]
|
||||
[:section.dashboard-layout
|
||||
[:div.main-logo
|
||||
[:a {:on-click #(st/emit! (rt/nav :dashboard-team {:team-id team-id}))}
|
||||
i/logo-icon]]
|
||||
[:& profile-section {:profile profile}]
|
||||
[:& sidebar {:team-id team-id
|
||||
:project-id project-id
|
||||
:section page
|
||||
:search-term search-term}]
|
||||
[:div.dashboard-content
|
||||
(case page
|
||||
:dashboard-search
|
||||
[:& search-page {:team-id team-id :search-term search-term}]
|
||||
|
||||
:dashboard-team
|
||||
[:& recent-files-page {:team-id team-id}]
|
||||
:dashboard-team
|
||||
[:& recent-files-page {:team-id team-id}]
|
||||
|
||||
:dashboard-libraries
|
||||
[:& libraries-page {:team-id team-id}]
|
||||
:dashboard-libraries
|
||||
[:& libraries-page {:team-id team-id}]
|
||||
|
||||
:dashboard-project
|
||||
[:& project-page {:team-id team-id
|
||||
:project-id project-id}])]]]))
|
||||
:dashboard-project
|
||||
[:& project-page {:team-id team-id
|
||||
:project-id project-id}])]]))
|
||||
|
||||
|
||||
(mf/defc global-notifications
|
||||
[{:keys [profile] :as props}]
|
||||
(let [locale (mf/deref i18n/locale)]
|
||||
(when (and profile
|
||||
(not= uuid/zero (:id profile))
|
||||
(= (:pending-email profile)
|
||||
(:email profile)))
|
||||
[:section.banner.error.quick
|
||||
[:div.content
|
||||
[:div.icon i/msg-warning]
|
||||
[:span (t locale "settings.notifications.email-not-verified" (:email profile))]]])))
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
(defonce components (atom {}))
|
||||
|
||||
(defn show!
|
||||
([type props]
|
||||
(let [id (random-uuid)]
|
||||
(st/emit! (mdm/show-modal id type props)))))
|
||||
[type props]
|
||||
(let [id (random-uuid)]
|
||||
(st/emit! (mdm/show-modal id type props))))
|
||||
|
||||
(defn allow-click-outside! []
|
||||
(st/emit! (mdm/update-modal {:allow-click-outside true})))
|
||||
|
@ -37,6 +37,8 @@
|
|||
[]
|
||||
(st/emit! (mdm/hide-modal)))
|
||||
|
||||
(def hide (mdm/hide-modal))
|
||||
|
||||
(defn- on-esc-clicked
|
||||
[event]
|
||||
(when (k/esc? event)
|
||||
|
|
|
@ -9,9 +9,7 @@
|
|||
|
||||
(ns app.main.ui.settings.change-email
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.auth :as da]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.users :as du]
|
||||
|
@ -21,12 +19,13 @@
|
|||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.messages :as msgs]
|
||||
[app.main.ui.modal :as modal]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.forms :as fm]
|
||||
[app.util.i18n :as i18n :refer [tr t]]))
|
||||
[app.util.i18n :as i18n :refer [tr t]]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(s/def ::email-1 ::fm/email)
|
||||
(s/def ::email-2 ::fm/email)
|
||||
(s/def ::email-1 ::us/email)
|
||||
(s/def ::email-2 ::us/email)
|
||||
|
||||
(defn- email-equality
|
||||
[data]
|
||||
|
@ -42,7 +41,7 @@
|
|||
(defn- on-error
|
||||
[form error]
|
||||
(cond
|
||||
(= (:code error) :app.services.mutations.profile/email-already-exists)
|
||||
(= (:code error) :email-already-exists)
|
||||
(swap! form (fn [data]
|
||||
(let [error {:message (tr "errors.email-already-exists")}]
|
||||
(assoc-in data [:errors :email-1] error))))
|
||||
|
@ -51,10 +50,16 @@
|
|||
(let [msg (tr "errors.unexpected-error")]
|
||||
(st/emit! (dm/error msg)))))
|
||||
|
||||
(defn- on-success
|
||||
[profile data]
|
||||
(let [msg (tr "auth.notifications.validation-email-sent" (:email profile))]
|
||||
(st/emit! (dm/info msg) modal/hide)))
|
||||
|
||||
(defn- on-submit
|
||||
[form event]
|
||||
[profile form event]
|
||||
(let [data (with-meta {:email (get-in form [:clean-data :email-1])}
|
||||
{:on-error (partial on-error form)})]
|
||||
{:on-error (partial on-error form)
|
||||
:on-success (partial on-success profile)})]
|
||||
(st/emit! (du/request-email-change data))))
|
||||
|
||||
(mf/defc change-email-form
|
||||
|
@ -66,7 +71,7 @@
|
|||
{:type :info
|
||||
:content (t locale "settings.change-email-info" (:email profile))}]
|
||||
|
||||
[:& form {:on-submit on-submit
|
||||
[:& form {:on-submit (partial on-submit profile)
|
||||
:spec ::email-change-form
|
||||
:validators [email-equality]
|
||||
:initial {}}
|
||||
|
@ -83,29 +88,14 @@
|
|||
[:& submit-button
|
||||
{:label (t locale "settings.change-email-submit-label")}]]])
|
||||
|
||||
(mf/defc change-email-confirmation
|
||||
[{:keys [locale profile] :as locale}]
|
||||
[:section.modal-content.generic-form.confirmation
|
||||
[:h2 (t locale "settings.verification-sent-title")]
|
||||
|
||||
|
||||
[:& msgs/inline-banner
|
||||
{:type :info
|
||||
:content (t locale "settings.change-email-info2" (:email profile))}]
|
||||
|
||||
[:button.btn-primary.btn-large
|
||||
{:on-click #(modal/hide!)}
|
||||
(t locale "settings.close-modal-label")]])
|
||||
|
||||
(mf/defc change-email-modal
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :change-email}
|
||||
[props]
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
profile (mf/deref refs/profile)]
|
||||
[:div.modal-overlay
|
||||
[:div.generic-modal.change-email-modal
|
||||
[:span.close {:on-click #(modal/hide!)} i/close]
|
||||
(if (:pending-email profile)
|
||||
[:& change-email-confirmation {:locale locale :profile profile}]
|
||||
[:& change-email-form {:locale locale :profile profile}])]]))
|
||||
[:& change-email-form {:locale locale :profile profile}]]]))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue