shared/models/user/
auth.rs1use crate::response::ApiResponse;
2use axum::http::StatusCode;
3use std::{
4 ops::{Deref, DerefMut},
5 sync::Arc,
6};
7
8#[derive(Clone)]
9pub enum AuthMethod {
10 Session(crate::models::user_session::UserSession),
11 ApiKey(crate::models::user_api_key::UserApiKey),
12}
13
14#[derive(Clone)]
15pub struct UserImpersonator(pub super::User);
16
17impl Deref for UserImpersonator {
18 type Target = super::User;
19
20 fn deref(&self) -> &Self::Target {
21 &self.0
22 }
23}
24
25impl DerefMut for UserImpersonator {
26 fn deref_mut(&mut self) -> &mut Self::Target {
27 &mut self.0
28 }
29}
30
31pub type GetUser = crate::extract::ConsumingExtension<super::User>;
32pub type GetUserImpersonator = crate::extract::ConsumingExtension<Option<UserImpersonator>>;
33pub type GetAuthMethod = crate::extract::ConsumingExtension<AuthMethod>;
34pub type GetPermissionManager = axum::extract::Extension<PermissionManager>;
35
36#[derive(Clone)]
37pub struct PermissionManager {
38 user_admin: bool,
39 user_server_owner: bool,
40 role_admin_permissions: Option<Arc<Vec<compact_str::CompactString>>>,
41 role_server_permissions: Option<Arc<Vec<compact_str::CompactString>>>,
42 api_key_user_permissions: Option<Arc<Vec<compact_str::CompactString>>>,
43 api_key_admin_permissions: Option<Arc<Vec<compact_str::CompactString>>>,
44 api_key_server_permissions: Option<Arc<Vec<compact_str::CompactString>>>,
45 server_subuser_permissions: Option<Arc<Vec<compact_str::CompactString>>>,
46}
47
48impl PermissionManager {
49 pub fn new(user: &super::User) -> Self {
50 Self {
51 user_admin: user.admin,
52 user_server_owner: false,
53 role_admin_permissions: user.role.as_ref().map(|r| r.admin_permissions.clone()),
54 role_server_permissions: user.role.as_ref().map(|r| r.server_permissions.clone()),
55 api_key_user_permissions: None,
56 api_key_admin_permissions: None,
57 api_key_server_permissions: None,
58 server_subuser_permissions: None,
59 }
60 }
61
62 pub fn add_api_key(mut self, api_key: &crate::models::user_api_key::UserApiKey) -> Self {
63 self.api_key_user_permissions = Some(api_key.user_permissions.clone());
64 self.api_key_admin_permissions = Some(api_key.admin_permissions.clone());
65 self.api_key_server_permissions = Some(api_key.server_permissions.clone());
66 self
67 }
68
69 pub fn set_user_server_owner(mut self, is_owner: bool) -> Self {
70 self.user_server_owner = is_owner;
71 self
72 }
73
74 pub fn add_subuser_permissions(
75 mut self,
76 permissions: Option<Arc<Vec<compact_str::CompactString>>>,
77 ) -> Self {
78 self.server_subuser_permissions = permissions;
79 self
80 }
81
82 pub fn has_user_permission(&self, permission: &str) -> Result<(), ApiResponse> {
83 if let Some(api_key_permissions) = &self.api_key_user_permissions
84 && !api_key_permissions.iter().any(|p| p == permission)
85 {
86 return Err(ApiResponse::error(format!(
87 "you do not have permission to perform this action: {permission}"
88 ))
89 .with_status(StatusCode::FORBIDDEN));
90 }
91
92 Ok(())
93 }
94
95 pub fn has_admin_permission(&self, permission: &str) -> Result<(), ApiResponse> {
96 let is_admin = self.user_admin;
97 let has_role_perm = self
98 .role_admin_permissions
99 .as_ref()
100 .is_some_and(|perms| perms.iter().any(|p| p == permission));
101
102 let has_base_permission = is_admin || has_role_perm;
103
104 if !has_base_permission {
105 return Err(ApiResponse::error(format!(
106 "you do not have permission to perform this action: {permission}"
107 ))
108 .with_status(StatusCode::FORBIDDEN));
109 }
110
111 if let Some(api_key_permissions) = &self.api_key_admin_permissions
112 && !api_key_permissions.iter().any(|p| p == permission)
113 {
114 return Err(ApiResponse::error(format!(
115 "you do not have permission to perform this action: {permission}"
116 ))
117 .with_status(StatusCode::FORBIDDEN));
118 }
119
120 Ok(())
121 }
122
123 pub fn has_server_permission(&self, permission: &str) -> Result<(), ApiResponse> {
124 let is_admin = self.user_admin;
125
126 let has_role_perm = self
127 .role_server_permissions
128 .as_ref()
129 .is_some_and(|perms| perms.iter().any(|p| p == permission));
130
131 let is_owner = self.user_server_owner;
132
133 let has_subuser_perm = self
134 .server_subuser_permissions
135 .as_ref()
136 .is_some_and(|perms| perms.iter().any(|p| p == permission));
137
138 let has_base_permission = is_admin || has_role_perm || is_owner || has_subuser_perm;
139
140 if !has_base_permission {
141 return Err(ApiResponse::error(format!(
142 "you do not have permission to perform this action: {permission}"
143 ))
144 .with_status(StatusCode::FORBIDDEN));
145 }
146
147 if let Some(api_key_permissions) = &self.api_key_server_permissions
148 && !api_key_permissions.iter().any(|p| p == permission)
149 {
150 return Err(ApiResponse::error(format!(
151 "you do not have permission to perform this action: {permission}"
152 ))
153 .with_status(StatusCode::FORBIDDEN));
154 }
155
156 Ok(())
157 }
158}