sa_token_plugin_salvo_v079/
middleware.rs1use salvo::prelude::*;
7use sa_token_core::{StpUtil, error::messages};
8use serde_json::json;
9use sa_token_plugin_salvo_core::{run_auth_flow, SaTokenState};
10
11use crate::adapter::SalvoCapturedRequest;
12
13pub fn auth_middleware() -> impl Handler {
26 auth_middleware_handler
27}
28
29#[handler]
30async fn auth_middleware_handler(req: &mut Request, res: &mut Response, depot: &mut Depot, ctrl: &mut FlowCtrl) {
31 let token = req
34 .headers()
35 .get("Authorization")
36 .and_then(|v| v.to_str().ok())
37 .and_then(|s| s.strip_prefix("Bearer "))
38 .map(|s| s.to_string());
39
40 if let Some(token_str) = token {
41 use sa_token_core::TokenValue;
44 let token_value = TokenValue::from(token_str.clone());
45 if StpUtil::is_login(&token_value).await {
46 if let Ok(login_id) = StpUtil::get_login_id(&token_value).await {
49 depot.insert("login_id", login_id);
50 ctrl.call_next(req, depot, res).await;
51 return;
52 }
53 }
54 }
55
56 res.status_code(StatusCode::UNAUTHORIZED);
59 res.render(Text::Json(r#"{"error":"Unauthorized"}"#));
60 ctrl.skip_rest();
61}
62
63pub fn permission_middleware(permission: &'static str) -> impl Handler {
76 PermissionMiddleware { permission }
77}
78
79struct PermissionMiddleware {
80 permission: &'static str,
81}
82
83#[handler]
84impl PermissionMiddleware {
85 async fn handle(&self, req: &mut Request, res: &mut Response, depot: &mut Depot, ctrl: &mut FlowCtrl) {
86 if let Ok(login_id) = depot.get::<String>("login_id") {
89 if StpUtil::has_permission(login_id, self.permission).await {
92 ctrl.call_next(req, depot, res).await;
93 return;
94 }
95 }
96
97 res.status_code(StatusCode::FORBIDDEN);
100 res.render(Text::Json(r#"{"error":"Forbidden"}"#));
101 ctrl.skip_rest();
102 }
103}
104
105#[derive(Clone)]
110pub struct SaCheckLoginMiddleware {
111 pub state: SaTokenState,
112}
113
114impl SaCheckLoginMiddleware {
115 pub fn new(state: SaTokenState) -> Self {
118 Self { state }
119 }
120}
121
122#[salvo::async_trait]
123impl Handler for SaCheckLoginMiddleware {
124 async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
125 let adapter =
126 SalvoCapturedRequest::capture(req, self.state.manager.config.token_name.as_str());
127 let flow = run_auth_flow(&adapter, &self.state.manager, None).await;
128
129 if flow.token.is_none() || flow.login_id.is_none() {
130 res.status_code(StatusCode::UNAUTHORIZED);
131 res.render(Text::Json(json!({
132 "code": 401,
133 "message": messages::AUTH_ERROR
134 }).to_string()));
135 ctrl.skip_rest();
136 return;
137 }
138
139 if let Some(ref t) = flow.token {
140 depot.insert("sa_token", t.clone());
141 }
142 if let Some(ref id) = flow.login_id {
143 depot.insert("sa_login_id", id.clone());
144 }
145
146 flow.run(ctrl.call_next(req, depot, res)).await;
147 }
148}
149
150#[derive(Clone)]
155pub struct SaCheckPermissionMiddleware {
156 pub state: SaTokenState,
157 permission: String,
158}
159
160impl SaCheckPermissionMiddleware {
161 pub fn new(state: SaTokenState, permission: impl Into<String>) -> Self {
164 Self { state, permission: permission.into() }
165 }
166}
167
168#[salvo::async_trait]
169impl Handler for SaCheckPermissionMiddleware {
170 async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
171 let adapter =
172 SalvoCapturedRequest::capture(req, self.state.manager.config.token_name.as_str());
173 let flow = run_auth_flow(&adapter, &self.state.manager, None).await;
174
175 let Some(login_id) = flow.login_id.clone() else {
176 res.status_code(StatusCode::FORBIDDEN);
177 res.render(Text::Json(json!({
178 "code": 403,
179 "message": messages::PERMISSION_REQUIRED
180 }).to_string()));
181 ctrl.skip_rest();
182 return;
183 };
184
185 if !StpUtil::has_permission(&login_id, &self.permission).await {
186 res.status_code(StatusCode::FORBIDDEN);
187 res.render(Text::Json(json!({
188 "code": 403,
189 "message": messages::PERMISSION_REQUIRED
190 }).to_string()));
191 ctrl.skip_rest();
192 return;
193 }
194
195 if let Some(ref t) = flow.token {
196 depot.insert("sa_token", t.clone());
197 }
198 depot.insert("sa_login_id", login_id);
199
200 flow.run(ctrl.call_next(req, depot, res)).await;
201 }
202}
203
204#[derive(Clone)]
209pub struct SaCheckRoleMiddleware {
210 pub state: SaTokenState,
211 role: String,
212}
213
214impl SaCheckRoleMiddleware {
215 pub fn new(state: SaTokenState, role: impl Into<String>) -> Self {
218 Self { state, role: role.into() }
219 }
220}
221
222#[salvo::async_trait]
223impl Handler for SaCheckRoleMiddleware {
224 async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response, ctrl: &mut FlowCtrl) {
225 let adapter =
226 SalvoCapturedRequest::capture(req, self.state.manager.config.token_name.as_str());
227 let flow = run_auth_flow(&adapter, &self.state.manager, None).await;
228
229 let Some(login_id) = flow.login_id.clone() else {
230 res.status_code(StatusCode::FORBIDDEN);
231 res.render(Text::Json(json!({
232 "code": 403,
233 "message": messages::ROLE_REQUIRED
234 }).to_string()));
235 ctrl.skip_rest();
236 return;
237 };
238
239 if !StpUtil::has_role(&login_id, &self.role).await {
240 res.status_code(StatusCode::FORBIDDEN);
241 res.render(Text::Json(json!({
242 "code": 403,
243 "message": messages::ROLE_REQUIRED
244 }).to_string()));
245 ctrl.skip_rest();
246 return;
247 }
248
249 if let Some(ref t) = flow.token {
250 depot.insert("sa_token", t.clone());
251 }
252 depot.insert("sa_login_id", login_id);
253
254 flow.run(ctrl.call_next(req, depot, res)).await;
255 }
256}