scufflecloud_core/services/
sessions.rs1use base64::Engine;
2use ext_traits::{OptionExt, RequestExt};
3use sha2::Digest;
4
5use crate::google_api;
6use crate::http_ext::CoreRequestExt;
7use crate::operations::Operation;
8use crate::operations::user_sessions::{InvalidateUserSessionRequest, RefreshUserSessionRequest};
9use crate::services::CoreSvc;
10
11#[async_trait::async_trait]
12impl<G: core_traits::Global> pb::scufflecloud::core::v1::sessions_service_server::SessionsService for CoreSvc<G> {
13 async fn login_with_magic_link(
14 &self,
15 req: tonic::Request<pb::scufflecloud::core::v1::LoginWithMagicLinkRequest>,
16 ) -> Result<tonic::Response<()>, tonic::Status> {
17 Operation::<G>::run(req).await.map(tonic::Response::new)
18 }
19
20 async fn complete_login_with_magic_link(
21 &self,
22 req: tonic::Request<pb::scufflecloud::core::v1::CompleteLoginWithMagicLinkRequest>,
23 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::NewUserSessionToken>, tonic::Status> {
24 Operation::<G>::run(req).await.map(tonic::Response::new)
25 }
26
27 async fn login_with_email_and_password(
28 &self,
29 req: tonic::Request<pb::scufflecloud::core::v1::LoginWithEmailAndPasswordRequest>,
30 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::NewUserSessionToken>, tonic::Status> {
31 Operation::<G>::run(req).await.map(tonic::Response::new)
32 }
33
34 async fn login_with_google(
35 &self,
36 req: tonic::Request<pb::scufflecloud::core::v1::LoginWithGoogleRequest>,
37 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::LoginWithGoogleResponse>, tonic::Status> {
38 let global = &req.global::<G>()?;
39 let dashboard_origin = req.dashboard_origin::<G>()?;
40 let payload = req.into_inner();
41
42 let device = payload.device.require("device")?;
43 let device_fingerprint = sha2::Sha256::digest(&device.public_key_data);
44 let state = base64::prelude::BASE64_URL_SAFE.encode(device_fingerprint);
45
46 let authorization_url = google_api::authorization_url(global, &dashboard_origin, &state);
47
48 Ok(tonic::Response::new(pb::scufflecloud::core::v1::LoginWithGoogleResponse {
49 authorization_url,
50 }))
51 }
52
53 async fn complete_login_with_google(
54 &self,
55 req: tonic::Request<pb::scufflecloud::core::v1::CompleteLoginWithGoogleRequest>,
56 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::CompleteLoginWithGoogleResponse>, tonic::Status> {
57 Operation::<G>::run(req).await.map(tonic::Response::new)
58 }
59
60 async fn login_with_webauthn(
61 &self,
62 req: tonic::Request<pb::scufflecloud::core::v1::LoginWithWebauthnRequest>,
63 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::NewUserSessionToken>, tonic::Status> {
64 Operation::<G>::run(req).await.map(tonic::Response::new)
65 }
66
67 async fn create_user_session_request(
68 &self,
69 req: tonic::Request<pb::scufflecloud::core::v1::CreateUserSessionRequestRequest>,
70 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::UserSessionRequest>, tonic::Status> {
71 Operation::<G>::run(req).await.map(tonic::Response::new)
72 }
73
74 async fn get_user_session_request(
75 &self,
76 req: tonic::Request<pb::scufflecloud::core::v1::GetUserSessionRequestRequest>,
77 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::UserSessionRequest>, tonic::Status> {
78 Operation::<G>::run(req).await.map(tonic::Response::new)
79 }
80
81 async fn get_user_session_request_by_code(
82 &self,
83 req: tonic::Request<pb::scufflecloud::core::v1::GetUserSessionRequestByCodeRequest>,
84 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::UserSessionRequest>, tonic::Status> {
85 Operation::<G>::run(req).await.map(tonic::Response::new)
86 }
87
88 async fn approve_user_session_request_by_code(
89 &self,
90 req: tonic::Request<pb::scufflecloud::core::v1::ApproveUserSessionRequestByCodeRequest>,
91 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::UserSessionRequest>, tonic::Status> {
92 Operation::<G>::run(req).await.map(tonic::Response::new)
93 }
94
95 async fn complete_user_session_request(
96 &self,
97 req: tonic::Request<pb::scufflecloud::core::v1::CompleteUserSessionRequestRequest>,
98 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::NewUserSessionToken>, tonic::Status> {
99 Operation::<G>::run(req).await.map(tonic::Response::new)
100 }
101
102 async fn validate_mfa_for_user_session(
103 &self,
104 req: tonic::Request<pb::scufflecloud::core::v1::ValidateMfaForUserSessionRequest>,
105 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::UserSession>, tonic::Status> {
106 Operation::<G>::run(req).await.map(tonic::Response::new)
107 }
108
109 async fn refresh_user_session(
110 &self,
111 req: tonic::Request<()>,
112 ) -> Result<tonic::Response<pb::scufflecloud::core::v1::NewUserSessionToken>, tonic::Status> {
113 let (metadata, extensions, _) = req.into_parts();
114 let req = tonic::Request::from_parts(metadata, extensions, RefreshUserSessionRequest);
115 Operation::<G>::run(req).await.map(tonic::Response::new)
116 }
117
118 async fn invalidate_user_session(&self, req: tonic::Request<()>) -> Result<tonic::Response<()>, tonic::Status> {
119 let (metadata, extensions, _) = req.into_parts();
120 let req = tonic::Request::from_parts(metadata, extensions, InvalidateUserSessionRequest);
121 Operation::<G>::run(req).await.map(tonic::Response::new)
122 }
123}