From 991d1e478b9b42706158fe63334670a41c641351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=BF=90=E5=AE=B6?= Date: Wed, 19 Jun 2024 17:26:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=94=E5=9B=9E=E4=BF=A1=E6=81=AF=E6=94=B9?= =?UTF-8?q?=E4=B8=BAi18n=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/controller/account.rs | 6 ++-- i18n/src/en_us.rs | 11 +++++- i18n/src/lib.rs | 2 +- i18n/src/message_ids.rs | 6 +++- i18n/src/zh_cn.rs | 8 ++++- library/src/cache/account_cache.rs | 6 ++-- library/src/context.rs | 11 +++--- library/src/middleware/req_ctx.rs | 20 +++-------- service/src/account.rs | 19 ++++++---- service/src/feedback.rs | 2 -- service/src/sys_account.rs | 58 ++++++++++++++++++++---------- 11 files changed, 92 insertions(+), 57 deletions(-) diff --git a/api/src/controller/account.rs b/api/src/controller/account.rs index bf3ccd6..3e39c67 100644 --- a/api/src/controller/account.rs +++ b/api/src/controller/account.rs @@ -3,17 +3,19 @@ use domain::{dto::account::{AuthenticateGooleAccountReq, AuthenticateWithPasswor use library::{context::Context, res::{response::{ ResData, ResResult}, validator}}; pub async fn authenticate_google( + Extension(context): Extension, Json(req): Json ) -> ResResult> { validator::validate_params(&req, "")?; - service::account::authenticate_google(req).await + service::account::authenticate_google(context, req).await } pub async fn authenticate_with_password( + Extension(context): Extension, Json(req): Json ) -> ResResult> { validator::validate_params(&req, "")?; - service::sys_account::authenticate_with_password(req).await + service::sys_account::authenticate_with_password(context, req).await } pub async fn refresh_token( diff --git a/i18n/src/en_us.rs b/i18n/src/en_us.rs index 1a63274..5d233f1 100644 --- a/i18n/src/en_us.rs +++ b/i18n/src/en_us.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use lazy_static::lazy_static; -use crate::message_ids::HELLO; +use crate::message_ids::{ + ACCOUNT_DISABLED, ACCOUNT_NO_PERMISSION, HELLO, INCORRECT_USERNAME_OR_PASSWORD, INVALID_TOKEN, +}; pub const LANGUAGE_ID: &str = "en-US"; @@ -10,6 +12,13 @@ lazy_static! { pub static ref MESSAGE: HashMap<&'static str, &'static str> = { let mut map = HashMap::new(); map.insert(HELLO, "hello {}"); + map.insert(ACCOUNT_DISABLED, "account is disabled"); + map.insert(ACCOUNT_NO_PERMISSION, "account has no permission"); + map.insert( + INCORRECT_USERNAME_OR_PASSWORD, + "incorrect username or password", + ); + map.insert(INVALID_TOKEN, "invalid token"); map }; } diff --git a/i18n/src/lib.rs b/i18n/src/lib.rs index 552be3f..1196808 100644 --- a/i18n/src/lib.rs +++ b/i18n/src/lib.rs @@ -19,7 +19,7 @@ fn get_i18n() -> &'static HashMap<&'static str, HashMap<&'static str, &'static s I18N.get_or_init(init_i18n) } -pub fn lang(lang_id: &'static str, message_id: &'static str) -> &'static str { +pub fn lang(lang_id: &str, message_id: &'static str) -> &'static str { get_i18n() .get(lang_id) .and_then(|map| map.get(message_id)) diff --git a/i18n/src/message_ids.rs b/i18n/src/message_ids.rs index dc71a5a..bde7bc9 100644 --- a/i18n/src/message_ids.rs +++ b/i18n/src/message_ids.rs @@ -1 +1,5 @@ -pub const HELLO: &str = "hello"; \ No newline at end of file +pub const HELLO: &str = "hello"; +pub const ACCOUNT_DISABLED: &str = "accout is disabled"; +pub const ACCOUNT_NO_PERMISSION: &str = "account has no permission"; +pub const INCORRECT_USERNAME_OR_PASSWORD: &str = "Incorrect username or password"; +pub const INVALID_TOKEN: &str = "invalid token"; diff --git a/i18n/src/zh_cn.rs b/i18n/src/zh_cn.rs index e96e2a5..a24e9f6 100644 --- a/i18n/src/zh_cn.rs +++ b/i18n/src/zh_cn.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use lazy_static::lazy_static; -use crate::message_ids::HELLO; +use crate::message_ids::{ + ACCOUNT_DISABLED, ACCOUNT_NO_PERMISSION, HELLO, INCORRECT_USERNAME_OR_PASSWORD, INVALID_TOKEN, +}; pub const LANGUAGE_ID: &str = "zh_CN"; @@ -10,6 +12,10 @@ lazy_static! { pub static ref MESSAGE: HashMap<&'static str, &'static str> = { let mut map = HashMap::new(); map.insert(HELLO, "你好 {}"); + map.insert(ACCOUNT_DISABLED, "账户已禁用"); + map.insert(ACCOUNT_NO_PERMISSION, "账户无权限"); + map.insert(INCORRECT_USERNAME_OR_PASSWORD, "用户名或密码错误"); + map.insert(INVALID_TOKEN, "无效令牌"); map }; } diff --git a/library/src/cache/account_cache.rs b/library/src/cache/account_cache.rs index 72cd9d6..2f15fce 100644 --- a/library/src/cache/account_cache.rs +++ b/library/src/cache/account_cache.rs @@ -1,4 +1,4 @@ -use std::time::Duration; +use std::{sync::Arc, time::Duration}; use domain::entities::account::Account; use lazy_static::lazy_static; @@ -10,8 +10,8 @@ use moka::{ #[derive(Debug, Clone)] pub struct CacheAccount { - pub account: Account, - pub token: String, + pub account: Arc, + pub token: Arc, } lazy_static! { diff --git a/library/src/context.rs b/library/src/context.rs index ba609ee..da956df 100644 --- a/library/src/context.rs +++ b/library/src/context.rs @@ -1,11 +1,12 @@ +use std::sync::Arc; + use domain::entities::account::Account; #[derive(Debug, Clone)] pub struct Context { - pub account: Account, - pub local: String, - pub token: String, + pub account: Arc, + pub token: Arc, } impl Context { @@ -17,7 +18,7 @@ impl Context { &self.token } - pub fn get_local(&self) -> &String { - &self.local + pub fn get_lang_id(&self) -> &String { + &self.account.lang_tag } } \ No newline at end of file diff --git a/library/src/middleware/req_ctx.rs b/library/src/middleware/req_ctx.rs index e2faf89..561ceba 100644 --- a/library/src/middleware/req_ctx.rs +++ b/library/src/middleware/req_ctx.rs @@ -34,20 +34,6 @@ pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response { None => return (StatusCode::UNAUTHORIZED, "Missing authorization header".to_string()).into_response(), }; - // 解析语言 - let language_header = req.headers().get(header::ACCEPT_LANGUAGE); - let language = match language_header { - Some(value) => { - let value_str: Vec<&str> = value.to_str().unwrap_or("zh-CN").split(',').collect(); - if value_str.is_empty() { - String::from("zh-CN") - } else { - String::from(value_str[0]) - } - }, - None => String::from("zh-CN"), - }; - let validation = Validation::default(); match decode::(token, &DecodingKey::from_secret(config!().jwt.token_secret.as_bytes()), &validation) { Ok(decoded) => { @@ -63,7 +49,11 @@ pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response { // return (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response(); // } // 将Claims附加到请求扩展中,以便后续处理使用 - req.extensions_mut().insert(Context { account: account.account, local: language, token: account.token }); + req.extensions_mut().insert( + Context { + account: account.account.clone(), + token: account.token + }); next.run(req).await }, Err(_) => (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response(), diff --git a/service/src/account.rs b/service/src/account.rs index bba06ce..66d626a 100644 --- a/service/src/account.rs +++ b/service/src/account.rs @@ -1,7 +1,11 @@ +use std::sync::Arc; + use chrono::Utc; use domain::dto::account::AuthenticateGooleAccountReq; use domain::entities::account::Account; use domain::vo::account::{LoginAccount, RefreshTokenResult}; +use i18n::message; +use i18n::message_ids::{ACCOUNT_DISABLED, INVALID_TOKEN}; use library::cache::account_cache::{CacheAccount, LOGIN_CACHE}; use library::context::Context; use library::res::response::ResErr::ErrPerm; @@ -11,6 +15,7 @@ use library::token::{generate_refresh_token, generate_token}; use library::{db, token}; pub async fn authenticate_google( + context: Context, req: AuthenticateGooleAccountReq, ) -> ResResult> { let verify_result = GOOGLE_SOCIAL @@ -42,7 +47,7 @@ pub async fn authenticate_google( tracing::info!("账户已存在, {:?}", account); if account.disable_time > Utc::now() { tracing::error!("账户已禁用"); - return Err(ResErr::system("账户已禁用")); + return Err(ResErr::system(message!(context.get_lang_id(), ACCOUNT_DISABLED))); } account } @@ -55,8 +60,8 @@ pub async fn authenticate_google( .insert( account.id.to_owned(), CacheAccount { - account: account.clone(), - token: token.to_owned(), + account: Arc::new(account.to_owned()), + token: Arc::new(token.to_owned()), }, ) .await; @@ -78,10 +83,10 @@ pub async fn refresh_token( context: Context, refresh_token: String, ) -> ResResult> { - let account = context.account; + let account = context.account.clone(); if token::verify_refresh_token(&refresh_token).is_err() { - return Err(ResErr::params("refresh_token无效")); + return Err(ResErr::params(message!(context.get_lang_id(), INVALID_TOKEN))); } let refresh_token = RefreshTokenResult { @@ -94,8 +99,8 @@ pub async fn refresh_token( .insert( account.id.to_owned(), CacheAccount { - account: account.clone(), - token: refresh_token.token.to_owned(), + account, + token: Arc::new(refresh_token.token.to_owned()), }, ) .await; diff --git a/service/src/feedback.rs b/service/src/feedback.rs index 9c5dc28..706f68b 100644 --- a/service/src/feedback.rs +++ b/service/src/feedback.rs @@ -1,6 +1,5 @@ use domain::dto::feedback::FeedbackAdd; use domain::entities::feedback::Feedback; -use i18n::message; use library::db; use library::res::pageable::Pageable; use library::res::response::{ResData, ResResult}; @@ -13,7 +12,6 @@ pub async fn get_feedback_list_by_page(page: i64, page_size: i64) -> ResResult::empty())); } let total = get_feedback_count().await; - tracing::info!("你好: {}", message!("zh_CN", "hello", "明天", "结束")); Ok(ResData::some(Pageable::new(feedback_list.unwrap(), total))) } diff --git a/service/src/sys_account.rs b/service/src/sys_account.rs index 52cc54e..922cbef 100644 --- a/service/src/sys_account.rs +++ b/service/src/sys_account.rs @@ -1,31 +1,50 @@ +use std::sync::Arc; + use chrono::Utc; use domain::{ dto::account::AuthenticateWithPassword, - entities::account::{Account, Role}, vo::account::LoginAccount, + entities::account::{Account, Role}, + vo::account::LoginAccount, +}; +use i18n::{ + message, + message_ids::{ACCOUNT_DISABLED, ACCOUNT_NO_PERMISSION, INCORRECT_USERNAME_OR_PASSWORD}, }; use library::{ - cache::account_cache::{CacheAccount, LOGIN_CACHE}, db, res::response::{ResErr, ResData, ResResult}, token::{generate_refresh_token, generate_token} + cache::account_cache::{CacheAccount, LOGIN_CACHE}, + context::Context, + db, + res::response::{ResData, ResErr, ResResult}, + token::{generate_refresh_token, generate_token}, }; - pub async fn authenticate_with_password( + context: Context, req: AuthenticateWithPassword, ) -> ResResult> { - let account = Account::find_with_password(req.username.unwrap(), req.password.unwrap(), db!()).await?; if account.is_none() { tracing::info!("登录用户失败,用户查询为空"); - return Err(ResErr::params("用户名或密码错误")); + return Err(ResErr::params(message!( + context.get_lang_id(), + INCORRECT_USERNAME_OR_PASSWORD + ))); } let account = account.unwrap(); if account.disable_time > Utc::now() { tracing::error!("账户已禁用"); - return Err(ResErr::auth("账户已禁用")); + return Err(ResErr::auth(message!( + context.get_lang_id(), + ACCOUNT_DISABLED + ))); } if account.role != Role::Admin { tracing::error!("账户不是管理员,无权限"); - return Err(ResErr::perm("账户无权限")); + return Err(ResErr::perm(message!( + context.get_lang_id(), + ACCOUNT_NO_PERMISSION + ))); } let token = generate_token(&account.id); @@ -35,25 +54,26 @@ pub async fn authenticate_with_password( .insert( account.id.to_owned(), CacheAccount { - account: account.clone(), - token: token.to_owned(), + account: Arc::new(account.to_owned()), + token: Arc::new(token.to_owned()), }, ) .await; - let login_account = LoginAccount{ - username: account.username, - display_name: account.display_name, - avatar_url: account.avatar_url, - metadata: account.metadata, - wallet: account.wallet, - email: account.email, - token, - refresh_token + let login_account = LoginAccount { + username: account.username, + display_name: account.display_name, + avatar_url: account.avatar_url, + metadata: account.metadata, + wallet: account.wallet, + email: account.email, + token, + refresh_token, }; Ok(ResData::some(login_account)) } +/// 仅仅用于管理员维护,不对外暴露接口 pub async fn add_account() -> ResResult> { let account = Account::add_account( &Account { @@ -70,4 +90,4 @@ pub async fn add_account() -> ResResult> { return Err(ResErr::service("添加用户失败")); } Ok(ResData(None)) -} \ No newline at end of file +}