backend/config/auth/
user_info.rs1use actix_http::{HttpMessage, StatusCode};
4use actix_utils::future::{ready, Ready};
5use actix_web::FromRequest;
6use serde::Deserialize;
7use uuid::Uuid;
8
9use crate::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}
23
24#[derive(Debug, Clone, Deserialize)]
26pub enum Role {
27 Member,
29}
30
31impl UserInfo {
32 #[must_use]
34 pub fn is_member(&self) -> bool {
35 self.roles.iter().any(|role| matches!(role, Role::Member))
36 }
37}
38
39impl Role {
40 #[must_use]
42 pub fn from_string(str: &str) -> Option<Self> {
43 match str {
44 "member" => Some(Self::Member),
45 _ => None,
46 }
47 }
48}
49
50impl From<Claims> for UserInfo {
53 fn from(value: Claims) -> Self {
54 let roles = match value.realm_access {
55 Some(realm_access) => realm_access
56 .roles
57 .into_iter()
58 .filter_map(|s| Role::from_string(&s))
59 .collect::<Vec<_>>(),
60 None => Vec::new(),
61 };
62
63 Self {
64 id: value.sub,
65 scopes: value.scope.split(' ').map(str::to_owned).collect(),
66 roles,
67 }
68 }
69}
70
71impl FromRequest for UserInfo {
72 type Future = Ready<Result<Self, Self::Error>>;
73 type Error = ServiceError;
74
75 fn from_request(
76 req: &actix_web::HttpRequest,
77 _payload: &mut actix_http::Payload,
78 ) -> Self::Future {
79 let extensions = req.extensions();
80 ready({
81 extensions.get::<Self>().map_or_else(
82 || {
83 Err(ServiceError::new(
84 StatusCode::INTERNAL_SERVER_ERROR,
85 &StatusCode::INTERNAL_SERVER_ERROR.to_string(),
86 ))
87 },
88 |user_info| Ok(user_info.clone()),
89 )
90 })
91 }
92}