tangled
alpha
login
or
join now
futur.blue
/
pegasus
57
fork
atom
objective categorical abstract machine language personal data server
57
fork
atom
overview
issues
2
pulls
pipelines
Add account switch endpoint for account switcher
futur.blue
2 months ago
dd16c861
8059388c
verified
This commit was signed with the committer's
known signature
.
futur.blue
SSH Key Fingerprint:
SHA256:QHGqHWNpqYyw9bt8KmPuJIyeZX9SZewBZ0PR1COtKQ0=
+61
-1
3 changed files
expand all
collapse all
unified
split
bin
main.ml
frontend
src
components
AccountSwitcher.mlx
pegasus
lib
api
account_
login.ml
+1
bin/main.ml
···
40
; ( get
41
, "/account/signup/check-handle"
42
, Api.Account_.Signup.check_handle_handler )
0
43
; (get, "/account/logout", Api.Account_.Logout.handler)
44
; (* admin ui *)
45
(get, "/admin", Api.Admin_.Index.handler)
···
40
; ( get
41
, "/account/signup/check-handle"
42
, Api.Account_.Signup.check_handle_handler )
43
+
; (post, "/account/switch", Api.Account_.Login.switch_account_handler)
44
; (get, "/account/logout", Api.Account_.Logout.handler)
45
; (* admin ui *)
46
(get, "/admin", Api.Admin_.Index.handler)
+27
-1
frontend/src/components/AccountSwitcher.mlx
···
24
25
let[@react.component] make ~current_user ~logged_in_users ~add_account_url
26
?(name = "did") ?(inline = false) ?onChange () =
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
27
let button_class =
28
if inline then
29
"group inline-flex flex-row items-center px-1.5 py-1 -mx-0.75 -my-1 \
···
41
<ClientOnly fallback=(fallback current_user.handle current_user.avatar_data_uri)>
42
[%browser_only
43
(fun () ->
44
-
<Aria.Select name className="inline" defaultValue=current_user.did placeholder="select account" ?onChange>
45
<Aria.Button className=button_class>
46
<Aria.SelectValue className=value_class />
47
</Aria.Button>
···
24
25
let[@react.component] make ~current_user ~logged_in_users ~add_account_url
26
?(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
53
let button_class =
54
if inline then
55
"group inline-flex flex-row items-center px-1.5 py-1 -mx-0.75 -my-1 \
···
67
<ClientOnly fallback=(fallback current_user.handle current_user.avatar_data_uri)>
68
[%browser_only
69
(fun () ->
70
+
<Aria.Select name className="inline" defaultValue=current_user.did placeholder="select account" onChange=handleAccountSwitch>
71
<Aria.Button className=button_class>
72
<Aria.SelectValue className=value_class />
73
</Aria.Button>
+33
pegasus/lib/api/account_/login.ml
···
11
(module Frontend.LoginPage)
12
~props:{redirect_url; csrf_token; error= None} )
13
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
14
let post_handler =
15
Xrpc.handler (fun ctx ->
16
let csrf_token = Dream.csrf_token ctx.req in
···
11
(module Frontend.LoginPage)
12
~props:{redirect_url; csrf_token; error= None} )
13
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
+
47
let post_handler =
48
Xrpc.handler (fun ctx ->
49
let csrf_token = Dream.csrf_token ctx.req in