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, sync::Arc};
13use tokio::sync::Mutex as TokioMutex;
14use tracing::{debug, info, warn};
15
16pub struct AuthorizationService<S = MemoryStorage>
18where
19 S: Storage + Send + Sync + Clone,
20{
21 pub role_system: AsyncRoleSystem<S>,
23
24 config: AuthorizationConfig,
26
27 storage_handle: Arc<TokioMutex<S>>,
34}
35
36#[derive(Debug, Clone)]
38pub struct AuthorizationConfig {
39 pub enable_audit: bool,
41
42 pub enable_caching: bool,
44
45 pub cache_ttl_seconds: u64,
47
48 pub max_hierarchy_depth: usize,
50}
51
52impl Default for AuthorizationConfig {
53 fn default() -> Self {
54 Self {
55 enable_audit: true,
56 enable_caching: true,
57 cache_ttl_seconds: 300, max_hierarchy_depth: 10,
59 }
60 }
61}
62
63impl AuthorizationService<MemoryStorage> {
64 pub async fn new() -> Result<Self> {
66 Self::with_config(AuthorizationConfig::default()).await
67 }
68
69 pub async fn with_config(config: AuthorizationConfig) -> Result<Self> {
71 let storage = MemoryStorage::new();
72 let storage_handle = Arc::new(TokioMutex::new(storage.clone()));
75
76 let role_system = AsyncRoleSystemBuilder::new().build_with_storage(storage);
77
78 let service = Self {
79 role_system,
80 config,
81 storage_handle,
82 };
83
84 service.initialize_authframework_roles().await?;
86
87 info!("AuthorizationService initialized with enhanced RBAC");
88 Ok(service)
89 }
90}
91
92impl<S> AuthorizationService<S>
93where
94 S: Storage + Send + Sync + Clone + Default,
95{
96 pub async fn with_storage(storage: S, config: AuthorizationConfig) -> Result<Self> {
98 let storage_handle = Arc::new(TokioMutex::new(storage.clone()));
99 let role_system = AsyncRoleSystemBuilder::new().build_with_storage(storage);
101
102 let service = Self {
103 role_system,
104 config,
105 storage_handle,
106 };
107
108 service.initialize_authframework_roles().await?;
109
110 info!("AuthorizationService initialized with custom storage");
111 Ok(service)
112 }
113
114 async fn initialize_authframework_roles(&self) -> Result<()> {
116 info!("Initializing AuthFramework standard roles");
117
118 let guest_role = Role::new("guest")
120 .with_description("Unauthenticated user with minimal access")
121 .add_permission(Permission::new("read", "public"));
122
123 let user_role = Role::new("user")
125 .with_description("Authenticated user")
126 .add_permission(Permission::new("read", "profile"))
127 .add_permission(Permission::new("update", "profile:own"))
128 .add_permission(Permission::new("read", "public"));
129
130 let moderator_role = Role::new("moderator")
132 .with_description("Content moderator")
133 .add_permission(Permission::new("read", "*"))
134 .add_permission(Permission::new("update", "content"))
135 .add_permission(Permission::new("delete", "content"));
136
137 let admin_role = Role::new("admin")
139 .with_description("System administrator")
140 .add_permission(Permission::super_admin());
141
142 self.role_system
144 .register_role(guest_role)
145 .await
146 .map_err(|e| {
147 AuthError::authorization(format!("Failed to register guest role: {}", e))
148 })?;
149
150 self.role_system
151 .register_role(user_role)
152 .await
153 .map_err(|e| {
154 AuthError::authorization(format!("Failed to register user role: {}", e))
155 })?;
156
157 self.role_system
158 .register_role(moderator_role)
159 .await
160 .map_err(|e| {
161 AuthError::authorization(format!("Failed to register moderator role: {}", e))
162 })?;
163
164 self.role_system
165 .register_role(admin_role)
166 .await
167 .map_err(|e| {
168 AuthError::authorization(format!("Failed to register admin role: {}", e))
169 })?;
170
171 self.role_system
173 .add_role_inheritance("admin", "moderator")
174 .await
175 .map_err(|e| {
176 AuthError::authorization(format!(
177 "Failed to set admin->moderator inheritance: {}",
178 e
179 ))
180 })?;
181
182 self.role_system
183 .add_role_inheritance("moderator", "user")
184 .await
185 .map_err(|e| {
186 AuthError::authorization(format!(
187 "Failed to set moderator->user inheritance: {}",
188 e
189 ))
190 })?;
191
192 self.role_system
193 .add_role_inheritance("user", "guest")
194 .await
195 .map_err(|e| {
196 AuthError::authorization(format!("Failed to set user->guest inheritance: {}", e))
197 })?;
198
199 info!("AuthFramework standard roles initialized successfully");
200 Ok(())
201 }
202
203 pub async fn check_permission(
205 &self,
206 user_id: &str,
207 action: &str,
208 resource_type: &str,
209 context: Option<&HashMap<String, String>>,
210 ) -> Result<bool> {
211 debug!(
212 "Checking permission for user '{}': {}:{}",
213 user_id, action, resource_type
214 );
215
216 let subject = Subject::user(user_id);
217 let resource = Resource::new("", resource_type); let result = if let Some(context) = context {
221 self.role_system
222 .check_permission_with_context(&subject, action, &resource, context)
223 .await
224 } else {
225 self.role_system
226 .check_permission(&subject, action, &resource)
227 .await
228 };
229
230 if self.config.enable_audit {
232 info!(
233 target: "authorization_audit",
234 user_id = user_id,
235 action = action,
236 resource_type = resource_type,
237 permission_granted = result.is_ok() && *result.as_ref().unwrap_or(&false),
238 timestamp = chrono::Utc::now().to_rfc3339(),
239 "Permission check performed"
240 );
241 }
242
243 match result {
244 Ok(granted) => {
245 debug!("Permission check result: {}", granted);
246 Ok(granted)
247 }
248 Err(e) => {
249 warn!("Permission check failed: {}", e);
250 Err(AuthError::authorization(format!(
251 "Permission check failed: {}",
252 e
253 )))
254 }
255 }
256 }
257
258 pub async fn check_api_permission(
260 &self,
261 user_id: &str,
262 method: &str,
263 endpoint: &str,
264 context: &HashMap<String, String>,
265 ) -> Result<bool> {
266 let action = match method.to_uppercase().as_str() {
268 "GET" => "read",
269 "POST" => "create",
270 "PUT" | "PATCH" => "update",
271 "DELETE" => "delete",
272 _ => "access",
273 };
274
275 self.check_permission(user_id, action, endpoint, Some(context))
276 .await
277 }
278
279 pub async fn assign_role(&self, user_id: &str, role_name: &str) -> Result<()> {
281 debug!("Assigning role '{}' to user '{}'", role_name, user_id);
282
283 let subject = Subject::user(user_id);
284
285 self.role_system
286 .assign_role(&subject, role_name)
287 .await
288 .map_err(|e| AuthError::authorization(format!("Failed to assign role: {}", e)))?;
289
290 info!("Role '{}' assigned to user '{}'", role_name, user_id);
291 Ok(())
292 }
293
294 pub async fn remove_role(&self, user_id: &str, role_name: &str) -> Result<()> {
296 debug!("Removing role '{}' from user '{}'", role_name, user_id);
297
298 let subject = Subject::user(user_id);
299
300 self.role_system
301 .remove_role(&subject, role_name)
302 .await
303 .map_err(|e| AuthError::authorization(format!("Failed to remove role: {}", e)))?;
304
305 info!("Role '{}' removed from user '{}'", role_name, user_id);
306 Ok(())
307 }
308
309 pub async fn elevate_role(
311 &self,
312 user_id: &str,
313 role_name: &str,
314 duration_seconds: Option<u64>,
315 ) -> Result<()> {
316 debug!(
317 "Elevating user '{}' to role '{}' for {:?} seconds",
318 user_id, role_name, duration_seconds
319 );
320
321 let subject = Subject::user(user_id);
322 let duration = duration_seconds.map(std::time::Duration::from_secs);
323
324 self.role_system
325 .elevate_role(&subject, role_name, duration)
326 .await
327 .map_err(|e| AuthError::authorization(format!("Failed to elevate role: {}", e)))?;
328
329 info!(
330 "User '{}' elevated to role '{}' for {:?} seconds",
331 user_id, role_name, duration_seconds
332 );
333 Ok(())
334 }
335
336 pub async fn get_user_roles(&self, user_id: &str) -> Result<Vec<String>> {
338 let subject = Subject::user(user_id);
339
340 let roles = self
341 .role_system
342 .get_subject_roles(&subject)
343 .await
344 .map_err(|e| AuthError::authorization(format!("Failed to get user roles: {}", e)))?;
345
346 Ok(roles.into_iter().collect())
347 }
348
349 pub async fn create_role(
351 &self,
352 name: &str,
353 description: &str,
354 permissions: Vec<Permission>,
355 parent_roles: Option<Vec<String>>,
356 ) -> Result<()> {
357 debug!(
358 "Creating role '{}' with {} permissions",
359 name,
360 permissions.len()
361 );
362
363 let mut role = Role::new(name).with_description(description);
364
365 for permission in permissions {
366 role = role.add_permission(permission);
367 }
368
369 self.role_system
370 .register_role(role)
371 .await
372 .map_err(|e| AuthError::authorization(format!("Failed to create role: {}", e)))?;
373
374 if let Some(parents) = parent_roles {
376 for parent in parents {
377 self.role_system
378 .add_role_inheritance(name, &parent)
379 .await
380 .map_err(|e| {
381 AuthError::authorization(format!("Failed to set role inheritance: {}", e))
382 })?;
383 }
384 }
385
386 info!("Role '{}' created successfully", name);
387 Ok(())
388 }
389
390 pub async fn get_role_hierarchy(&self, role_id: &str) -> Result<Vec<String>> {
392 if let Ok(Some(role)) = self.role_system.get_role(role_id).await {
394 let mut result = vec![role.id().to_string()];
395 if let Some(parent_id) = role.parent_role_id() {
396 result.push(parent_id.to_string());
397 }
398 Ok(result)
399 } else {
400 Ok(vec![])
401 }
402 }
403
404 pub async fn get_role_metadata(&self, role_id: &str) -> Result<String> {
406 if let Ok(Some(role)) = self.role_system.get_role(role_id).await {
407 let depth = role.hierarchy_depth();
408 let is_root = role.is_root_role();
409 let is_leaf = role.is_leaf_role();
410 let children = role.child_role_ids();
411
412 Ok(format!(
413 "Role '{}': depth={}, root={}, leaf={}, children={:?}",
414 role.name(),
415 depth,
416 is_root,
417 is_leaf,
418 children
419 ))
420 } else {
421 Err(AuthError::authorization("Role not found".to_string()))
422 }
423 }
424
425 pub async fn delete_role(&self, name: &str) -> Result<()> {
427 let exists = self
429 .role_system
430 .get_role(name)
431 .await
432 .map_err(|e| AuthError::authorization(format!("Failed to look up role: {}", e)))?;
433
434 if exists.is_none() {
435 return Err(AuthError::authorization(format!(
436 "Role '{}' not found",
437 name
438 )));
439 }
440
441 let mut storage = self.storage_handle.lock().await;
445 match storage.delete_role(name) {
446 Ok(true) => {
447 info!("Role deleted: {}", name);
448 Ok(())
449 }
450 Ok(false) => {
451 warn!("delete_role: role '{}' was not found in storage", name);
453 Ok(())
454 }
455 Err(e) => Err(AuthError::authorization(format!(
456 "Failed to delete role '{}': {}",
457 name, e
458 ))),
459 }
460 }
461
462 pub async fn get_role(&self, name: &str) -> Result<Option<Role>> {
464 self.role_system
465 .get_role(name)
466 .await
467 .map_err(|e| AuthError::authorization(format!("Failed to get role: {}", e)))
468 }
469
470 pub async fn update_role(
475 &self,
476 name: &str,
477 new_description: Option<&str>,
478 new_parent_id: Option<Option<&str>>,
479 ) -> Result<()> {
480 let role = self
481 .role_system
482 .get_role(name)
483 .await
484 .map_err(|e| AuthError::authorization(format!("Failed to look up role: {}", e)))?
485 .ok_or_else(|| AuthError::authorization(format!("Role '{}' not found", name)))?;
486
487 let mut updated = Role::with_id(role.id(), role.name());
489
490 let description = new_description
491 .map(|s| s.to_string())
492 .or_else(|| role.description().map(|s| s.to_string()));
493 if let Some(desc) = description {
494 updated = updated.with_description(desc);
495 }
496
497 for perm in role.permissions().permissions() {
499 updated = updated.add_permission(perm.clone());
500 }
501
502 let mut storage = self.storage_handle.lock().await;
504 storage
505 .update_role(updated)
506 .map_err(|e| AuthError::authorization(format!("Failed to update role: {}", e)))?;
507 drop(storage);
508
509 if let Some(new_parent) = new_parent_id {
511 if let Some(old_parent) = role.parent_role_id() {
513 let _ = self
514 .role_system
515 .remove_role_inheritance(name, old_parent)
516 .await;
517 }
518 if let Some(parent) = new_parent {
519 self.role_system
520 .add_role_inheritance(name, parent)
521 .await
522 .map_err(|e| {
523 AuthError::authorization(format!(
524 "Failed to update role inheritance: {}",
525 e
526 ))
527 })?;
528 }
529 }
530
531 info!("Role '{}' updated", name);
532 Ok(())
533 }
534
535 pub async fn list_roles(&self) -> Result<Vec<Role>> {
537 let storage = self.storage_handle.lock().await;
538 let names = storage
539 .list_roles()
540 .map_err(|e| AuthError::authorization(format!("Failed to list roles: {}", e)))?;
541 drop(storage);
542
543 let mut roles = Vec::with_capacity(names.len());
545 for name in names {
546 if let Ok(Some(role)) = self.role_system.get_role(&name).await {
547 roles.push(role);
548 }
549 }
550 Ok(roles)
551 }
552
553 pub async fn batch_check_permissions(
555 &self,
556 user_id: &str,
557 checks: &[(String, String)], ) -> Result<Vec<(String, String, bool)>> {
559 let subject = Subject::user(user_id);
560
561 let resource_checks: Vec<(String, Resource)> = checks
562 .iter()
563 .map(|(action, resource)| (action.clone(), Resource::new(resource, "api")))
564 .collect();
565
566 let results = self
567 .role_system
568 .batch_check_permissions(&subject, &resource_checks)
569 .await
570 .map_err(|e| {
571 AuthError::authorization(format!("Batch permission check failed: {}", e))
572 })?;
573
574 Ok(results
575 .into_iter()
576 .map(|(action, resource, granted)| {
577 (
578 action,
579 resource.name().unwrap_or("unknown").to_string(),
580 granted,
581 )
582 })
583 .collect())
584 }
585}
586
587#[cfg(test)]
588mod tests {
589 use super::*;
590
591 #[tokio::test]
592 async fn test_authorization_service_creation() {
593 let service = AuthorizationService::new().await.unwrap();
594
595 let roles = ["guest", "user", "moderator", "admin"];
597 for role_name in &roles {
598 let role = service.get_role(role_name).await.unwrap();
599 assert!(role.is_some(), "Role '{}' should exist", role_name);
600 }
601 }
602
603 #[tokio::test]
604 async fn test_role_assignment_and_permission_check() {
605 let service = AuthorizationService::new().await.unwrap();
606
607 service.assign_role("test_user", "user").await.unwrap();
609
610 let can_read_profile = service
612 .check_permission("test_user", "read", "profile", None)
613 .await
614 .unwrap();
615 assert!(can_read_profile, "User should have read access to profile");
616
617 let can_admin = service
618 .check_permission("test_user", "admin", "system", None)
619 .await
620 .unwrap();
621 assert!(!can_admin);
622 }
623
624 #[tokio::test]
625 async fn test_role_hierarchy() {
626 let service = AuthorizationService::new().await.unwrap();
627
628 service.assign_role("admin_user", "admin").await.unwrap();
630
631 let can_read_profile = service
633 .check_permission("admin_user", "read", "profile", None)
634 .await
635 .unwrap();
636 assert!(can_read_profile);
637
638 let can_admin = service
640 .check_permission("admin_user", "admin", "system", None)
641 .await
642 .unwrap();
643 assert!(can_admin);
644 }
645}