Skip to content

Commit e789e0a

Browse files
committed
♻️ 重写鉴权中间件,解析完 token 后立即就得读取用户信息的局部缓存。
1 parent b593013 commit e789e0a

File tree

15 files changed

+477
-180
lines changed

15 files changed

+477
-180
lines changed

packages/database/src/models/system/sys_user.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub struct Model {
4343
/// 头像链接
4444
pub logo: Option<String>,
4545

46-
/// 角色 ID
46+
/// 角色
4747
pub role_id: SystemUserRole,
4848
/// 权限策略
4949
#[sea_orm(column_type = "Json")]
@@ -84,6 +84,7 @@ impl Into<SysUserVO> for Model {
8484
qq: self.qq,
8585
phone: self.phone,
8686
logo: self.logo,
87+
role_id: self.role_id,
8788
access_policy: self.access_policy,
8889
remark: self.remark,
8990
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod oauth;
2+
pub mod user;

packages/functions/src/functions/system/oauth.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use sea_orm::{prelude::*, ActiveValue::Set};
77
use _database::{models, DB_CONN};
88
use _utils::{
99
bcrypt::verify_hash,
10-
jwt::{generate_token, EXPIRED_APPEND_DURATION},
10+
jwt::{generate_token, verify_token, Claims, EXPIRED_APPEND_DURATION},
11+
models::SysUserVO,
1112
types::{
1213
auth::{OauthAnonymousResponse, OauthLoginResponse, OauthScopeType, OauthTokenType},
1314
SystemActionLogAction,
@@ -32,15 +33,17 @@ async fn oauth_password_login_inner(
3233
let access_token = generate_token(now, item.id, jti).await?;
3334
let refresh_token = generate_token(now, item.id, jti).await?;
3435

36+
let id = item.id;
37+
let vo: SysUserVO = item.into();
3538
let mut redis_conn = DB_CONN
3639
.wait()
3740
.redis_conn
3841
.get_multiplexed_async_connection()
3942
.await?;
4043
redis_conn
4144
.set_options(
42-
format!("jwt:access:{}:{}", item.id, jti),
43-
&access_token,
45+
format!("jwt:access:{}:{}", id, jti),
46+
serde_json::to_string(&vo)?,
4447
SetOptions::default()
4548
.conditional_set(redis::ExistenceCheck::NX)
4649
.with_expiration(redis::SetExpiry::EX(
@@ -50,8 +53,8 @@ async fn oauth_password_login_inner(
5053
.await?;
5154
redis_conn
5255
.set_options(
53-
format!("jwt:refresh:{}:{}", item.id, jti),
54-
&refresh_token,
56+
format!("jwt:refresh:{}:{}", id, jti),
57+
&"",
5558
SetOptions::default()
5659
.conditional_set(redis::ExistenceCheck::NX)
5760
.with_expiration(redis::SetExpiry::EX(
@@ -70,6 +73,21 @@ async fn oauth_password_login_inner(
7073
})
7174
}
7275

76+
pub async fn oauth_parse_token(token: String) -> Result<(SysUserVO, Claims)> {
77+
let claims = verify_token(&token).await?;
78+
79+
let mut redis_conn = DB_CONN
80+
.wait()
81+
.redis_conn
82+
.get_multiplexed_async_connection()
83+
.await?;
84+
let item = redis_conn
85+
.get(format!("jwt:access:{}:{}", claims.sub, claims.jti))
86+
.await?
87+
.ok_or(anyhow!("Token not found in Redis"))?;
88+
Ok((serde_json::from_str(&item)?, claims))
89+
}
90+
7391
pub async fn oauth_password_login(
7492
username: String,
7593
password_raw: String,
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use anyhow::Result;
2+
3+
use _utils::{
4+
jwt::AuthInfo,
5+
models::Pagination,
6+
types::{AccessPolicyItemEnum, SystemUserRole},
7+
};
8+
9+
// 业务处理函数
10+
pub async fn do_register(
11+
_auth: AuthInfo,
12+
_access_policy: Vec<AccessPolicyItemEnum>,
13+
_logo: String,
14+
_remark: String,
15+
_role_id: SystemUserRole,
16+
_username: String,
17+
) -> Result<()> {
18+
// TODO: 实现注册逻辑
19+
Ok(())
20+
}
21+
22+
pub async fn do_register_qq(
23+
_auth: AuthInfo,
24+
_access_policy: Vec<AccessPolicyItemEnum>,
25+
_logo: String,
26+
_remark: String,
27+
_role_id: SystemUserRole,
28+
_username: String,
29+
) -> Result<()> {
30+
// TODO: 实现QQ注册逻辑
31+
Ok(())
32+
}
33+
34+
pub async fn do_get_info(_auth: AuthInfo, _user_id: i64) -> Result<()> {
35+
// TODO: 实现获取用户信息逻辑
36+
Ok(())
37+
}
38+
39+
pub async fn do_update(
40+
_auth: AuthInfo,
41+
_id: i64,
42+
_access_policy: Option<Vec<AccessPolicyItemEnum>>,
43+
_logo: Option<String>,
44+
_nickname: Option<String>,
45+
_phone: Option<String>,
46+
_qq: Option<String>,
47+
_remark: Option<String>,
48+
_role_id: SystemUserRole,
49+
) -> Result<()> {
50+
// TODO: 实现更新用户信息逻辑
51+
Ok(())
52+
}
53+
54+
pub async fn do_update_password(
55+
_auth: AuthInfo,
56+
_access_policy: Vec<AccessPolicyItemEnum>,
57+
_id: i64,
58+
_logo: String,
59+
_old_password: String,
60+
_remark: String,
61+
_role_id: SystemUserRole,
62+
) -> Result<()> {
63+
// TODO: 实现更新用户密码逻辑
64+
Ok(())
65+
}
66+
67+
pub async fn do_update_password_by_admin(
68+
_auth: AuthInfo,
69+
_password: String,
70+
_user_id: i64,
71+
) -> Result<()> {
72+
// TODO: 实现管理员更新用户密码逻辑
73+
Ok(())
74+
}
75+
76+
pub async fn do_delete(_auth: AuthInfo, _work_id: i64) -> Result<()> {
77+
// TODO: 实现删除用户逻辑
78+
Ok(())
79+
}
80+
81+
pub async fn do_list(
82+
_auth: AuthInfo,
83+
_pagination: Pagination,
84+
_nickname: String,
85+
_role_ids: Option<Vec<SystemUserRole>>,
86+
_sort: Option<Vec<String>>, // 简化为 String,因为 UserSort 已移动
87+
_username: String,
88+
) -> Result<()> {
89+
// TODO: 实现批量查询用户信息逻辑
90+
Ok(())
91+
}
92+
93+
pub async fn do_kick_out(_auth: AuthInfo, _work_id: String) -> Result<()> {
94+
// TODO: 实现踢出用户逻辑
95+
Ok(())
96+
}

packages/router/src/middlewares/auth_extrator.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ use axum_extra::{
1010
TypedHeader,
1111
};
1212

13-
use _utils::{
14-
jwt::{verify_token, AuthInfo},
15-
models::CommonResponse,
16-
};
13+
use _functions::functions::system::oauth::oauth_parse_token;
14+
use _utils::{jwt::AuthInfo, models::CommonResponse};
1715

1816
pub struct ExtractAuthInfo(pub AuthInfo);
1917

@@ -28,7 +26,7 @@ where
2826
TypedHeader::<Authorization<Bearer>>::from_request_parts(parts, state).await
2927
{
3028
let token = bearer.token().to_string();
31-
let claims = verify_token(&token).await.map_err(|err| {
29+
let (info, claims) = oauth_parse_token(token).await.map_err(|err| {
3230
(
3331
StatusCode::UNAUTHORIZED,
3432
serde_json::to_string(&CommonResponse::<()>::new(Err(err)))
@@ -38,8 +36,7 @@ where
3836
})?;
3937

4038
return Ok(Self(AuthInfo {
41-
token,
42-
user_id: claims.sub,
39+
info,
4340
created_at: claims.iat,
4441
expires_at: claims.exp,
4542
}));

packages/router/src/routes/system/action_log.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
use anyhow::Result;
22
use serde::{Deserialize, Serialize};
33

4-
use axum::{extract::Query, http::StatusCode, response::IntoResponse};
4+
use axum::{
5+
extract::{Json, Query},
6+
http::StatusCode,
7+
response::IntoResponse,
8+
};
59

610
use crate::middlewares::ExtractAuthInfo;
7-
use _utils::models::wrapper::Pagination;
11+
use _utils::{
12+
models::Pagination,
13+
types::{ActionLogAction, SystemUserRole},
14+
};
815

9-
/// 设备状态
10-
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11-
pub enum Action {
12-
#[serde(rename = "LOGIN")]
13-
Login,
14-
}
15-
16-
/// 操作日志排序枚举
16+
/// 格式:字段+ 字段-
1717
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1818
pub enum ActionLogSort {
19-
#[serde(rename = "action+")]
20-
Action,
21-
#[serde(rename = "action-")]
22-
ActionReverse,
19+
#[serde(rename = "createTime+")]
20+
CreateTime,
21+
#[serde(rename = "createTime-")]
22+
CreateTimeReverse,
2323
#[serde(rename = "deviceId+")]
2424
DeviceId,
2525
#[serde(rename = "deviceId-")]
@@ -46,7 +46,7 @@ pub enum ActionLogSort {
4646
#[serde(rename_all = "camelCase")]
4747
pub struct ActionLogParams {
4848
/// 设备状态
49-
pub action: Option<Action>,
49+
pub action: Option<ActionLogAction>,
5050
#[serde(flatten)]
5151
pub pagination: Option<Pagination>,
5252
/// 设备ID
@@ -68,5 +68,9 @@ pub async fn list(
6868
ExtractAuthInfo(auth): ExtractAuthInfo,
6969
Query(query): Query<ActionLogParams>,
7070
) -> Result<impl IntoResponse, (StatusCode, String)> {
71-
Ok(())
71+
if auth.info.role_id != SystemUserRole::Admin {
72+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
73+
}
74+
75+
Ok(Json(()).into_response())
7276
}

packages/router/src/routes/system/archive.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use axum::{
99
};
1010

1111
use crate::middlewares::ExtractAuthInfo;
12+
use _utils::types::SystemUserRole;
1213

1314
/// 获取指定槽位的最新存档
1415
/// GET /archive/last/{slot_index}
@@ -17,7 +18,11 @@ pub async fn get_last(
1718
ExtractAuthInfo(auth): ExtractAuthInfo,
1819
Path(slot_index): Path<u64>,
1920
) -> Result<impl IntoResponse, (StatusCode, String)> {
20-
Ok(())
21+
if auth.info.role_id != SystemUserRole::Admin {
22+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
23+
}
24+
25+
Ok(Json(()).into_response())
2126
}
2227

2328
/// 获取指定槽位的所有历史存档
@@ -27,7 +32,11 @@ pub async fn get_history(
2732
ExtractAuthInfo(auth): ExtractAuthInfo,
2833
Path(slot_index): Path<u64>,
2934
) -> Result<impl IntoResponse, (StatusCode, String)> {
30-
Ok(())
35+
if auth.info.role_id != SystemUserRole::Admin {
36+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
37+
}
38+
39+
Ok(Json(()).into_response())
3140
}
3241

3342
/// 获取所有槽位的历史存档
@@ -36,7 +45,11 @@ pub async fn get_history(
3645
pub async fn get_all_history(
3746
ExtractAuthInfo(auth): ExtractAuthInfo,
3847
) -> Result<impl IntoResponse, (StatusCode, String)> {
39-
Ok(())
48+
if auth.info.role_id != SystemUserRole::Admin {
49+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
50+
}
51+
52+
Ok(Json(()).into_response())
4053
}
4154

4255
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -55,7 +68,11 @@ pub async fn put(
5568
Path((slot_index, name)): Path<(u64, String)>,
5669
Json(payload): Json<ArchiveSaveParams>,
5770
) -> Result<impl IntoResponse, (StatusCode, String)> {
58-
Ok(())
71+
if auth.info.role_id != SystemUserRole::Admin {
72+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
73+
}
74+
75+
Ok(Json(()).into_response())
5976
}
6077

6178
/// 存档入指定槽位
@@ -66,7 +83,11 @@ pub async fn save(
6683
Path(slot_index): Path<u64>,
6784
Json(payload): Json<ArchiveSaveParams>,
6885
) -> Result<impl IntoResponse, (StatusCode, String)> {
69-
Ok(())
86+
if auth.info.role_id != SystemUserRole::Admin {
87+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
88+
}
89+
90+
Ok(Json(()).into_response())
7091
}
7192

7293
/// 重命名指定槽位
@@ -76,7 +97,11 @@ pub async fn rename(
7697
ExtractAuthInfo(auth): ExtractAuthInfo,
7798
Path((slot_index, new_name)): Path<(u64, String)>,
7899
) -> Result<impl IntoResponse, (StatusCode, String)> {
79-
Ok(())
100+
if auth.info.role_id != SystemUserRole::Admin {
101+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
102+
}
103+
104+
Ok(Json(()).into_response())
80105
}
81106

82107
/// 删除最近一次存档(恢复为上次存档)
@@ -86,7 +111,11 @@ pub async fn restore(
86111
ExtractAuthInfo(auth): ExtractAuthInfo,
87112
Path(slot_index): Path<u64>,
88113
) -> Result<impl IntoResponse, (StatusCode, String)> {
89-
Ok(())
114+
if auth.info.role_id != SystemUserRole::Admin {
115+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
116+
}
117+
118+
Ok(Json(()).into_response())
90119
}
91120

92121
/// 删除存档槽位
@@ -96,5 +125,9 @@ pub async fn delete_slot(
96125
ExtractAuthInfo(auth): ExtractAuthInfo,
97126
Path(slot_index): Path<u64>,
98127
) -> Result<impl IntoResponse, (StatusCode, String)> {
99-
Ok(())
128+
if auth.info.role_id != SystemUserRole::Admin {
129+
return Ok((axum::http::StatusCode::FORBIDDEN, "Forbidden".to_string()).into_response());
130+
}
131+
132+
Ok(Json(()).into_response())
100133
}

0 commit comments

Comments
 (0)