Skip to content

Commit dd16c86

Browse files
committed
Add account switch endpoint for account switcher
1 parent 8059388 commit dd16c86

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

bin/main.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ let handlers =
4040
; ( get
4141
, "/account/signup/check-handle"
4242
, Api.Account_.Signup.check_handle_handler )
43+
; (post, "/account/switch", Api.Account_.Login.switch_account_handler)
4344
; (get, "/account/logout", Api.Account_.Logout.handler)
4445
; (* admin ui *)
4546
(get, "/admin", Api.Admin_.Index.handler)

frontend/src/components/AccountSwitcher.mlx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,32 @@ let fallback handle avatar =
2424

2525
let[@react.component] make ~current_user ~logged_in_users ~add_account_url
2626
?(name = "did") ?(inline = false) ?onChange () =
27+
let handleAccountSwitch =
28+
[%browser_only
29+
fun newDid ->
30+
if newDid <> current_user.did then
31+
let formData = Fetch.FormData.make () in
32+
Fetch.FormData.set "did" newDid formData ;
33+
let _ =
34+
Fetch.fetchWithInit "/account/switch"
35+
(Fetch.RequestInit.make ~method_:Fetch.Post
36+
~body:(Fetch.BodyInit.makeWithFormData formData)
37+
() )
38+
|> Js.Promise.then_ (fun response ->
39+
if Fetch.Response.ok response then (
40+
ignore ([%mel.raw {| window.location.reload() |}] : unit) ;
41+
Js.Promise.resolve () )
42+
else Js.Promise.resolve () )
43+
|> Js.Promise.catch (fun _ -> Js.Promise.resolve ())
44+
in
45+
() ;
46+
( match onChange with
47+
| Some f ->
48+
f newDid
49+
| None ->
50+
() )
51+
else ()]
52+
in
2753
let button_class =
2854
if inline then
2955
"group inline-flex flex-row items-center px-1.5 py-1 -mx-0.75 -my-1 \
@@ -41,7 +67,7 @@ let[@react.component] make ~current_user ~logged_in_users ~add_account_url
4167
<ClientOnly fallback=(fallback current_user.handle current_user.avatar_data_uri)>
4268
[%browser_only
4369
(fun () ->
44-
<Aria.Select name className="inline" defaultValue=current_user.did placeholder="select account" ?onChange>
70+
<Aria.Select name className="inline" defaultValue=current_user.did placeholder="select account" onChange=handleAccountSwitch>
4571
<Aria.Button className=button_class>
4672
<Aria.SelectValue className=value_class />
4773
</Aria.Button>

pegasus/lib/api/account_/login.ml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,39 @@ let get_handler =
1111
(module Frontend.LoginPage)
1212
~props:{redirect_url; csrf_token; error= None} )
1313

14+
type switch_account_response =
15+
{success: bool; error: string option [@default None]}
16+
[@@deriving yojson {strict= false}]
17+
18+
let switch_account_handler =
19+
Xrpc.handler (fun ctx ->
20+
match%lwt Dream.form ctx.req with
21+
| `Ok fields -> (
22+
let did = List.assoc_opt "did" fields in
23+
match did with
24+
| Some did ->
25+
let%lwt logged_in_dids = Session.Raw.get_logged_in_dids ctx.req in
26+
if List.mem did logged_in_dids then
27+
let%lwt () = Session.Raw.set_current_did ctx.req did in
28+
Dream.json @@ Yojson.Safe.to_string
29+
@@ switch_account_response_to_yojson {success= true; error= None}
30+
else
31+
Dream.json ~status:`Bad_Request
32+
@@ Yojson.Safe.to_string
33+
@@ switch_account_response_to_yojson
34+
{ success= false
35+
; error= Some "not logged in as this account" }
36+
| None ->
37+
Dream.json ~status:`Bad_Request
38+
@@ Yojson.Safe.to_string
39+
@@ switch_account_response_to_yojson
40+
{success= false; error= Some "missing did parameter"} )
41+
| _ ->
42+
Dream.json ~status:`Bad_Request
43+
@@ Yojson.Safe.to_string
44+
@@ switch_account_response_to_yojson
45+
{success= false; error= Some "invalid form submission"} )
46+
1447
let post_handler =
1548
Xrpc.handler (fun ctx ->
1649
let csrf_token = Dream.csrf_token ctx.req in

0 commit comments

Comments
 (0)