objective categorical abstract machine language personal data server

Add account switch endpoint for account switcher

futur.blue dd16c861 8059388c

verified
+61 -1
+1
bin/main.ml
··· 40 ; ( get 41 , "/account/signup/check-handle" 42 , Api.Account_.Signup.check_handle_handler ) 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 () = 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 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