next_web_dev/manager/
user_authorization_manager.rs

1// #[cfg(feature = "redis")]
2use crate::{
3    autoconfigure::context::user_authorization_options_properties::UserAuthorizationOptions,
4    security::{
5        auth_group::{AuthGroup, CombinationMode}, authorization_service::AuthorizationService, login_type::LoginType,
6        user_permission_resource::UserPermissionResource,
7    },
8};
9
10#[derive(Clone)]
11pub struct UserAuthorizationManager<T>
12where
13    T: AuthorizationService<Vec<String>> + Clone,
14{
15    options: UserAuthorizationOptions,
16    authorization_service: T,
17    user_permission_resource: UserPermissionResource,
18}
19
20impl<T> UserAuthorizationManager<T>
21where
22    T: AuthorizationService<Vec<String>> + Clone,
23{
24    pub fn new(
25        options: UserAuthorizationOptions,
26        authorization_service: T,
27        user_permission_resource: UserPermissionResource,
28    ) -> Self {
29        Self {
30            options,
31            authorization_service,
32            user_permission_resource,
33        }
34    }
35
36    pub fn options(&self) -> &UserAuthorizationOptions {
37        &self.options
38    }
39
40    pub fn authorization_service(&self) -> &T {
41        &self.authorization_service
42    }
43
44    pub fn get_permission(&self, method: &axum::http::Method, path: &str) -> Option<&AuthGroup> {
45        self.user_permission_resource.get_permission(method, path)
46    }
47}
48
49impl<T> UserAuthorizationManager<T>
50where
51    T: AuthorizationService<Vec<String>> + Clone,
52{
53    pub async fn pre_authorize(
54        &self,
55        user_id: &String,
56        auth_group: &AuthGroup,
57        login_type: &LoginType,
58    ) -> bool {
59        if user_id.is_empty() {
60            return false;
61        }
62
63        if auth_group.is_combination() {
64            if auth_group.combination_valid() {
65                return true;
66            }
67        }
68
69        let roles = auth_group.roles().unwrap_or_default();
70        let permissions = auth_group.permissions().unwrap_or_default();
71        let bing = auth_group.mode();
72        let mode = bing.as_ref();
73
74        if roles.is_empty() && permissions.is_empty() {
75            return true;
76        }
77
78        let user_roles = self
79            .authorization_service
80            .user_role(user_id, login_type)
81            .await;
82
83        // Mode  And or Or
84        // tips:
85        // 1. And mode: if user has all roles and permissions, return true
86        // 2. Or mode: if user has any roles or permissions, return true
87        let role_flag = auth_group.match_value(roles, user_roles, mode);
88        if let Some(_model ) = mode {
89            if _model != &CombinationMode::Or {
90                if !role_flag {
91                    return false;
92                }
93            }
94        }else {
95            if !role_flag {
96                return false;
97            }
98        }
99        
100        let user_permissions = self
101            .authorization_service
102            .user_permission(user_id, login_type)
103            .await;
104
105        let permission_flag =
106            auth_group.match_value(permissions, user_permissions, mode);
107
108        if role_flag && permission_flag {
109            return true;
110        }
111        false
112    }
113
114    pub async fn verify_token(&self, token: &String, login_type: &LoginType) -> bool {
115        self.authorization_service
116            .verify_token(token, login_type)
117            .await
118    }
119}