userinfo.rs
1 use rocket::{serde::json::Json, State}; 2 use serde::Serialize; 3 use serde_with::skip_serializing_none; 4 use sqlx::Pool; 5 6 use crate::{ 7 api::auth::access_token_guard::AccessTokenAuth, 8 db::DB, 9 models::oauth_scope::OauthScope, 10 services::user_info_service::{self, UserInfoError}, 11 }; 12 13 #[skip_serializing_none] 14 #[derive(Serialize, Debug, Clone)] 15 pub struct Userinfo { 16 #[serde(rename = "sub")] 17 pub subject: String, 18 pub name: Option<String>, 19 pub given_name: Option<String>, 20 pub family_name: Option<String>, 21 pub email: Option<String>, 22 pub email_verified: Option<bool>, 23 } 24 25 #[derive(Responder, Debug)] 26 pub enum UserinfoResponse { 27 #[response(status = 200)] 28 Success(Json<Userinfo>), 29 #[response(status = 401)] 30 Unauthorized(String), 31 #[response(status = 500)] 32 Failure(String), 33 } 34 35 #[get("/userinfo")] 36 pub async fn get_userinfo( 37 access_token: AccessTokenAuth, 38 db_pool: &State<Pool<DB>>, 39 ) -> UserinfoResponse { 40 let user_info = 41 match user_info_service::get_user_info(db_pool, &access_token.access_token).await { 42 Ok(user_info) => user_info, 43 Err(UserInfoError::InvalidAccessToken) => { 44 return UserinfoResponse::Unauthorized("Invalid access token".to_string()) 45 } 46 Err(err) => { 47 error!("Failed to get user info {}", err); 48 return UserinfoResponse::Failure("An unknown error occurred".to_string()); 49 } 50 }; 51 52 let email_scope = if access_token.access_token.has_scope(&OauthScope::Email) { 53 Some(&user_info) 54 } else { 55 None 56 }; 57 58 let profile_scope = if access_token.access_token.has_scope(&OauthScope::Profile) { 59 Some(&user_info) 60 } else { 61 None 62 }; 63 64 UserinfoResponse::Success(Json(Userinfo { 65 subject: access_token.access_token.account_id.to_string(), 66 email: email_scope.map(|e| e.email.clone()), 67 email_verified: email_scope.map(|_| true), 68 name: profile_scope.map(|s| s.get_name()), 69 given_name: profile_scope.map(|s| s.account.first_name.clone()), 70 family_name: profile_scope.map(|s| s.account.last_name.clone()), 71 })) 72 }