backend/config/auth/
user_info.rs1use actix_http::{HttpMessage, StatusCode};
4use actix_utils::future::{ready, Ready};
5use actix_web::FromRequest;
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use crate::{config::app::Mode, error::ServiceError};
10
11use super::claims::Claims;
12
13#[derive(Debug, Clone, Deserialize)]
15pub struct UserInfo {
16 pub id: Uuid,
18 pub scopes: Vec<String>,
20 pub roles: Vec<Role>,
22 pub mode: Mode,
24}
25
26#[derive(Debug, Clone, Deserialize, Serialize)]
28pub enum Role {
29 Member,
31 Testing,
33 Admin,
35}
36
37impl UserInfo {
38 #[must_use]
40 pub fn is_member(&self) -> bool {
41 self.roles.iter().any(|role| matches!(role, Role::Member))
42 }
43
44 #[must_use]
46 pub fn is_admin(&self) -> bool {
47 match self.mode {
48 Mode::Production => self.roles.iter().any(|role| matches!(role, Role::Admin)),
49 Mode::Testing => self
50 .roles
51 .iter()
52 .any(|role| matches!(role, Role::Admin | Role::Testing)),
53 }
54 }
55}
56
57impl Role {
58 #[must_use]
60 pub fn from_string(str: &str) -> Option<Self> {
61 match str {
62 "/Member" => Some(Self::Member),
63 "/Testing" => Some(Self::Testing),
64 "/Admin" => Some(Self::Admin),
65 _ => None,
66 }
67 }
68}
69
70impl From<(Claims, Mode)> for UserInfo {
73 fn from((value, mode): (Claims, Mode)) -> Self {
74 let roles = value.groups.map_or_else(Vec::new, |groups| {
75 groups
76 .into_iter()
77 .filter_map(|s| Role::from_string(&s))
78 .collect::<Vec<_>>()
79 });
80
81 Self {
82 id: value.sub,
83 scopes: value.scope.split(' ').map(str::to_owned).collect(),
84 roles,
85 mode,
86 }
87 }
88}
89
90impl FromRequest for UserInfo {
91 type Future = Ready<Result<Self, Self::Error>>;
92 type Error = ServiceError;
93
94 fn from_request(
95 req: &actix_web::HttpRequest,
96 _payload: &mut actix_http::Payload,
97 ) -> Self::Future {
98 let extensions = req.extensions();
99 ready({
100 extensions.get::<Self>().map_or_else(
101 || {
102 Err(ServiceError::new(
103 StatusCode::INTERNAL_SERVER_ERROR,
104 &StatusCode::INTERNAL_SERVER_ERROR.to_string(),
105 ))
106 },
107 |user_info| Ok(user_info.clone()),
108 )
109 })
110 }
111}