objective categorical abstract machine language personal data server

Multi account session support

futur.blue 9b7df25f c48efaf4

verified
+144 -48
+1 -1
pegasus/lib/api/account_/login.ml
··· 33 ~props:{redirect_url; csrf_token; error= Some error} 34 | Some {did; _} -> 35 let%lwt () = Dream.invalidate_session ctx.req in 36 - let%lwt () = Dream.set_session_field ctx.req "did" did in 37 Dream.redirect ctx.req redirect_url ) 38 | _ -> 39 let redirect_url = "/account" in
··· 33 ~props:{redirect_url; csrf_token; error= Some error} 34 | Some {did; _} -> 35 let%lwt () = Dream.invalidate_session ctx.req in 36 + let%lwt () = Session.log_in_did ctx.req did in 37 Dream.redirect ctx.req redirect_url ) 38 | _ -> 39 let redirect_url = "/account" in
+53 -44
pegasus/lib/api/oauth_/authorize.ml
··· 1 open Oauth 2 open Oauth.Types 3 4 - let get_session_user (ctx : Xrpc.context) = 5 - match Dream.session_field ctx.req "did" with 6 - | Some did -> 7 - Lwt.return_some did 8 - | None -> 9 - Lwt.return_none 10 - 11 let get_handler = 12 Xrpc.handler (fun ctx -> 13 let login_redirect = ··· 62 ; expires_at 63 ; used= false } 64 in 65 - match%lwt get_session_user ctx with 66 | None -> 67 login_redirect 68 - | Some did -> ( 69 - match req.login_hint with 70 - | Some hint when hint <> did -> 71 - login_redirect 72 - | _ -> 73 - let%lwt handle = 74 - match%lwt 75 - Data_store.get_actor_by_identifier did ctx.db 76 - with 77 - | Some {handle; _} -> 78 - Lwt.return handle 79 - | None -> 80 - Errors.internal_error 81 - ~msg:"failed to resolve user" () 82 - in 83 - let scopes = String.split_on_char ' ' req.scope in 84 - let csrf_token = Dream.csrf_token ctx.req in 85 - let client_id_uri = Uri.of_string metadata.client_id in 86 - let host, path = 87 - ( Uri.host_with_default client_id_uri 88 - ~default:"unknown" 89 - , Uri.path client_id_uri ) 90 - in 91 - let client_url = (host, path) in 92 - let client_name = metadata.client_name in 93 - Util.render_html ~title:("Authorizing " ^ host) 94 - (module Frontend.OauthAuthorizePage) 95 - ~props: 96 - { client_url 97 - ; client_name 98 - ; handle 99 - ; scopes 100 - ; code 101 - ; request_uri 102 - ; csrf_token } ) ) ) ) 103 104 let post_handler = 105 Xrpc.handler (fun ctx -> 106 - match%lwt get_session_user ctx with 107 | None -> 108 Errors.auth_required "missing authentication" 109 | Some user_did -> (
··· 1 open Oauth 2 open Oauth.Types 3 4 let get_handler = 5 Xrpc.handler (fun ctx -> 6 let login_redirect = ··· 55 ; expires_at 56 ; used= false } 57 in 58 + match%lwt Session.Raw.get_session ctx.req with 59 | None -> 60 login_redirect 61 + | Some session when session.logged_in_dids = [] -> 62 + login_redirect 63 + | Some {current_did; logged_in_dids} -> ( 64 + let%lwt did = 65 + match req.login_hint with 66 + | Some hint when List.mem hint logged_in_dids -> 67 + let%lwt () = 68 + if Some hint <> current_did then 69 + Session.Raw.set_current_did ctx.req hint 70 + else Lwt.return_unit 71 + in 72 + Lwt.return_some hint 73 + | _ -> 74 + Lwt.return current_did 75 + in 76 + match did with 77 + | None -> 78 + login_redirect 79 + | Some did -> 80 + let%lwt handle = 81 + match%lwt 82 + Data_store.get_actor_by_identifier did ctx.db 83 + with 84 + | Some {handle; _} -> 85 + Lwt.return handle 86 + | None -> 87 + Errors.internal_error 88 + ~msg:"failed to resolve user" () 89 + in 90 + let scopes = String.split_on_char ' ' req.scope in 91 + let csrf_token = Dream.csrf_token ctx.req in 92 + let client_id_uri = 93 + Uri.of_string metadata.client_id 94 + in 95 + let host, path = 96 + ( Uri.host_with_default client_id_uri 97 + ~default:"unknown" 98 + , Uri.path client_id_uri ) 99 + in 100 + let client_url = (host, path) in 101 + let client_name = metadata.client_name in 102 + Util.render_html ~title:("Authorizing " ^ host) 103 + (module Frontend.OauthAuthorizePage) 104 + ~props: 105 + { client_url 106 + ; client_name 107 + ; handle 108 + ; scopes 109 + ; code 110 + ; request_uri 111 + ; csrf_token } ) ) ) ) 112 113 let post_handler = 114 Xrpc.handler (fun ctx -> 115 + match%lwt Session.Raw.get_current_did ctx.req with 116 | None -> 117 Errors.auth_required "missing authentication" 118 | Some user_did -> (
+1
pegasus/lib/api/oauth_/token.ml
··· 170 Queries.update_oauth_token ctx.db 171 ~old_refresh_token:refresh_token 172 ~new_refresh_token:new_refresh ~expires_at:new_expires_at 173 in 174 Dream.json ~headers:[("Cache-Control", "no-store")] 175 @@ Yojson.Safe.to_string
··· 170 Queries.update_oauth_token ctx.db 171 ~old_refresh_token:refresh_token 172 ~new_refresh_token:new_refresh ~expires_at:new_expires_at 173 + ~ip ~user_agent 174 in 175 Dream.json ~headers:[("Cache-Control", "no-store")] 176 @@ Yojson.Safe.to_string
+5 -3
pegasus/lib/oauth/queries.ml
··· 103 record_out] 104 ~refresh_token 105 106 - let update_oauth_token conn ~old_refresh_token ~new_refresh_token ~expires_at = 107 Util.use_pool conn 108 @@ [%rapper 109 execute 110 {sql| 111 UPDATE oauth_tokens 112 SET refresh_token = %string{new_refresh_token}, 113 - expires_at = %int{expires_at} 114 WHERE refresh_token = %string{old_refresh_token} 115 |sql}] 116 - ~new_refresh_token ~expires_at ~old_refresh_token 117 118 let delete_oauth_token_by_refresh conn refresh_token = 119 Util.use_pool conn
··· 103 record_out] 104 ~refresh_token 105 106 + let update_oauth_token conn ~old_refresh_token ~new_refresh_token ~expires_at 107 + ~ip ~user_agent = 108 Util.use_pool conn 109 @@ [%rapper 110 execute 111 {sql| 112 UPDATE oauth_tokens 113 SET refresh_token = %string{new_refresh_token}, 114 + expires_at = %int{expires_at}, last_ip = %string{ip}, 115 + last_user_agent = %string?{user_agent} 116 WHERE refresh_token = %string{old_refresh_token} 117 |sql}] 118 + ~new_refresh_token ~expires_at ~old_refresh_token ~ip ~user_agent 119 120 let delete_oauth_token_by_refresh conn refresh_token = 121 Util.use_pool conn
+84
pegasus/lib/session.ml
···
··· 1 + type data = 2 + { current_did: string option [@default None] 3 + ; logged_in_dids: string list [@default []] } 4 + [@@deriving yojson {strict= false}] 5 + 6 + let default = {current_did= None; logged_in_dids= []} 7 + 8 + module Raw = struct 9 + let set_session req data = 10 + Dream.set_session_field req "pegasus.session" 11 + (data_to_yojson data |> Yojson.Safe.to_string) 12 + 13 + let get_session req = 14 + match Dream.session_field req "pegasus.session" with 15 + | Some data -> ( 16 + match 17 + data_of_yojson (try Yojson.Safe.from_string data with _ -> `Null) 18 + with 19 + | Ok data -> 20 + Lwt.return_some data 21 + | Error _ -> 22 + let%lwt () = set_session req default in 23 + Lwt.return_some default ) 24 + | None -> 25 + Lwt.return_none 26 + 27 + let clear_session req = Dream.set_session_field req "pegasus.session" "" 28 + 29 + let get_current_did req = 30 + match%lwt get_session req with 31 + | Some {current_did; _} when current_did <> None -> 32 + Lwt.return current_did 33 + | _ -> 34 + Lwt.return_none 35 + 36 + let set_current_did req did = 37 + match%lwt get_session req with 38 + | Some {logged_in_dids; _} -> 39 + let%lwt () = set_session req {current_did= Some did; logged_in_dids} in 40 + Lwt.return_unit 41 + | None -> 42 + Lwt.return_unit 43 + 44 + let get_logged_in_dids req = 45 + match%lwt get_session req with 46 + | Some {logged_in_dids; _} -> 47 + Lwt.return logged_in_dids 48 + | None -> 49 + Lwt.return [] 50 + 51 + let set_logged_in_dids req dids = 52 + match%lwt get_session req with 53 + | Some {current_did; _} -> 54 + let%lwt () = set_session req {current_did; logged_in_dids= dids} in 55 + Lwt.return_unit 56 + | None -> 57 + Lwt.return_unit 58 + end 59 + 60 + open Raw 61 + 62 + let log_in_did ?(set_current = true) req did = 63 + match%lwt get_session req with 64 + | Some {current_did; logged_in_dids} -> 65 + let%lwt () = 66 + set_session req 67 + { current_did= (if set_current then Some did else current_did) 68 + ; logged_in_dids= did :: logged_in_dids } 69 + in 70 + Lwt.return_unit 71 + | None -> 72 + Lwt.return_unit 73 + 74 + let log_out_did req did = 75 + match%lwt get_session req with 76 + | Some {current_did; logged_in_dids} -> 77 + let%lwt () = 78 + set_session req 79 + { current_did 80 + ; logged_in_dids= List.filter (fun d -> d <> did) logged_in_dids } 81 + in 82 + Lwt.return_unit 83 + | None -> 84 + Lwt.return_unit