- layout-component (ornament fn)
- handle CSS part
- leverage query syntax to assign CSS to child structure
- widget-component (ornament fn)
- small, reusable, and self-contained UI elements)
- presenter-fn (ordinary fn)
- handle pure html structure (withouth CSS)
- example:
fail-page
- container-fn (ordinary fn)
- handle the data && logic behavior
- example:
verification-success
(ns co.gaiwan.oak.html.totp)
...
(o/defstyled totp-layout :div
{:display :flex
:justify-content :center
:align-items :center
:min-height "100vh"}
[:p
{:text-align :center
:margin-top 0}]
([& children]
[:<>
[w/leaf-bg]
(into [w/full-center-card] children)]))
(defn fail-page [{:keys [next-uri]}]
[totp-layout
[:h1 "2FA Setup Failed"]
[:p "Invalid code. Please check and re-enter."]
[:a {:href next-uri} "Go back to 2FA setup page"]])
=====================================================
(ns co.gaiwan.oak.apis.totp)
...
(defn verification-success
"Tell success, store secret as credential (upsert the record), remove the secret from
the session"
[{:keys [identity db session]} secret]
(let [opts {:identity-id (:identity/id identity)
:type "totp"
:value secret}
updated-session (dissoc session :totp/secret)]
(if (credential/create-or-update! db opts)
{:status 200
:session updated-session
:html/body
[totp-html/success-page {:cred-save-success? true}]}
{:status 200
:html/body
[totp-html/success-page {:cred-save-success? false}]})))