1use crate::errors::{AuthError, Result};
7use role_system::{
8 Permission, Resource, Role, Subject,
9 async_support::{AsyncRoleSystem, AsyncRoleSystemBuilder},
10 storage::{MemoryStorage, Storage},
11};
12use std::collections::HashMap;
13use tracing::{debug, info, warn};
14
15pub struct AuthorizationService<S = MemoryStorage>
17where
18 S: Storage + Send + Sync,
19{
20 pub role_system: AsyncRoleSystem<S>,
22
23 config: AuthorizationConfig,
26}
27
28#[derive(Debug, Clone)]
30pub struct AuthorizationConfig {
31 pub enable_audit: bool,
33
34 pub enable_caching: bool,
36
37 pub cache_ttl_seconds: u64,
39
40 pub max_hierarchy_depth: usize,
42}
43
44impl Default for AuthorizationConfig {
45 fn default() -> Self {
46 Self {
47 enable_audit: true,
48 enable_caching: true,
49 cache_ttl_seconds: 300, max_hierarchy_depth: 10,
51 }
52 }
53}
54
55impl AuthorizationService<MemoryStorage> {
56 pub async fn new() -> Result<Self> {
58 Self::with_config(AuthorizationConfig::default()).await
59 }
60
61 pub async fn with_config(config: AuthorizationConfig) -> Result<Self> {
63 let storage = MemoryStorage::new();
64
65 let role_system = AsyncRoleSystemBuilder::new().build_with_storage(storage);
67
68 let service = Self {
69 role_system,
70 config,
71 };
72
73 service.initialize_authframework_roles().await?;
75
76 info!("AuthorizationService initialized with enhanced RBAC");
77 Ok(service)
78 }
79}
80
81impl<S> AuthorizationService<S>
82where
83 S: Storage + Send + Sync + Default,
84{
85 pub async fn with_storage(storage: S, config: AuthorizationConfig) -> Result<Self> {
87 let role_system = AsyncRoleSystemBuilder::new().build_with_storage(storage);
89
90 let service = Self {
91 role_system,
92 config,
93 };
94
95 service.initialize_authframework_roles().await?;
96
97 info!("AuthorizationService initialized with custom storage");
98 Ok(service)
99 }
100
101 async fn initialize_authframework_roles(&self) -> Result<()> {
103 info!("Initializing AuthFramework standard roles");
104
105 let guest_role = Role::new("guest")
107 .with_description("Unauthenticated user with minimal access")
108 .add_permission(Permission::new("read", "public"));
109
110 let user_role = Role::new("user")
112 .with_description("Authenticated user")
113 .add_permission(Permission::new("read", "profile"))
114 .add_permission(Permission::new("update", "profile:own"))
115 .add_permission(Permission::new("read", "public"));
116
117 let moderator_role = Role::new("moderator")
119 .with_description("Content moderator")
120 .add_permission(Permission::new("read", "*"))
121 .add_permission(Permission::new("update", "content"))
122 .add_permission(Permission::new("delete", "content"));
123
124 let admin_role = Role::new("admin")
126 .with_description("System administrator")
127 .add_permission(Permission::super_admin());
128
129 self.role_system
131 .register_role(guest_role)
132 .await
133 .map_err(|e| {
134 AuthError::authorization(format!("Failed to register guest role: {}", e))
135 })?;
136
137 self.role_system
138 .register_role(user_role)
139 .await
140 .map_err(|e| {
141 AuthError::authorization(format!("Failed to register user role: {}", e))
142 })?;
143
144 self.role_system
145 .register_role(moderator_role)
146 .await
147 .map_err(|e| {
148 AuthError::authorization(format!("Failed to register moderator role: {}", e))
149 })?;
150
151 self.role_system
152 .register_role(admin_role)
153 .await
154 .map_err(|e| {
155 AuthError::authorization(format!("Failed to register admin role: {}", e))
156 })?;
157
158 self.role_system
160 .add_role_inheritance("admin", "moderator")
161 .await
162 .map_err(|e| {
163 AuthError::authorization(format!(
164 "Failed to set admin->moderator inheritance: {}",
165 e
166 ))
167 })?;
168
169 self.role_system
170 .add_role_inheritance("moderator", "user")
171 .await
172 .map_err(|e| {
173 AuthError::authorization(format!(
174 "Failed to set moderator->user inheritance: {}",
175 e
176 ))
177 })?;
178
179 self.role_system
180 .add_role_inheritance("user", "guest")
181 .await
182 .map_err(|e| {
183 AuthError::authorization(format!("Failed to set user->guest inheritance: {}", e))
184 })?;
185
186 info!("AuthFramework standard roles initialized successfully");
187 Ok(())
188 }
189
190 pub async fn check_permission(
192 &self,
193 user_id: &str,
194 action: &str,
195 resource_type: &str,
196 context: Option<&HashMap<String, String>>,
197 ) -> Result<bool> {
198 debug!(
199 "Checking permission for user '{}': {}:{}",
200 user_id, action, resource_type
201 );
202
203 let subject = Subject::user(user_id);
204 let resource = Resource::new("", resource_type); let result = if let Some(context) = context {
208 self.role_system
209 .check_permission_with_context(&subject, action, &resource, context)
210 .await
211 } else {
212 self.role_system
213 .check_permission(&subject, action, &resource)
214 .await
215 };
216
217 if self.config.enable_audit {
219 info!(
220 target: "authorization_audit",
221 user_id = user_id,
222 action = action,
223 resource_type = resource_type,
224 permission_granted = result.is_ok() && *result.as_ref().unwrap_or(&false),
225 timestamp = chrono::Utc::now().to_rfc3339(),
226 "Permission check performed"
227 );
228 }
229
230 match result {
231 Ok(granted) => {
232 debug!("Permission check result: {}", granted);
233 Ok(granted)
234 }
235 Err(e) => {
236 warn!("Permission check failed: {}", e);
237 Err(AuthError::authorization(format!(
238 "Permission check failed: {}",
239 e
240 )))
241 }
242 }
243 }
244
245 pub async fn check_api_permission(
247 &self,
248 user_id: &str,
249 method: &str,
250 endpoint: &str,
251 context: &HashMap<String, String>,
252 ) -> Result<bool> {
253 let action = match method.to_uppercase().as_str() {
255 "GET" => "read",
256 "POST" => "create",
257 "PUT" | "PATCH" => "update",
258 "DELETE" => "delete",
259 _ => "access",
260 };
261
262 self.check_permission(user_id, action, endpoint, Some(context))
263 .await
264 }
265
266 pub async fn assign_role(&self, user_id: &str, role_name: &str) -> Result<()> {
268 debug!("Assigning role '{}' to user '{}'", role_name, user_id);
269
270 let subject = Subject::user(user_id);
271
272 self.role_system
273 .assign_role(&subject, role_name)
274 .await
275 .map_err(|e| AuthError::authorization(format!("Failed to assign role: {}", e)))?;
276
277 info!("Role '{}' assigned to user '{}'", role_name, user_id);
278 Ok(())
279 }
280
281 pub async fn remove_role(&self, user_id: &str, role_name: &str) -> Result<()> {
283 debug!("Removing role '{}' from user '{}'", role_name, user_id);
284
285 let subject = Subject::user(user_id);
286
287 self.role_system
288 .remove_role(&subject, role_name)
289 .await
290 .map_err(|e| AuthError::authorization(format!("Failed to remove role: {}", e)))?;
291
292 info!("Role '{}' removed from user '{}'", role_name, user_id);
293 Ok(())
294 }
295
296 pub async fn elevate_role(
298 &self,
299 user_id: &str,
300 role_name: &str,
301 duration_seconds: Option<u64>,
302 ) -> Result<()> {
303 debug!(
304 "Elevating user '{}' to role '{}' for {:?} seconds",
305 user_id, role_name, duration_seconds
306 );
307
308 let subject = Subject::user(user_id);
309 let duration = duration_seconds.map(std::time::Duration::from_secs);
310
311 self.role_system
312 .elevate_role(&subject, role_name, duration)
313 .await
314 .map_err(|e| AuthError::authorization(format!("Failed to elevate role: {}", e)))?;
315
316 info!(
317 "User '{}' elevated to role '{}' for {:?} seconds",
318 user_id, role_name, duration_seconds
319 );
320 Ok(())
321 }
322
323 pub async fn get_user_roles(&self, user_id: &str) -> Result<Vec<String>> {
325 let subject = Subject::user(user_id);
326
327 let roles = self
328 .role_system
329 .get_subject_roles(&subject)
330 .await
331 .map_err(|e| AuthError::authorization(format!("Failed to get user roles: {}", e)))?;
332
333 Ok(roles.into_iter().collect())
334 }
335
336 pub async fn create_role(
338 &self,
339 name: &str,
340 description: &str,
341 permissions: Vec<Permission>,
342 parent_roles: Option<Vec<String>>,
343 ) -> Result<()> {
344 debug!(
345 "Creating role '{}' with {} permissions",
346 name,
347 permissions.len()
348 );
349
350 let mut role = Role::new(name).with_description(description);
351
352 for permission in permissions {
353 role = role.add_permission(permission);
354 }
355
356 self.role_system
357 .register_role(role)
358 .await
359 .map_err(|e| AuthError::authorization(format!("Failed to create role: {}", e)))?;
360
361 if let Some(parents) = parent_roles {
363 for parent in parents {
364 self.role_system
365 .add_role_inheritance(name, &parent)
366 .await
367 .map_err(|e| {
368 AuthError::authorization(format!("Failed to set role inheritance: {}", e))
369 })?;
370 }
371 }
372
373 info!("Role '{}' created successfully", name);
374 Ok(())
375 }
376
377 pub async fn get_role_hierarchy(&self, role_id: &str) -> Result<Vec<String>> {
379 if let Ok(Some(role)) = self.role_system.get_role(role_id).await {
381 let mut result = vec![role.id().to_string()];
382 if let Some(parent_id) = role.parent_role_id() {
383 result.push(parent_id.to_string());
384 }
385 Ok(result)
386 } else {
387 Ok(vec![])
388 }
389 }
390
391 pub async fn get_role_metadata(&self, role_id: &str) -> Result<String> {
393 if let Ok(Some(role)) = self.role_system.get_role(role_id).await {
394 let depth = role.hierarchy_depth();
395 let is_root = role.is_root_role();
396 let is_leaf = role.is_leaf_role();
397 let children = role.child_role_ids();
398
399 Ok(format!(
400 "Role '{}': depth={}, root={}, leaf={}, children={:?}",
401 role.name(),
402 depth,
403 is_root,
404 is_leaf,
405 children
406 ))
407 } else {
408 Err(AuthError::authorization("Role not found".to_string()))
409 }
410 }
411
412 pub async fn delete_role(&self, _name: &str) -> Result<()> {
414 warn!("Role deletion not yet implemented in role-system v1.0");
417 Err(AuthError::authorization(
418 "Role deletion not supported yet".to_string(),
419 ))
420 }
421
422 pub async fn get_role(&self, name: &str) -> Result<Option<Role>> {
424 self.role_system
425 .get_role(name)
426 .await
427 .map_err(|e| AuthError::authorization(format!("Failed to get role: {}", e)))
428 }
429
430 pub async fn batch_check_permissions(
432 &self,
433 user_id: &str,
434 checks: &[(String, String)], ) -> Result<Vec<(String, String, bool)>> {
436 let subject = Subject::user(user_id);
437
438 let resource_checks: Vec<(String, Resource)> = checks
439 .iter()
440 .map(|(action, resource)| (action.clone(), Resource::new(resource, "api")))
441 .collect();
442
443 let results = self
444 .role_system
445 .batch_check_permissions(&subject, &resource_checks)
446 .await
447 .map_err(|e| {
448 AuthError::authorization(format!("Batch permission check failed: {}", e))
449 })?;
450
451 Ok(results
452 .into_iter()
453 .map(|(action, resource, granted)| {
454 (
455 action,
456 resource.name().unwrap_or("unknown").to_string(),
457 granted,
458 )
459 })
460 .collect())
461 }
462}
463
464#[cfg(test)]
465mod tests {
466 use super::*;
467
468 #[tokio::test]
469 async fn test_authorization_service_creation() {
470 let service = AuthorizationService::new().await.unwrap();
471
472 let roles = ["guest", "user", "moderator", "admin"];
474 for role_name in &roles {
475 let role = service.get_role(role_name).await.unwrap();
476 assert!(role.is_some(), "Role '{}' should exist", role_name);
477 }
478 }
479
480 #[tokio::test]
481 async fn test_role_assignment_and_permission_check() {
482 let service = AuthorizationService::new().await.unwrap();
483
484 service.assign_role("test_user", "user").await.unwrap();
486
487 let can_read_profile = service
489 .check_permission("test_user", "read", "profile", None)
490 .await
491 .unwrap();
492 assert!(can_read_profile, "User should have read access to profile");
493
494 let can_admin = service
495 .check_permission("test_user", "admin", "system", None)
496 .await
497 .unwrap();
498 assert!(!can_admin);
499 }
500
501 #[tokio::test]
502 async fn test_role_hierarchy() {
503 let service = AuthorizationService::new().await.unwrap();
504
505 service.assign_role("admin_user", "admin").await.unwrap();
507
508 let can_read_profile = service
510 .check_permission("admin_user", "read", "profile", None)
511 .await
512 .unwrap();
513 assert!(can_read_profile);
514
515 let can_admin = service
517 .check_permission("admin_user", "admin", "system", None)
518 .await
519 .unwrap();
520 assert!(can_admin);
521 }
522}