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