mirror of
https://github.com/penpot/penpot.git
synced 2025-01-10 08:50:57 -05:00
Add password recovery page.
This commit is contained in:
parent
0fc6efa7b0
commit
87152c6b46
8 changed files with 194 additions and 34 deletions
|
@ -10,7 +10,7 @@
|
||||||
[promesa.core :as p]
|
[promesa.core :as p]
|
||||||
[uxbox.repo :as rp]
|
[uxbox.repo :as rp]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.router :as r]
|
[uxbox.router :as rt]
|
||||||
[uxbox.state :as st]
|
[uxbox.state :as st]
|
||||||
[uxbox.schema :as us]
|
[uxbox.schema :as us]
|
||||||
[uxbox.locales :refer (tr)]
|
[uxbox.locales :refer (tr)]
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [this state s]
|
(-apply-watch [this state s]
|
||||||
(rx/of (udu/fetch-profile)
|
(rx/of (udu/fetch-profile)
|
||||||
(r/navigate :dashboard/projects)))
|
(rt/navigate :dashboard/projects)))
|
||||||
|
|
||||||
rs/EffectEvent
|
rs/EffectEvent
|
||||||
(-apply-effect [this state]
|
(-apply-effect [this state]
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
|
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [_ state s]
|
(-apply-watch [_ state s]
|
||||||
(rx/of (r/navigate :auth/login))))
|
(rx/of (rt/navigate :auth/login))))
|
||||||
|
|
||||||
(defn logout
|
(defn logout
|
||||||
[]
|
[]
|
||||||
|
@ -142,3 +142,42 @@
|
||||||
(defn recovery-request
|
(defn recovery-request
|
||||||
[data]
|
[data]
|
||||||
(RecoveryRequest. data))
|
(RecoveryRequest. data))
|
||||||
|
|
||||||
|
;; --- Check Recovery Token
|
||||||
|
|
||||||
|
(defrecord ValidateRecoveryToken [token]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state stream]
|
||||||
|
(letfn [(on-error [{payload :payload}]
|
||||||
|
(rx/of
|
||||||
|
(rt/navigate :auth/login)
|
||||||
|
(udm/show-error (tr "errors.auth.invalid-recovery-token"))))]
|
||||||
|
(->> (rp/req :auth/validate-recovery-token token)
|
||||||
|
(rx/ignore)
|
||||||
|
(rx/catch rp/client-error? on-error)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn validate-recovery-token
|
||||||
|
[data]
|
||||||
|
(ValidateRecoveryToken. data))
|
||||||
|
|
||||||
|
;; --- Recovery (Password)
|
||||||
|
|
||||||
|
(defrecord Recovery [token password]
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state stream]
|
||||||
|
(letfn [(on-error [{payload :payload}]
|
||||||
|
(udm/error (tr "errors.auth.invalid-recovery-token")))
|
||||||
|
(on-success [{payload :payload}]
|
||||||
|
(rx/of
|
||||||
|
(rt/navigate :auth/login)
|
||||||
|
(udm/show-info (tr "auth.message.password-recovered"))))]
|
||||||
|
(->> (rp/req :auth/recovery {:token token :password password})
|
||||||
|
(rx/mapcat on-success)
|
||||||
|
(rx/catch rp/client-error? on-error)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn recovery
|
||||||
|
[{:keys [token password]}]
|
||||||
|
(Recovery. token password))
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
"ds.help.line" "Line (Ctrl + L)"
|
"ds.help.line" "Line (Ctrl + L)"
|
||||||
|
|
||||||
"auth.message.recovery-token-sent" "Password recovery link sent to your inbox."
|
"auth.message.recovery-token-sent" "Password recovery link sent to your inbox."
|
||||||
|
"auth.message.password-recovered" "Password successfully recovered."
|
||||||
|
|
||||||
"settings.profile" "PROFILE"
|
"settings.profile" "PROFILE"
|
||||||
"settings.password" "PASSWORD"
|
"settings.password" "PASSWORD"
|
||||||
|
@ -68,5 +69,6 @@
|
||||||
"errors.form.password-not-match" "Password does not match"
|
"errors.form.password-not-match" "Password does not match"
|
||||||
"errors.generic" "Something work has happened."
|
"errors.generic" "Something work has happened."
|
||||||
"errors.auth.unauthorized" "Username or passwords seems to be wrong."
|
"errors.auth.unauthorized" "Username or passwords seems to be wrong."
|
||||||
|
"errors.auth.invalid-recovery-token" "The recovery token is invalid."
|
||||||
"errors.profile.update-password" "Error updating password, probably your old password is wrong."
|
"errors.profile.update-password" "Error updating password, probably your old password is wrong."
|
||||||
})
|
})
|
||||||
|
|
|
@ -44,3 +44,16 @@
|
||||||
:method :post
|
:method :post
|
||||||
:body data}]
|
:body data}]
|
||||||
(send! params)))
|
(send! params)))
|
||||||
|
|
||||||
|
(defmethod request :auth/validate-recovery-token
|
||||||
|
[_ token]
|
||||||
|
(let [params {:url (str url "/auth/recovery/" token)
|
||||||
|
:method :get}]
|
||||||
|
(send! params)))
|
||||||
|
|
||||||
|
(defmethod request :auth/recovery
|
||||||
|
[_ data]
|
||||||
|
(let [params {:url (str url "/auth/recovery")
|
||||||
|
:method :put
|
||||||
|
:body data}]
|
||||||
|
(send! params)))
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
(defrecord Navigate [id params]
|
(defrecord Navigate [id params]
|
||||||
rs/EffectEvent
|
rs/EffectEvent
|
||||||
(-apply-effect [_ state]
|
(-apply-effect [_ state]
|
||||||
;; (println "navigate" id params)
|
|
||||||
(let [loc (merge {:handler id}
|
(let [loc (merge {:handler id}
|
||||||
(when params
|
(when params
|
||||||
{:route-params params}))]
|
{:route-params params}))]
|
||||||
|
@ -61,7 +60,8 @@
|
||||||
(def routes
|
(def routes
|
||||||
["/" [["auth/login" :auth/login]
|
["/" [["auth/login" :auth/login]
|
||||||
["auth/register" :auth/register]
|
["auth/register" :auth/register]
|
||||||
["auth/recovery-request" :auth/recovery-request]
|
["auth/recovery/request" :auth/recovery-request]
|
||||||
|
[["auth/recovery/token/" :token] :auth/recovery]
|
||||||
|
|
||||||
["settings/" [["profile" :settings/profile]
|
["settings/" [["profile" :settings/profile]
|
||||||
["password" :settings/password]
|
["password" :settings/password]
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
:auth/login (auth/login-page)
|
:auth/login (auth/login-page)
|
||||||
:auth/register (auth/register-page)
|
:auth/register (auth/register-page)
|
||||||
:auth/recovery-request (auth/recovery-request-page)
|
:auth/recovery-request (auth/recovery-request-page)
|
||||||
;; :auth/recovery (auth/recovery-page)
|
:auth/recovery (auth/recovery-page (:token params))
|
||||||
:dashboard/projects (dashboard/projects-page)
|
:dashboard/projects (dashboard/projects-page)
|
||||||
:dashboard/elements (dashboard/elements-page)
|
:dashboard/elements (dashboard/elements-page)
|
||||||
:dashboard/icons (dashboard/icons-page)
|
:dashboard/icons (dashboard/icons-page)
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
(ns uxbox.ui.auth
|
(ns uxbox.ui.auth
|
||||||
(:require [uxbox.ui.auth.login :as login]
|
(:require [uxbox.ui.auth.login :as login]
|
||||||
[uxbox.ui.auth.register :as register]
|
[uxbox.ui.auth.register :as register]
|
||||||
|
[uxbox.ui.auth.recovery-request :as recovery-request]
|
||||||
[uxbox.ui.auth.recovery :as recovery]))
|
[uxbox.ui.auth.recovery :as recovery]))
|
||||||
|
|
||||||
(def login-page login/login-page)
|
(def login-page login/login-page)
|
||||||
(def register-page register/register-page)
|
(def register-page register/register-page)
|
||||||
(def recovery-request-page recovery/recovery-request-page)
|
(def recovery-page recovery/recovery-page)
|
||||||
|
(def recovery-request-page recovery-request/recovery-request-page)
|
||||||
|
|
|
@ -25,43 +25,44 @@
|
||||||
|
|
||||||
;; --- Constants
|
;; --- Constants
|
||||||
|
|
||||||
(def recovery-request-form-data
|
(def form-data
|
||||||
(-> (l/in [:forms :recovery-request])
|
(-> (l/in [:forms :recovery])
|
||||||
(l/focus-atom st/state)))
|
(l/focus-atom st/state)))
|
||||||
|
|
||||||
(def recovery-request-form-errors
|
(def form-errors
|
||||||
(-> (l/in [:errors :recovery-request])
|
(-> (l/in [:errors :recovery])
|
||||||
(l/focus-atom st/state)))
|
(l/focus-atom st/state)))
|
||||||
|
|
||||||
(def set-value!
|
(def set-value!
|
||||||
(partial udf/assign-field-value :recovery-request))
|
(partial udf/assign-field-value :recovery))
|
||||||
|
|
||||||
;; --- Recovery Request Form
|
;; --- Recovery Request Form
|
||||||
|
|
||||||
(def recovery-request-schema
|
(def schema
|
||||||
{:username [us/required us/string]})
|
{:password [us/required us/string]})
|
||||||
|
|
||||||
(defn- recovery-request-form-render
|
(defn- form-render
|
||||||
[own]
|
[own token]
|
||||||
(let [form (rum/react recovery-request-form-data)
|
(let [form (rum/react form-data)
|
||||||
errors (rum/react recovery-request-form-errors)
|
errors (rum/react form-errors)
|
||||||
valid? (us/valid? form recovery-request-schema)]
|
valid? (us/valid? form schema)]
|
||||||
(letfn [(on-change [field event]
|
(letfn [(on-change [field event]
|
||||||
(let [value (dom/event->value event)]
|
(let [value (dom/event->value event)]
|
||||||
(rs/emit! (set-value! field value))))
|
(rs/emit! (set-value! field value))))
|
||||||
(on-submit [event]
|
(on-submit [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(rs/emit! (uda/recovery-request form)))]
|
(rs/emit! (uda/recovery (assoc form :token token))))]
|
||||||
(html
|
(html
|
||||||
[:form {:on-submit on-submit}
|
[:form {:on-submit on-submit}
|
||||||
[:div.login-content
|
[:div.login-content
|
||||||
|
|
||||||
[:input.input-text
|
[:input.input-text
|
||||||
{:name "username"
|
{:name "password"
|
||||||
:value (:username form "")
|
:value (:password form "")
|
||||||
:on-change (partial on-change :username)
|
:on-change (partial on-change :password)
|
||||||
:placeholder "username or email address"
|
:placeholder "Password"
|
||||||
:type "text"}]
|
:type "password"}]
|
||||||
(forms/input-error errors :username)
|
(forms/input-error errors :password)
|
||||||
|
|
||||||
[:input.btn-primary
|
[:input.btn-primary
|
||||||
{:name "login"
|
{:name "login"
|
||||||
|
@ -72,25 +73,32 @@
|
||||||
[:div.login-links
|
[:div.login-links
|
||||||
[:a {:on-click #(rt/go :auth/login)} "Go back!"]]]]))))
|
[:a {:on-click #(rt/go :auth/login)} "Go back!"]]]]))))
|
||||||
|
|
||||||
(def recovery-request-form
|
(def form
|
||||||
(mx/component
|
(mx/component
|
||||||
{:render recovery-request-form-render
|
{:render form-render
|
||||||
:name "recovery-request-form"
|
:name "form"
|
||||||
:mixins [mx/static rum/reactive]}))
|
:mixins [mx/static rum/reactive]}))
|
||||||
|
|
||||||
;; --- Recovery Request Page
|
;; --- Recovery Request Page
|
||||||
|
|
||||||
(defn- recovery-request-page-render
|
(defn- recovery-page-will-mount
|
||||||
[own]
|
[own]
|
||||||
|
(let [[token] (:rum/props own)]
|
||||||
|
(rs/emit! (uda/validate-recovery-token token))
|
||||||
|
own))
|
||||||
|
|
||||||
|
(defn- recovery-page-render
|
||||||
|
[own token]
|
||||||
(html
|
(html
|
||||||
[:div.login
|
[:div.login
|
||||||
[:div.login-body
|
[:div.login-body
|
||||||
(uum/messages)
|
(uum/messages)
|
||||||
[:a i/logo]
|
[:a i/logo]
|
||||||
(recovery-request-form)]]))
|
(form token)]]))
|
||||||
|
|
||||||
(def recovery-request-page
|
(def recovery-page
|
||||||
(mx/component
|
(mx/component
|
||||||
{:render recovery-request-page-render
|
{:render recovery-page-render
|
||||||
:name "recovery-request-page"
|
:will-mount recovery-page-will-mount
|
||||||
|
:name "recovery-page"
|
||||||
:mixins [mx/static]}))
|
:mixins [mx/static]}))
|
||||||
|
|
96
src/uxbox/ui/auth/recovery_request.cljs
Normal file
96
src/uxbox/ui/auth/recovery_request.cljs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
;; 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) 2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
|
(ns uxbox.ui.auth.recovery-request
|
||||||
|
(:require [sablono.core :as html :refer-macros [html]]
|
||||||
|
[lentes.core :as l]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[uxbox.router :as rt]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.schema :as us]
|
||||||
|
[uxbox.data.auth :as uda]
|
||||||
|
[uxbox.data.messages :as udm]
|
||||||
|
[uxbox.data.forms :as udf]
|
||||||
|
[uxbox.ui.forms :as forms]
|
||||||
|
[uxbox.ui.icons :as i]
|
||||||
|
[uxbox.ui.messages :as uum]
|
||||||
|
[uxbox.ui.navigation :as nav]
|
||||||
|
[uxbox.ui.mixins :as mx]
|
||||||
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
;; --- Recovery Request Constants
|
||||||
|
|
||||||
|
(def form-data
|
||||||
|
(-> (l/in [:forms :recovery-request])
|
||||||
|
(l/focus-atom st/state)))
|
||||||
|
|
||||||
|
(def form-errors
|
||||||
|
(-> (l/in [:errors :recovery-request])
|
||||||
|
(l/focus-atom st/state)))
|
||||||
|
|
||||||
|
(def set-value!
|
||||||
|
(partial udf/assign-field-value :recovery-request))
|
||||||
|
|
||||||
|
;; --- Recovery Request Form
|
||||||
|
|
||||||
|
(def schema
|
||||||
|
{:username [us/required us/string]})
|
||||||
|
|
||||||
|
(defn- form-render
|
||||||
|
[own]
|
||||||
|
(let [form (rum/react form-data)
|
||||||
|
errors (rum/react form-errors)
|
||||||
|
valid? (us/valid? form schema)]
|
||||||
|
(letfn [(on-change [field event]
|
||||||
|
(let [value (dom/event->value event)]
|
||||||
|
(rs/emit! (set-value! field value))))
|
||||||
|
(on-submit [event]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(rs/emit! (uda/recovery-request form)))]
|
||||||
|
(html
|
||||||
|
[:form {:on-submit on-submit}
|
||||||
|
[:div.login-content
|
||||||
|
[:input.input-text
|
||||||
|
{:name "username"
|
||||||
|
:value (:username form "")
|
||||||
|
:on-change (partial on-change :username)
|
||||||
|
:placeholder "username or email address"
|
||||||
|
:type "text"}]
|
||||||
|
(forms/input-error errors :username)
|
||||||
|
|
||||||
|
[:input.btn-primary
|
||||||
|
{:name "login"
|
||||||
|
:class (when-not valid? "btn-disabled")
|
||||||
|
:disabled (not valid?)
|
||||||
|
:value "Recover password"
|
||||||
|
:type "submit"}]
|
||||||
|
[:div.login-links
|
||||||
|
[:a {:on-click #(rt/go :auth/login)} "Go back!"]]]]))))
|
||||||
|
|
||||||
|
(def form
|
||||||
|
(mx/component
|
||||||
|
{:render form-render
|
||||||
|
:name "form"
|
||||||
|
:mixins [mx/static rum/reactive]}))
|
||||||
|
|
||||||
|
;; --- Recovery Request Page
|
||||||
|
|
||||||
|
(defn- recovery-request-page-render
|
||||||
|
[own]
|
||||||
|
(html
|
||||||
|
[:div.login
|
||||||
|
[:div.login-body
|
||||||
|
(uum/messages)
|
||||||
|
[:a i/logo]
|
||||||
|
(form)]]))
|
||||||
|
|
||||||
|
(def recovery-request-page
|
||||||
|
(mx/component
|
||||||
|
{:render recovery-request-page-render
|
||||||
|
:name "recovery-request-page"
|
||||||
|
:mixins [mx/static]}))
|
Loading…
Reference in a new issue