next_web_dev/security/
user_permission_resource.rs

1use axum::http::Method;
2use matchit::Router;
3
4use super::auth_group::{AuthGroup, CombinationGroup, CombinationMode};
5
6#[derive(Debug, serde::Deserialize)]
7pub struct UserPermissionResourceBuilder {
8    pub method: String,
9    pub path: String,
10    pub role: Vec<String>,
11    pub permission: Vec<String>,
12    pub mode: Option<CombinationMode>,
13}
14
15impl UserPermissionResourceBuilder {
16    pub fn method(&self) -> Method {
17        let method = self.method.to_uppercase();
18        match method.as_str() {
19            "POST" => Method::POST,
20            "GET" => Method::GET,
21            "PUT" => Method::PUT,
22            "DELETE" => Method::DELETE,
23            _ => Method::POST,
24        }
25    }
26}
27
28impl Into<UserPermissionResource> for Vec<UserPermissionResourceBuilder> {
29    fn into(self) -> UserPermissionResource {
30        let mut user_permission_resource = UserPermissionResource::new();
31        for user in self {
32            let method: Method = user.method();
33            let path = user.path;
34            let role_group = user.role;
35            let permission_group = user.permission;
36            let mode = user.mode;
37            let auth_group = if let Some(mode) = mode {
38                AuthGroup::new(
39                    None,
40                    None,
41                    Some(CombinationGroup::new(
42                        Some(role_group),
43                        Some(permission_group),
44                        mode,
45                    )),
46                )
47            } else {
48                AuthGroup::new(
49                    if role_group.is_empty() {
50                        None
51                    } else {
52                        Some(role_group)
53                    },
54                    if permission_group.is_empty() {
55                        None
56                    } else {
57                        Some(permission_group)
58                    },
59                    None,
60                )
61            };
62
63            user_permission_resource.add_permission(method, path.as_str(), auth_group);
64        }
65        user_permission_resource
66    }
67}
68
69#[derive(Clone)]
70pub struct UserPermissionResource {
71    pub post_permission: Router<AuthGroup>,
72    pub get_permission: Router<AuthGroup>,
73    pub put_permission: Router<AuthGroup>,
74    pub delete_permission: Router<AuthGroup>,
75}
76
77impl UserPermissionResource {
78    pub fn new() -> Self {
79        Self {
80            post_permission: Router::new(),
81            get_permission: Router::new(),
82            put_permission: Router::new(),
83            delete_permission: Router::new(),
84        }
85    }
86
87    pub fn add_permission(&mut self, method: Method, path: &str, mut auth_group: AuthGroup) {
88        if auth_group.is_combination() {
89            auth_group.set_combination(true);
90        }
91        let _ = match method {
92            Method::POST => self.post_permission.insert(path, auth_group),
93            Method::GET => self.get_permission.insert(path, auth_group),
94            Method::PUT => self.put_permission.insert(path, auth_group),
95            Method::DELETE => self.delete_permission.insert(path, auth_group),
96            _ => Ok(()),
97        };
98    }
99
100    pub fn get_permission(&self, method: &Method, path: &str) -> Option<&AuthGroup> {
101        let auth_group = match method {
102            &Method::POST => self.post_permission.at(path),
103            &Method::GET => self.get_permission.at(path),
104            &Method::PUT => self.put_permission.at(path),
105            &Method::DELETE => self.delete_permission.at(path),
106            _ => return None,
107        };
108        if let Ok(auth_group) = auth_group {
109            return Some(auth_group.value);
110        }
111        None
112    }
113}