mirror of
https://github.com/penpot/penpot.git
synced 2025-05-29 09:06:12 +02:00
✨ Allow repeated registers after small delay
Helps users with expired tokens proceed with a new register
This commit is contained in:
parent
395a7096bf
commit
37e2fe5c65
10 changed files with 487 additions and 293 deletions
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.rpc.commands.auth
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
|
@ -184,8 +185,9 @@
|
|||
|
||||
;; ---- COMMAND: Prepare Register
|
||||
|
||||
(defn prepare-register
|
||||
[{:keys [pool sprops] :as cfg} params]
|
||||
(defn validate-register-attempt!
|
||||
[{:keys [pool sprops]} params]
|
||||
|
||||
(when-not (contains? cf/flags :registration)
|
||||
(if-not (contains? params :invitation-token)
|
||||
(ex/raise :type :restriction
|
||||
|
@ -208,20 +210,46 @@
|
|||
:code :email-has-permanent-bounces
|
||||
:hint "looks like the email has one or many bounces reported"))
|
||||
|
||||
(check-profile-existence! pool params)
|
||||
|
||||
;; Perform a basic validation of email & password
|
||||
(when (= (str/lower (:email params))
|
||||
(str/lower (:password params)))
|
||||
(ex/raise :type :validation
|
||||
:code :email-as-password
|
||||
:hint "you can't use your email as password"))
|
||||
:hint "you can't use your email as password")))
|
||||
|
||||
(let [params {:email (:email params)
|
||||
:password (:password params)
|
||||
:invitation-token (:invitation-token params)
|
||||
:backend "penpot"
|
||||
:iss :prepared-register
|
||||
:exp (dt/in-future "48h")}
|
||||
(def register-retry-threshold
|
||||
(dt/duration "15m"))
|
||||
|
||||
(defn- elapsed-register-retry-threshold?
|
||||
[profile]
|
||||
(let [elapsed (dt/diff (:modified-at profile) (dt/now))]
|
||||
(pos? (compare elapsed register-retry-threshold))))
|
||||
|
||||
(defn prepare-register
|
||||
[{:keys [pool sprops] :as cfg} params]
|
||||
|
||||
(validate-register-attempt! cfg params)
|
||||
|
||||
(let [profile (when-let [profile (profile/retrieve-profile-data-by-email pool (:email params))]
|
||||
(if (:is-active profile)
|
||||
(ex/raise :type :validation
|
||||
:code :email-already-exists
|
||||
:hint "profile already exists and correctly validated")
|
||||
(if (elapsed-register-retry-threshold? profile)
|
||||
profile
|
||||
(ex/raise :type :validation
|
||||
:code :email-already-exists
|
||||
:hint "profile already exists"))))
|
||||
|
||||
params {:email (:email params)
|
||||
:password (:password params)
|
||||
:invitation-token (:invitation-token params)
|
||||
:backend "penpot"
|
||||
:iss :prepared-register
|
||||
:profile-id (:id profile)
|
||||
:exp (dt/in-future {:days 7})}
|
||||
|
||||
params (d/without-nils params)
|
||||
|
||||
token (tokens/generate sprops params)]
|
||||
(with-meta {:token token}
|
||||
|
@ -240,11 +268,10 @@
|
|||
;; ---- COMMAND: Register Profile
|
||||
|
||||
(defn create-profile
|
||||
"Create the profile entry on the database with limited input filling
|
||||
all the other fields with defaults."
|
||||
"Create the profile entry on the database with limited set of input
|
||||
attrs (all the other attrs are filled with default values)."
|
||||
[conn params]
|
||||
(let [id (or (:id params) (uuid/next))
|
||||
|
||||
props (-> (audit/extract-utm-params params)
|
||||
(merge (:props params))
|
||||
(merge {:viewed-tutorial? false
|
||||
|
@ -320,22 +347,36 @@
|
|||
|
||||
(defn register-profile
|
||||
[{:keys [conn sprops session] :as cfg} {:keys [token] :as params}]
|
||||
(let [claims (tokens/verify sprops {:token token :iss :prepared-register})
|
||||
params (merge params claims)]
|
||||
(check-profile-existence! conn params)
|
||||
(let [claims (tokens/verify sprops {:token token :iss :prepared-register})
|
||||
params (merge params claims)]
|
||||
|
||||
(let [is-active (or (:is-active params)
|
||||
(not (contains? cf/flags :email-verification))
|
||||
|
||||
;; DEPRECATED: v1.15
|
||||
(contains? cf/flags :insecure-register))
|
||||
|
||||
profile (->> (assoc params :is-active is-active)
|
||||
(create-profile conn)
|
||||
(create-profile-relations conn)
|
||||
(profile/decode-profile-row))
|
||||
profile (if-let [profile-id (:profile-id claims)]
|
||||
(profile/retrieve-profile conn profile-id)
|
||||
(->> (assoc params :is-active is-active)
|
||||
(create-profile conn)
|
||||
(create-profile-relations conn)
|
||||
(profile/decode-profile-row)))
|
||||
audit-fn (:audit cfg)
|
||||
|
||||
invitation (when-let [token (:invitation-token params)]
|
||||
(tokens/verify sprops {:token token :iss :team-invitation}))]
|
||||
|
||||
;; If profile is filled in claims, means it tries to register
|
||||
;; again, so we proceed to update the modified-at attr
|
||||
;; accordingly.
|
||||
(when-let [id (:profile-id claims)]
|
||||
(db/update! conn :profile {:modified-at (dt/now)} {:id id})
|
||||
(audit-fn :cmd :submit
|
||||
:type "fact"
|
||||
:name "register-profile-retry"
|
||||
:profile-id id))
|
||||
|
||||
(cond
|
||||
;; If invitation token comes in params, this is because the
|
||||
;; user comes from team-invitation process; in this case,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue