i18n增加校验,检查系统用到的多语言字段是否在csv文件中定义
This commit is contained in:
parent
f7dca5ba30
commit
ba544174b7
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -292,6 +292,7 @@ dependencies = [
|
|||||||
name = "chuanyue-service"
|
name = "chuanyue-service"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"i18n",
|
||||||
"library",
|
"library",
|
||||||
"mimalloc",
|
"mimalloc",
|
||||||
"server",
|
"server",
|
||||||
@ -821,6 +822,12 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -992,6 +999,8 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"csv",
|
"csv",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"strum",
|
||||||
|
"strum_macros",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2250,7 +2259,7 @@ checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"either",
|
"either",
|
||||||
"heck",
|
"heck 0.4.1",
|
||||||
"hex",
|
"hex",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -2397,6 +2406,25 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn 2.0.77",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
@ -14,6 +14,7 @@ mimalloc = { workspace = true }
|
|||||||
|
|
||||||
server = { path = "server" }
|
server = { path = "server" }
|
||||||
library = { path = "library" }
|
library = { path = "library" }
|
||||||
|
i18n = { path = "i18n" }
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
tokio = "1.36"
|
tokio = "1.36"
|
||||||
@ -53,4 +54,6 @@ syn = "2.0.77"
|
|||||||
quote = "1.0.37"
|
quote = "1.0.37"
|
||||||
hyper = "1.4.1"
|
hyper = "1.4.1"
|
||||||
tower = "0.5.1"
|
tower = "0.5.1"
|
||||||
csv = "1.3.0"
|
csv = "1.3.0"
|
||||||
|
strum = "0.26.3"
|
||||||
|
strum_macros = "0.26.3"
|
@ -3,15 +3,15 @@ use validator::Validate;
|
|||||||
|
|
||||||
#[derive(Debug, Validate, Deserialize, Serialize)]
|
#[derive(Debug, Validate, Deserialize, Serialize)]
|
||||||
pub struct AuthenticateWithPassword {
|
pub struct AuthenticateWithPassword {
|
||||||
#[validate(required(message = "VALIDATE_ACCOUNT_NAME_REQUIRED"), length(min = 1, message = "VALIDATE_ACCOUNT_NAME_REQUIRED"))]
|
#[validate(required(message = "ValidateAccountNameRequired"), length(min = 1, message = "ValidateAccountNameRequired"))]
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
#[validate(required(message = "VALIDATE_ACCOUNT_PASSWORD_REQUIRED"), length(min = 1, message = "VALIDATE_ACCOUNT_PASSWORD_REQUIRED"))]
|
#[validate(required(message = "ValidateAccountPasswordRequired"), length(min = 1, message = "ValidateAccountPasswordRequired"))]
|
||||||
pub password: Option<String>,
|
pub password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Validate, Deserialize, Serialize)]
|
#[derive(Debug, Validate, Deserialize, Serialize)]
|
||||||
pub struct AuthenticateGooleAccountReq {
|
pub struct AuthenticateGooleAccountReq {
|
||||||
#[validate(required(message = "VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED"), length(min = 1, message = "VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED"))]
|
#[validate(required(message = "ValidateAccountIdTokenRequired"), length(min = 1, message = "ValidateAccountIdTokenRequired"))]
|
||||||
pub id_token: Option<String>,
|
pub id_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@ use validator::Validate;
|
|||||||
|
|
||||||
#[derive(Debug, Validate, Deserialize, Serialize)]
|
#[derive(Debug, Validate, Deserialize, Serialize)]
|
||||||
pub struct FeedbackAdd {
|
pub struct FeedbackAdd {
|
||||||
#[validate(required(message = "VALIDATE_FEEDBACK_CONTENT_REQUIRED"), length(min = 1, message = "VALIDATE_FEEDBACK_CONTENT_REQUIRED"))]
|
#[validate(required(message = "ValidateFeedbackContentRequired"), length(min = 1, message = "ValidateFeedbackContentRequired"))]
|
||||||
pub content: Option<String>
|
pub content: Option<String>
|
||||||
}
|
}
|
@ -3,9 +3,9 @@ use validator::Validate;
|
|||||||
|
|
||||||
#[derive(Deserialize, Validate)]
|
#[derive(Deserialize, Validate)]
|
||||||
pub struct PageParams {
|
pub struct PageParams {
|
||||||
#[validate(required(message = "VALIDATE_PAGEABLE_PAGE_REQUIRED"), range(min = 1, message = "VALIDATE_PAGEABLE_PAGE_REQUIRED"))]
|
#[validate(required(message = "ValidatePageablePageRequired"), range(min = 1, message = "ValidatePageablePageRequired"))]
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
#[serde(rename = "pageSize")]
|
#[serde(rename = "pageSize")]
|
||||||
#[validate(required(message = "VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED"), range(min = 1, message = "VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED"))]
|
#[validate(required(message = "ValidatePageablePageSizeRequired"), range(min = 1, message = "ValidatePageablePageSizeRequired"))]
|
||||||
pub page_size: Option<i64>,
|
pub page_size: Option<i64>,
|
||||||
}
|
}
|
26
i18n.csv
26
i18n.csv
@ -1,14 +1,14 @@
|
|||||||
id,en-US,zh-CN
|
id,en-US,zh-CN
|
||||||
SERVER_INTERNAL_ERROR,Internal server error,系统内部错误
|
ServerInternalError,Internal server error,系统内部错误
|
||||||
HELLO,hello {},你好 {}
|
Hello,hello {},你好 {}
|
||||||
ACCOUNT_DISABLED,account is disabled,账户已禁用
|
AccountDisabled,account is disabled,账户已禁用
|
||||||
ACCOUNT_NO_PERMISSION,account has no permission,账户无权限
|
AccountNoPermission,account has no permission,账户无权限
|
||||||
INCORRECT_USERNAME_OR_PASSWORD,incorrect username or password,用户名或密码错误
|
IncorrectUsernameOrPassword,incorrect username or password,用户名或密码错误
|
||||||
INVALID_TOKEN,invalid token,无效令牌
|
InvalidToken,invalid token,无效令牌
|
||||||
VALIDATE_FEEDBACK_CONTENT_REQUIRED,feedback content is required,反馈内容不能为空
|
ValidateFeedbackContentRequired,feedback content is required,反馈内容不能为空
|
||||||
VALIDATE_ACCOUNT_NAME_REQUIRED,username is required,"用户名称不能为空"
|
ValidateAccountNameRequired,username is required,"用户名称不能为空"
|
||||||
VALIDATE_ACCOUNT_PASSWORD_REQUIRED,password is required,密码不能为空
|
ValidateAccountPasswordRequired,password is required,密码不能为空
|
||||||
VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED,ID Token is required,用户ID Token不能为空
|
ValidateAccountIdTokenRequired,ID Token is required,用户ID Token不能为空
|
||||||
VALIDATE_ACCOUNT_LANG_TAG_REQUIRED,lang tag is required,用户语言标识不能为空
|
ValidateAccountLangTagRequired,lang tag is required,用户语言标识不能为空
|
||||||
VALIDATE_PAGEABLE_PAGE_REQUIRED,invalid page number,页码无效
|
ValidatePageablePageRequired,invalid page number,页码无效
|
||||||
VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED,invalid quantity per page,每页数量无效
|
ValidatePageablePageSizeRequired,invalid quantity per page,每页数量无效
|
|
@ -6,4 +6,6 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = { workspace = true }
|
lazy_static = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
csv = { workspace = true }
|
csv = { workspace = true }
|
||||||
|
strum = { workspace = true }
|
||||||
|
strum_macros = { workspace = true }
|
@ -2,12 +2,15 @@ extern crate self as i18n;
|
|||||||
|
|
||||||
use std::{collections::HashMap, sync::OnceLock};
|
use std::{collections::HashMap, sync::OnceLock};
|
||||||
|
|
||||||
|
use message_ids::MessageId;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
pub mod message_ids;
|
pub mod message_ids;
|
||||||
|
|
||||||
const I18N_FILE: &str = "i18n.csv";
|
const I18N_FILE: &str = "i18n.csv";
|
||||||
static I18N: OnceLock<HashMap<&'static str, HashMap<&'static str, &'static str>>> = OnceLock::new();
|
static I18N: OnceLock<HashMap<&'static str, HashMap<&'static str, &'static str>>> = OnceLock::new();
|
||||||
|
|
||||||
fn init_i18n() -> HashMap<&'static str, HashMap<&'static str, &'static str>> {
|
fn init() -> HashMap<&'static str, HashMap<&'static str, &'static str>> {
|
||||||
let mut i18n_map = HashMap::new();
|
let mut i18n_map = HashMap::new();
|
||||||
let mut i18n_id_map = HashMap::new();
|
let mut i18n_id_map = HashMap::new();
|
||||||
let mut rdr = csv::Reader::from_path(I18N_FILE).expect("读取多语言文件失败");
|
let mut rdr = csv::Reader::from_path(I18N_FILE).expect("读取多语言文件失败");
|
||||||
@ -31,19 +34,27 @@ fn init_i18n() -> HashMap<&'static str, HashMap<&'static str, &'static str>> {
|
|||||||
.insert(message_id, message);
|
.insert(message_id, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracing::info!("多语言文件解析完成:{:?}", i18n_map);
|
|
||||||
|
// 检查多语言文件是否完整
|
||||||
|
for (lang_id, lang_map) in i18n_map.iter() {
|
||||||
|
MessageId::iter().for_each(|message_id| {
|
||||||
|
if !lang_map.contains_key(message_id.as_ref()) {
|
||||||
|
tracing::error!("多语言文件缺失消息:{},语言:{}", message_id, lang_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
i18n_map
|
i18n_map
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_i18n() -> &'static HashMap<&'static str, HashMap<&'static str, &'static str>> {
|
pub fn init_i18n() -> &'static HashMap<&'static str, HashMap<&'static str, &'static str>> {
|
||||||
I18N.get_or_init(init_i18n)
|
I18N.get_or_init(init)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取语言模板
|
/// 获取语言模板
|
||||||
pub fn lang(lang_id: &str, message_id: &str) -> &'static str {
|
pub fn lang(lang_id: &str, message_id: MessageId) -> &'static str {
|
||||||
get_i18n()
|
init_i18n()
|
||||||
.get(lang_id)
|
.get(lang_id)
|
||||||
.and_then(|map| map.get(message_id))
|
.and_then(|map| map.get(message_id.as_ref()))
|
||||||
.unwrap_or_else(|| &"UNKNOWN")
|
.unwrap_or_else(|| &"UNKNOWN")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
pub const SERVER_INTERNAL_ERROR: &str = "SERVER_INTERNAL_ERROR";
|
use strum_macros::{AsRefStr, Display, EnumIter, EnumString};
|
||||||
|
|
||||||
pub const HELLO: &str = "HELLO";
|
#[derive(Debug, EnumIter, EnumString, Display, PartialEq, AsRefStr)]
|
||||||
pub const ACCOUNT_DISABLED: &str = "ACCOUNT_DISABLED";
|
pub enum MessageId {
|
||||||
pub const ACCOUNT_NO_PERMISSION: &str = "ACCOUNT_NO_PERMISSION";
|
ServerInternalError,
|
||||||
pub const INCORRECT_USERNAME_OR_PASSWORD: &str = "INCORRECT_USERNAME_OR_PASSWORD";
|
Hello,
|
||||||
pub const INVALID_TOKEN: &str = "INVALID_TOKEN";
|
AccountDisabled,
|
||||||
|
AccountNoPermission,
|
||||||
|
IncorrectUsernameOrPassword,
|
||||||
|
InvalidToken,
|
||||||
|
|
||||||
pub const VALIDATE_FEEDBACK_CONTENT_REQUIRED: &'static str = "VALIDATE_FEEDBACK_CONTENT_REQUIRED";
|
ValidateFeedbackContentRequired,
|
||||||
pub const VALIDATE_ACCOUNT_NAME_REQUIRED: &'static str = "VALIDATE_ACCOUNT_NAME_REQUIRED";
|
ValidateAccountNameRequired,
|
||||||
pub const VALIDATE_ACCOUNT_PASSWORD_REQUIRED: &'static str = "VALIDATE_ACCOUNT_PASSWORD_REQUIRED";
|
ValidateAccountPasswordRequired,
|
||||||
pub const VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED: &'static str = "VALIDATE_ACCOUNT_ID_TOKEN_REQUIRED";
|
ValidateAccountIdTokenRequired,
|
||||||
pub const VALIDATE_ACCOUNT_LANG_TAG_REQUIRED: &'static str = "VALIDATE_ACCOUNT_LANG_TAG_REQUIRED";
|
ValidateAccountLangTagRequired,
|
||||||
pub const VALIDATE_PAGEABLE_PAGE_REQUIRED: &'static str = "VALIDATE_PAGEABLE_PAGE_REQUIRED";
|
ValidatePageablePageRequired,
|
||||||
pub const VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED: &'static str = "VALIDATE_PAGEABLE_PAGE_SIZE_REQUIRED";
|
ValidatePageablePageSizeRequired,
|
||||||
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use i18n::message;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use i18n::{message, message_ids::MessageId};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
use super::response::{ResData, ResErr, ResResult};
|
use super::response::{ResData, ResErr, ResResult};
|
||||||
@ -16,7 +18,7 @@ pub fn validate_params(params: &impl Validate, local: &str) -> ResResult<ResData
|
|||||||
err.field_errors().iter().for_each(|(_field, errs)| {
|
err.field_errors().iter().for_each(|(_field, errs)| {
|
||||||
errs.iter().for_each(|e| {
|
errs.iter().for_each(|e| {
|
||||||
let msg = e.message.clone().unwrap_or_default();
|
let msg = e.message.clone().unwrap_or_default();
|
||||||
errors.push(message!(local, msg.trim()))
|
errors.push(message!(local, MessageId::from_str(msg.trim()).unwrap()))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -25,7 +27,7 @@ pub fn validate_params(params: &impl Validate, local: &str) -> ResResult<ResData
|
|||||||
err.field_errors().iter().for_each(|(_field, errs)| {
|
err.field_errors().iter().for_each(|(_field, errs)| {
|
||||||
errs.iter().for_each(|e| {
|
errs.iter().for_each(|e| {
|
||||||
let msg = e.message.clone().unwrap_or_default();
|
let msg = e.message.clone().unwrap_or_default();
|
||||||
errors.push(message!(local, msg.trim()))
|
errors.push(message!(local, MessageId::from_str(msg.trim()).unwrap()))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -33,7 +35,7 @@ pub fn validate_params(params: &impl Validate, local: &str) -> ResResult<ResData
|
|||||||
validator::ValidationErrorsKind::Field(err) => {
|
validator::ValidationErrorsKind::Field(err) => {
|
||||||
err.iter().for_each(|e| {
|
err.iter().for_each(|e| {
|
||||||
let msg = e.message.clone().unwrap_or_default();
|
let msg = e.message.clone().unwrap_or_default();
|
||||||
errors.push(message!(local, msg.trim()))
|
errors.push(message!(local, MessageId::from_str(msg.trim()).unwrap()))
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ use domain::dto::account::AuthenticateGooleAccountReq;
|
|||||||
use domain::entities::account::Account;
|
use domain::entities::account::Account;
|
||||||
use domain::vo::account::{LoginAccount, RefreshTokenResult};
|
use domain::vo::account::{LoginAccount, RefreshTokenResult};
|
||||||
use i18n::message;
|
use i18n::message;
|
||||||
use i18n::message_ids::{ACCOUNT_DISABLED, INVALID_TOKEN};
|
use i18n::message_ids::MessageId;
|
||||||
use library::cache::account_cache::{CacheAccount, LOGIN_CACHE};
|
use library::cache::account_cache::{CacheAccount, LOGIN_CACHE};
|
||||||
use library::context::{Context, WhiteContext};
|
use library::context::{Context, WhiteContext};
|
||||||
use library::model::response::ResErr::ErrPerm;
|
use library::model::response::ResErr::ErrPerm;
|
||||||
@ -48,7 +48,7 @@ pub async fn authenticate_google(
|
|||||||
if let Some(disable_time) = account.disable_time {
|
if let Some(disable_time) = account.disable_time {
|
||||||
if disable_time > Utc::now() {
|
if disable_time > Utc::now() {
|
||||||
tracing::error!("账户已禁用");
|
tracing::error!("账户已禁用");
|
||||||
return Err(ResErr::service(message!(context.get_lang_tag(), ACCOUNT_DISABLED)));
|
return Err(ResErr::service(message!(context.get_lang_tag(), MessageId::AccountDisabled)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ pub async fn refresh_token(
|
|||||||
let account = context.account.clone();
|
let account = context.account.clone();
|
||||||
|
|
||||||
if token::verify_refresh_token(&refresh_token).is_err() {
|
if token::verify_refresh_token(&refresh_token).is_err() {
|
||||||
return Err(ResErr::params(message!(context.get_lang_tag(), INVALID_TOKEN)));
|
return Err(ResErr::params(message!(context.get_lang_tag(), MessageId::InvalidToken)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let refresh_token = RefreshTokenResult {
|
let refresh_token = RefreshTokenResult {
|
||||||
|
@ -8,7 +8,7 @@ use domain::{
|
|||||||
};
|
};
|
||||||
use i18n::{
|
use i18n::{
|
||||||
message,
|
message,
|
||||||
message_ids::{ACCOUNT_DISABLED, ACCOUNT_NO_PERMISSION, INCORRECT_USERNAME_OR_PASSWORD},
|
message_ids::MessageId,
|
||||||
};
|
};
|
||||||
use library::{
|
use library::{
|
||||||
cache::account_cache::{CacheAccount, LOGIN_CACHE}, context::WhiteContext, db, model::response::{ResErr, ResResult}, token::{generate_refresh_token, generate_token}
|
cache::account_cache::{CacheAccount, LOGIN_CACHE}, context::WhiteContext, db, model::response::{ResErr, ResResult}, token::{generate_refresh_token, generate_token}
|
||||||
@ -25,7 +25,7 @@ pub async fn authenticate_with_password(
|
|||||||
tracing::info!("登录用户失败,用户查询为空");
|
tracing::info!("登录用户失败,用户查询为空");
|
||||||
return Err(ResErr::params(message!(
|
return Err(ResErr::params(message!(
|
||||||
context.get_lang_tag(),
|
context.get_lang_tag(),
|
||||||
INCORRECT_USERNAME_OR_PASSWORD
|
MessageId::IncorrectUsernameOrPassword
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let account = account.unwrap();
|
let account = account.unwrap();
|
||||||
@ -34,7 +34,7 @@ pub async fn authenticate_with_password(
|
|||||||
tracing::error!("账户已禁用");
|
tracing::error!("账户已禁用");
|
||||||
return Err(ResErr::auth(message!(
|
return Err(ResErr::auth(message!(
|
||||||
context.get_lang_tag(),
|
context.get_lang_tag(),
|
||||||
ACCOUNT_DISABLED
|
MessageId::AccountDisabled
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ pub async fn authenticate_with_password(
|
|||||||
tracing::error!("账户不是管理员,无权限");
|
tracing::error!("账户不是管理员,无权限");
|
||||||
return Err(ResErr::perm(message!(
|
return Err(ResErr::perm(message!(
|
||||||
context.get_lang_tag(),
|
context.get_lang_tag(),
|
||||||
ACCOUNT_NO_PERMISSION
|
MessageId::AccountNoPermission
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ static GLOBAL: MiMalloc = MiMalloc;
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let (_std_guard, _file_guard) = library::core::logger::init_log(config!());
|
let (_std_guard, _file_guard) = library::core::logger::init_log(config!());
|
||||||
|
let _i18n = i18n::init_i18n();
|
||||||
library::core::db::init_database(config!()).await;
|
library::core::db::init_database(config!()).await;
|
||||||
|
|
||||||
server::serve().await;
|
server::serve().await;
|
||||||
|
Loading…
Reference in New Issue
Block a user