Andrey Antukh 8057fb54a6 ✨ Add verify macro for true runtime spec asserts.
This commits mainly renames the old `assert` to `verify` and
adds new `assert` that laverages `:elide-asserts` on clojurescript
and *assert* value on clojure.

This approach enables an assert macro that does not performs
any runtime checks and compiles to more performant code in both
cases: development mode and production mode.
2020-01-31 19:12:48 +01:00

162 lines
4.2 KiB
Clojure

;; 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/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.data.auth
(:require
[cljs.spec.alpha :as s]
[beicon.core :as rx]
[potok.core :as ptk]
[uxbox.common.spec :as us]
[uxbox.main.repo :as rp]
[uxbox.main.store :refer [initial-state]]
[uxbox.main.data.users :as du]
[uxbox.util.messages :as um]
[uxbox.util.router :as rt]
[uxbox.util.i18n :as i18n :refer [tr]]
[uxbox.util.storage :refer [storage]]))
(s/def ::username string?)
(s/def ::password string?)
(s/def ::fullname string?)
(s/def ::email ::us/email)
;; --- Logged In
(defn logged-in
[data]
(ptk/reify ::logged-in
ptk/UpdateEvent
(update [this state]
(assoc state :auth data))
ptk/WatchEvent
(watch [this state s]
(swap! storage assoc :auth data)
(rx/of du/fetch-profile
(rt/navigate :dashboard-projects)))))
;; --- Login
(s/def ::login-params
(s/keys :req-un [::username ::password]))
(defn login
[{:keys [username password] :as data}]
(us/verify ::login-params data)
(ptk/reify ::login
ptk/UpdateEvent
(update [_ state]
(merge state (dissoc initial-state :route :router)))
ptk/WatchEvent
(watch [this state s]
(let [params {:username username
:password password
:scope "webapp"}
on-error #(rx/of (um/error (tr "errors.auth.unauthorized")))]
(->> (rp/mutation :login params)
(rx/map logged-in)
(rx/catch rp/client-error? on-error))))))
;; --- Logout
(def clear-user-data
(ptk/reify ::clear-user-data
ptk/UpdateEvent
(update [_ state]
(merge state (dissoc initial-state :route :router)))
ptk/WatchEvent
(watch [_ state s]
(->> (rp/mutation :logout)
(rx/ignore)))
ptk/EffectEvent
(effect [_ state s]
(reset! storage {})
(i18n/set-default-locale!))))
(def logout
(ptk/reify ::logout
ptk/WatchEvent
(watch [_ state s]
(rx/of (rt/nav :login)
clear-user-data))))
;; --- Register
(s/def ::register
(s/keys :req-un [::fullname
::username
::password
::email]))
(defn register
"Create a register event instance."
[data on-error]
(s/assert ::register data)
(s/assert fn? on-error)
(ptk/reify ::register
ptk/WatchEvent
(watch [_ state stream]
(letfn [(handle-error [{payload :payload}]
(on-error payload)
(rx/empty))]
(->> (rp/mutation :register-profile data)
(rx/map (fn [_] (login data)))
(rx/catch rp/client-error? handle-error))))))
;; --- Recovery Request
(s/def ::recovery-request
(s/keys :req-un [::username]))
(defn request-profile-recovery
[data on-success]
(us/verify ::recovery-request data)
(us/verify fn? on-success)
(ptk/reify ::request-profile-recovery
ptk/WatchEvent
(watch [_ state stream]
(letfn [(on-error [{payload :payload}]
(rx/empty))]
(->> (rp/mutation :request-profile-recovery data)
(rx/tap on-success)
(rx/catch rp/client-error? on-error))))))
;; --- Recovery (Password)
(s/def ::token string?)
(s/def ::on-error fn?)
(s/def ::on-success fn?)
(s/def ::recover-profile
(s/keys :req-un [::password ::token ::on-error ::on-success]))
(defn recover-profile
[{:keys [token password on-error on-success] :as data}]
(us/verify ::recover-profile data)
(ptk/reify ::recover-profile
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/mutation :recover-profile {:token token :password password})
(rx/tap on-success)
(rx/catch (fn [err]
(on-error)
(rx/empty)))))))
;; --- Create Demo Profile
(def create-demo-profile
(ptk/reify ::create-demo-profile
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/mutation :create-demo-profile {})
(rx/map login)))))