chimes_rust/utils/
auth.rs

1use std::pin::Pin;
2
3use crate::entity::ChimesUserDetailInfo;
4use crate::query::{QueryUserRole, QueryUserRoleParams};
5use actix_web::{HttpRequest, Result};
6use futures::Future;
7use serde::Deserialize;
8
9use crate::entity::ChimesUserInfo;
10use crate::query::{QueryUserPermission, QueryUserPermissionParams};
11use actix_utils::future::{err, ok};
12use actix_web::dev::Payload;
13use actix_web::{FromRequest, HttpMessage};
14use chimes_auth::{ChimesAuthService, ChimesAuthUser};
15use chimes_utils::get_rbatis;
16
17use super::UserClaims;
18
19#[derive(Clone, Default, Deserialize)]
20pub struct SystemUser<ChimesUserInfo> {
21    pub user: ChimesUserInfo,
22    pub roles: Vec<String>,
23    pub open_id: Option<String>,
24    pub union_id: Option<String>,
25}
26
27impl SystemUser<ChimesUserInfo> {
28    #[allow(dead_code)]
29    pub fn has_role(&self, role: &String) -> bool {
30        self.roles.contains(role)
31    }
32}
33
34impl ChimesAuthUser<SystemUser<ChimesUserInfo>> for SystemUser<ChimesUserInfo> {
35    #[allow(dead_code)]
36    fn get_user_name(&self) -> String {
37        self.user.username.clone().unwrap_or_default()
38    }
39
40    #[allow(dead_code)]
41    fn get_creditial(&self) -> String {
42        self.user.phone.clone().unwrap_or_default()
43    }
44
45    #[allow(dead_code)]
46    fn to_detail(self) -> Self {
47        self
48    }
49}
50
51impl FromRequest for SystemUser<ChimesUserInfo> {
52    type Error = actix_web::Error;
53    type Future = actix_utils::future::Ready<Result<Self, Self::Error>>;
54
55    fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
56        let header = req.headers();
57
58        match req.extensions().get::<SystemUser<ChimesUserInfo>>() {
59            Some(user) => {
60                let mut us = user.clone();
61                if header.contains_key("AttachedOpenId") {
62                    us.open_id = header
63                        .get("AttachedOpenId")
64                        .map(|f| f.to_str().ok().map(|g| g.to_string()).unwrap_or_default());
65                    us.union_id = header
66                        .get("AttachedUnionId")
67                        .map(|f| f.to_str().ok().map(|g| g.to_string()).unwrap_or_default());
68                }
69                ok(us)
70            }
71            None => {
72                log::info!("Not found the SystemUser");
73                err(actix_web::error::ErrorBadRequest("ups..."))
74            }
75        }
76    }
77}
78
79#[derive(Clone)]
80pub struct ChimesUserAuthService<SystemUser> {
81    #[allow(unused)]
82    pub system_user: Option<SystemUser>,
83}
84
85impl ChimesAuthService<SystemUser<ChimesUserInfo>>
86    for ChimesUserAuthService<SystemUser<ChimesUserInfo>>
87{
88    type Future = Pin<Box<dyn Future<Output = Option<SystemUser<ChimesUserInfo>>>>>;
89
90    fn permit(
91        &self,
92        ust: &Option<SystemUser<ChimesUserInfo>>,
93        req_method: &String,
94        url_pattern: &String,
95    ) -> Self::Future {
96        let up = url_pattern.clone();
97        let mth = req_method.clone();
98        let mtusr = ust.clone();
99        let username = match ust {
100            Some(st) => st.get_user_name(),
101            None => "ANNOYMOUS".to_string(),
102        };
103
104        Box::pin(async move {
105            let param = QueryUserPermissionParams {
106                api_method: mth.clone(),
107                api_pattern: up.clone(),
108                username: username.clone(),
109            };
110
111            let rb = get_rbatis();
112            match QueryUserPermission::query(rb, &param).await {
113                Ok(rs) => {
114                    if !rs.is_empty() {
115                        let rp = rs[0].clone();
116                        if rp.api_bypass == Some("ANONYMOUS".to_string())
117                            || rp.api_bypass == Some("anonymous".to_string())
118                        {
119                            // log::info!("Found Permission {}, the api_pass is {}", rp.api_pattern.clone().unwrap_or_default(), rp.api_bypass.clone().unwrap_or_default());
120                            Some(SystemUser::default())
121                        } else if rp.api_bypass == Some("USER".to_string())
122                            || rp.api_bypass == Some("user".to_string())
123                        {
124                            if mtusr.is_none() {
125                                return None;
126                            } else {
127                                return mtusr;
128                            }
129                        } else {
130                            let mut find_username = None;
131                            for rx in rs.clone() {
132                                if rx.username.is_some() {
133                                    find_username = rx.username.clone();
134                                    break;
135                                }
136                            }
137                            if find_username.is_none() {
138                                return None;
139                            } else {
140                                return mtusr;
141                            }
142                        }
143                    } else if up.is_empty() {
144                        mtusr
145                    } else {
146                        None
147                    }
148                }
149                Err(err) => {
150                    log::warn!(
151                        "Query the permission for user with an error: {}",
152                        err.to_string()
153                    );
154                    None
155                }
156            }
157        })
158    }
159
160    fn authenticate(&self, token: &String) -> Self::Future {
161        let rb = get_rbatis();
162        let tk = token.clone();
163        Box::pin(async move {
164            match UserClaims::decode(&tk) {
165                Some(uc) => match ChimesUserInfo::load_username(rb, &uc.aud).await {
166                    Ok(r) => match r {
167                        Some(u) => {
168                            let param = QueryUserRoleParams {
169                                user_id: u.user_id,
170                                username: u.username.clone(),
171                                company_code: u.company_code.clone(),
172                                role_codes: u.parse_simulate_roles(),
173                            };
174
175                            let roles: Vec<String> = match QueryUserRole::query(rb, &param).await {
176                                Ok(rs) => rs
177                                    .into_iter()
178                                    .map(|f| f.role_code.unwrap_or_default())
179                                    .collect(),
180                                Err(_) => {
181                                    vec![]
182                                }
183                            };
184                            Some(SystemUser {
185                                user: u,
186                                roles,
187                                open_id: None,
188                                union_id: None,
189                            })
190                        }
191                        None => None,
192                    },
193                    Err(_) => None,
194                },
195                None => None,
196            }
197        })
198    }
199
200    fn nojwt_authenticate(&self, token: &String) -> Self::Future {
201        let rb = get_rbatis();
202        let tk = token.clone();
203        Box::pin(async move {
204            match ChimesUserInfo::load_username(rb, &tk.clone()).await {
205                Ok(r) => match r {
206                    Some(u) => {
207                        let param = QueryUserRoleParams {
208                            user_id: u.user_id,
209                            username: u.username.clone(),
210                            company_code: u.company_code.clone(),
211                            role_codes: u.parse_simulate_roles(),
212                        };
213
214                        let roles = match QueryUserRole::query(rb, &param).await {
215                            Ok(rs) => rs
216                                .into_iter()
217                                .map(|f| f.role_code.unwrap_or_default())
218                                .collect(),
219                            Err(_) => {
220                                vec![]
221                            }
222                        };
223                        Some(SystemUser {
224                            user: u,
225                            roles,
226                            open_id: None,
227                            union_id: None,
228                        })
229                    }
230                    None => {
231                        log::warn!("For NoJWT mode, to load by openid with: {}, ", tk.clone());
232                        match ChimesUserDetailInfo::load_openid(rb, &tk.clone()).await {
233                            Ok(cdinfo) => {
234                                if cdinfo.is_none() {
235                                    None
236                                } else {
237                                    let cdu = cdinfo.unwrap();
238                                    let mu = cdu.to_user();
239                                    let roles = cdu
240                                        .roles
241                                        .into_iter()
242                                        .map(|f| f.role_code.unwrap_or_default())
243                                        .collect::<Vec<String>>();
244                                    Some(SystemUser {
245                                        user: mu.clone(),
246                                        roles,
247                                        open_id: mu.open_id.clone(),
248                                        union_id: mu.union_id.clone(),
249                                    })
250                                }
251                            }
252                            Err(_err) => None,
253                        }
254                    }
255                },
256                Err(_) => None,
257            }
258        })
259    }
260}