on master help sign in
Automatically reauthenticate when token expires during poll or send
4e3635ciko
client/ApiClient.fs+3−2
@@ -11,6 +11,7 @@ module ApiClient =
11
11
12 exception ApiError of string
12 exception ApiError of string
13 exception ServerRejected of string
13 exception ServerRejected of string
14+ exception Unauthorized
14
15
15 [<CLIMutable>]
16 [<CLIMutable>]
16 type EventPayload = { EncryptedBlob: string; Timestamp: int64 }
17 type EventPayload = { EncryptedBlob: string; Timestamp: int64 }
@@ -33,7 +34,7 @@ module ApiClient =
33 type PollEvent = { Id: string; EventType: EventType; Payload: EventPayload }
34 type PollEvent = { Id: string; EventType: EventType; Payload: EventPayload }
34
35
35 [<CLIMutable>]
36 [<CLIMutable>]
36− type PollResponse = { Cursor: int64; Events: PollEvent array }
37+ type PollResponse = { Cursor: int64; Events: PollEvent array; Authorized: bool }
37
38
38 /// Awaits a Task without converting TaskCanceledException to F# async
39 /// Awaits a Task without converting TaskCanceledException to F# async
39 /// cancellation (which bypasses try...with). Re-raises it as a regular exception.
40 /// cancellation (which bypasses try...with). Re-raises it as a regular exception.
@@ -99,7 +100,7 @@ module ApiClient =
99 match doc.RootElement.GetProperty("status").GetString() with
100 match doc.RootElement.GetProperty("status").GetString() with
100 | "delivered" | "federated" | "queued" -> ()
101 | "delivered" | "federated" | "queued" -> ()
101 | "rejected" -> raise (ServerRejected "Message rejected by server")
102 | "rejected" -> raise (ServerRejected "Message rejected by server")
102− | "unauthorized" -> raise (ServerRejected "Not authorized to deliver message")
103+ | "unauthorized" -> raise Unauthorized
103 | s -> raise (ApiError $"Unexpected status: {s}")
104 | s -> raise (ApiError $"Unexpected status: {s}")
104 }
105 }
105
106
client/App.fs+17−1
@@ -171,7 +171,7 @@ module App =
171
171
172 { model with
172 { model with
173 Auth = Identified(id, Online token)
173 Auth = Identified(id, Online token)
174− Page = Conversations
174+ Page = match model.Page with Setup -> Conversations | p -> p
175 Error = None
175 Error = None
176 PollStatus = "polling..."
176 PollStatus = "polling..."
177 FlushingOutbox = true },
177 FlushingOutbox = true },
@@ -185,6 +185,14 @@ module App =
185 PollRetries = 0 },
185 PollRetries = 0 },
186 []
186 []
187
187
188+ | TokenExpired ->
189+ match model.Auth with
190+ | Identified(id, Online _) ->
191+ let m = setConn Connecting model
192+ { m with FlushingOutbox = false; PollRetries = 0 },
193+ [ CmdConnect(model.ServerUrl, id) ]
194+ | _ -> model, []
195+
188 | DoDisconnect ->
196 | DoDisconnect ->
189 { setConn Offline model with
197 { setConn Offline model with
190 PollStatus = ""
198 PollStatus = ""
@@ -482,6 +490,9 @@ module App =
482 do! Store.dequeueOutbox item.Id
490 do! Store.dequeueOutbox item.Id
483 dispatch (FlushResult true)
491 dispatch (FlushResult true)
484 with
492 with
493+ | Unauthorized ->
494+ log "outbox unauthorized, reauthenticating"
495+ dispatch TokenExpired
485 | ServerRejected msg ->
496 | ServerRejected msg ->
486 log $"outbox rejected, dropping: {msg}"
497 log $"outbox rejected, dropping: {msg}"
487 do! Store.dequeueOutbox item.Id
498 do! Store.dequeueOutbox item.Id
@@ -503,6 +514,11 @@ module App =
503 let! response = poll session.Url session.Token cursor
514 let! response = poll session.Url session.Token cursor
504 log $"poll response: {response.Events.Length} events, cursor={response.Cursor}"
515 log $"poll response: {response.Events.Length} events, cursor={response.Cursor}"
505
516
517+ if not response.Authorized then
518+ log "poll unauthorized, reauthenticating"
519+ dispatch TokenExpired
520+ else
521+
506 let ackIds = response.Events |> Array.map _.Id |> Array.toList
522 let ackIds = response.Events |> Array.map _.Id |> Array.toList
507
523
508 let results =
524 let results =
client/AppTypes.fs+1
@@ -84,6 +84,7 @@ module AppTypes =
84 | StartFlush
84 | StartFlush
85 | FlushResult of sent: bool
85 | FlushResult of sent: bool
86 | Search of string
86 | Search of string
87+ | TokenExpired
87 | KeyboardHeightChanged of float
88 | KeyboardHeightChanged of float
88
89
89 // ── CmdMsg ──
90 // ── CmdMsg ──