|
1 | 1 | (ns parts.frontend.components.auth
|
2 | 2 | (:require
|
3 | 3 | [uix.core :refer [defui $ use-state use-effect use-callback]]
|
4 |
| - [cljs.core.async :refer [<!]] |
| 4 | + [cljs.core.async :refer [<! chan]] |
5 | 5 | [parts.frontend.context :as ctx]
|
6 |
| - [parts.frontend.utils.api :as api] |
| 6 | + [parts.frontend.api.core :as api] |
| 7 | + [parts.frontend.utils.api :as utils] ;; Still need for token storage functions |
7 | 8 | [parts.frontend.components.modal :refer [modal]])
|
8 | 9 | (:require-macros
|
9 | 10 | [cljs.core.async.macros :refer [go]]))
|
10 | 11 |
|
| 12 | +;; Auth-specific API operations using core API functions |
| 13 | +(defn login-user [email password csrf-token] |
| 14 | + (let [result-chan (chan)] |
| 15 | + ;; Create the request |
| 16 | + (api/create-entity "/auth/login" |
| 17 | + {:email email |
| 18 | + :password password |
| 19 | + :__anti-forgery-token csrf-token}) |
| 20 | + |
| 21 | + ;; Wait for the response on the event channel |
| 22 | + (go |
| 23 | + (loop [] |
| 24 | + (let [event (<! api/event-channel)] |
| 25 | + (cond |
| 26 | + ;; Success event for our login |
| 27 | + (and (= (:event event) :api-success) |
| 28 | + (= (:type event) :create-entity)) |
| 29 | + (do |
| 30 | + (js/console.log "Got login success event" event) |
| 31 | + (put! result-chan {:success true :data (:data event)})) |
| 32 | + |
| 33 | + ;; Error event for our login |
| 34 | + (and (= (:event event) :api-error) |
| 35 | + (= (:type (:error event)) :create-entity)) |
| 36 | + (do |
| 37 | + (js/console.log "Got login error event" event) |
| 38 | + (put! result-chan {:success false :error (:message (:error event))})) |
| 39 | + |
| 40 | + ;; Neither success nor error yet, keep waiting |
| 41 | + :else |
| 42 | + (recur))))) |
| 43 | + |
| 44 | + result-chan)) |
| 45 | + |
| 46 | +(defn logout-user [] |
| 47 | + (let [result-chan (chan) |
| 48 | + tokens (utils/get-tokens)] |
| 49 | + |
| 50 | + (when tokens |
| 51 | + ;; Create the logout request |
| 52 | + (api/create-entity "/auth/logout" |
| 53 | + {:refresh_token (:refresh_token tokens) |
| 54 | + :__anti-forgery-token (utils/get-csrf-token)}) |
| 55 | + |
| 56 | + ;; Wait for response on event channel |
| 57 | + (go |
| 58 | + (loop [] |
| 59 | + (let [event (<! api/event-channel)] |
| 60 | + (when (or (and (= (:event event) :api-success) |
| 61 | + (= (:type event) :create-entity)) |
| 62 | + (and (= (:event event) :api-error) |
| 63 | + (= (:type (:error event)) :create-entity))) |
| 64 | + ;; Success or error, either way we're logged out |
| 65 | + (put! result-chan {:success true})) |
| 66 | + |
| 67 | + ;; Keep waiting |
| 68 | + (recur))))) |
| 69 | + |
| 70 | + ;; If no tokens, just return success |
| 71 | + (when-not tokens |
| 72 | + (put! result-chan {:success true})) |
| 73 | + |
| 74 | + result-chan)) |
| 75 | + |
| 76 | +(defn get-user-info [] |
| 77 | + (let [result-chan (chan)] |
| 78 | + (go |
| 79 | + (let [user-data (<! (api/fetch-data "/account"))] |
| 80 | + (put! result-chan user-data))) |
| 81 | + result-chan)) |
| 82 | + |
11 | 83 | (defui auth-provider [{:keys [children]}]
|
12 | 84 | (let [[auth-state set-auth-state] (use-state
|
13 | 85 | {:logged-in false
|
|
16 | 88 |
|
17 | 89 | login (use-callback
|
18 | 90 | (fn [email password csrf-token]
|
19 |
| - (let [login-promise (js/Promise. |
20 |
| - (fn [resolve reject] |
21 |
| - (go |
22 |
| - (let [response (<! (api/login email password csrf-token)) |
23 |
| - _ (js/console.log "Login response:", response) |
24 |
| - {:keys [success data error]} response] |
25 |
| - (if success |
26 |
| - (do |
27 |
| - (js/console.log "Login success, saving tokens:", data) |
28 |
| - (api/save-tokens data) |
29 |
| - (api/save-user-email email) |
30 |
| - (set-auth-state |
31 |
| - {:logged-in true |
32 |
| - :email email |
33 |
| - :loading false}) |
34 |
| - (resolve true)) |
35 |
| - (do |
36 |
| - (js/console.log "Login failed:", error) |
37 |
| - (reject (or error "Login failed"))))))))] |
38 |
| - login-promise)) |
| 91 | + (let [result-chan (chan)] |
| 92 | + (go |
| 93 | + (let [response (<! (login-user email password csrf-token))] |
| 94 | + (js/console.log "Login response:", response) |
| 95 | + (if (:success response) |
| 96 | + (let [data (:data response)] |
| 97 | + (js/console.log "Login success, saving tokens:", data) |
| 98 | + (utils/save-tokens data) |
| 99 | + (utils/save-user-email email) |
| 100 | + (set-auth-state |
| 101 | + {:logged-in true |
| 102 | + :email email |
| 103 | + :loading false}) |
| 104 | + (put! result-chan true)) |
| 105 | + (put! result-chan (js/Error. "Login failed"))))) |
| 106 | + result-chan)) |
39 | 107 | [])
|
40 | 108 |
|
41 | 109 | logout (use-callback
|
42 | 110 | (fn []
|
43 |
| - (let [logout-promise (js/Promise. |
44 |
| - (fn [resolve _reject] |
45 |
| - (go |
46 |
| - (let [_ (<! (api/logout))] |
47 |
| - (set-auth-state |
48 |
| - {:logged-in false |
49 |
| - :email nil |
50 |
| - :loading false}) |
51 |
| - (resolve true)))))] |
52 |
| - logout-promise)) |
| 111 | + (let [result-chan (chan)] |
| 112 | + (go |
| 113 | + (let [_ (<! (logout-user))] |
| 114 | + (utils/clear-tokens) |
| 115 | + (set-auth-state |
| 116 | + {:logged-in false |
| 117 | + :email nil |
| 118 | + :loading false}) |
| 119 | + (put! result-chan true))) |
| 120 | + result-chan)) |
53 | 121 | [])]
|
54 | 122 |
|
55 | 123 | ;; Load auth state on mount
|
|
58 | 126 | (let [effect-fn
|
59 | 127 | (fn []
|
60 | 128 | (go
|
61 |
| - (if-let [tokens (api/get-tokens)] |
62 |
| - (let [stored-email (api/get-user-email)] |
| 129 | + (if-let [tokens (utils/get-tokens)] |
| 130 | + (let [stored-email (utils/get-user-email)] |
63 | 131 | (js/console.log "Found tokens in storage:", tokens)
|
64 | 132 | (js/console.log "Found email in storage:", stored-email)
|
65 | 133 |
|
|
75 | 143 | :loading false}))
|
76 | 144 |
|
77 | 145 | ;; No email stored, try to get user info
|
78 |
| - (let [response (<! (api/get-user-info)) |
79 |
| - _ (js/console.log "Get user info response:", response) |
80 |
| - {:keys [success data]} response] |
81 |
| - (if success |
| 146 | + (let [user-data (<! (get-user-info))] |
| 147 | + (js/console.log "Get user info response:", user-data) |
| 148 | + (if user-data |
82 | 149 | (do
|
83 |
| - (js/console.log "Successfully got user info:", data) |
84 |
| - (when-let [email (:email data)] |
85 |
| - (api/save-user-email email)) |
| 150 | + (js/console.log "Successfully got user info:", user-data) |
| 151 | + (when-let [email (:email user-data)] |
| 152 | + (utils/save-user-email email)) |
86 | 153 | (set-auth-state
|
87 | 154 | {:logged-in true
|
88 |
| - :email (:email data) |
| 155 | + :email (:email user-data) |
89 | 156 | :loading false}))
|
90 | 157 | (do
|
91 | 158 | (js/console.log "Failed to get user info with token")
|
92 | 159 | ;; Failed to get user info with existing token
|
93 |
| - (api/clear-tokens) |
| 160 | + (utils/clear-tokens) |
94 | 161 | (set-auth-state
|
95 | 162 | {:logged-in false
|
96 | 163 | :email nil
|
|
118 | 185 | [error set-error] (use-state nil)
|
119 | 186 | [loading set-loading] (use-state false)
|
120 | 187 | {:keys [login]} (uix.core/use-context ctx/auth-context)
|
121 |
| - csrf-token (or (api/get-csrf-token) "") |
| 188 | + csrf-token (or (utils/get-csrf-token) "") |
122 | 189 |
|
123 | 190 | handle-submit (fn [e]
|
124 | 191 | (.preventDefault e)
|
125 | 192 | (set-loading true)
|
126 | 193 | (set-error nil)
|
127 |
| - (.then |
128 |
| - (login email password csrf-token) |
129 |
| - (fn [_] |
130 |
| - (set-loading false) |
131 |
| - (on-close)) |
132 |
| - (fn [err] |
133 |
| - (js/console.log "Login error:", err) |
134 |
| - (set-loading false) |
135 |
| - (set-error "Invalid email or password"))))] |
| 194 | + (go |
| 195 | + (try |
| 196 | + (let [result (<! (login email password csrf-token))] |
| 197 | + (set-loading false) |
| 198 | + (on-close)) |
| 199 | + (catch js/Error err |
| 200 | + (js/console.log "Login error:", err) |
| 201 | + (set-loading false) |
| 202 | + (set-error "Invalid email or password")))))] |
136 | 203 |
|
137 | 204 | ($ modal
|
138 | 205 | {:show show
|
|
145 | 212 | error))
|
146 | 213 |
|
147 | 214 | ;; Anti-forgery token - hidden field
|
148 |
| - (when-let [token (api/get-csrf-token)] |
| 215 | + (when-let [token (utils/get-csrf-token)] |
149 | 216 | ($ :input
|
150 | 217 | {:type "hidden"
|
151 | 218 | :id "__anti-forgery-token"
|
|
0 commit comments