/ backend / src / api / openid / userinfo.rs
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  }