diff --git a/api/src/controller/account.rs b/api/src/controller/account.rs index a59fef4..6c4b94e 100644 --- a/api/src/controller/account.rs +++ b/api/src/controller/account.rs @@ -1,6 +1,6 @@ use axum::Json; use axum_extra::extract::WithRejection; -use domain::dto::account::AuthenticateGooleAccountReq; +use domain::dto::account::{AuthenticateGooleAccountReq, AuthenticateWithPassword}; use library::resp::{rejection::IRejection, response::{ ResOK, ResResult}}; use validator::Validate; @@ -13,3 +13,11 @@ pub async fn authenticate_google( Ok(ResOK(None)) } + +pub async fn authenticate_with_password( + WithRejection(Json(req), _): IRejection> +) -> ResResult> { + req.validate()?; + + service::sys_account::authenticate_with_password(req).await +} \ No newline at end of file diff --git a/api/src/router.rs b/api/src/router.rs index 27b5249..9f13c77 100644 --- a/api/src/router.rs +++ b/api/src/router.rs @@ -9,14 +9,29 @@ pub(crate) fn init() -> Router { let open = Router::new().route("/", get(|| async { "hello" })); let auth: Router = Router::new() - .route("/account/google", post(controller::account::authenticate_google)) - .route("/feedback", post(controller::feedback::add_feedback).get(controller::feedback::get_feedback_list_by_page)) - .layer(axum::middleware::from_fn(library::middleware::req_token::authenticate_access_token)); + .route( + "/account/google", + post(controller::account::authenticate_google), + ) + .route( + "/account/sys", + post(controller::account::authenticate_with_password), + ) + .route( + "/feedback", + post(controller::feedback::add_feedback) + .get(controller::feedback::get_feedback_list_by_page), + ) + .layer(axum::middleware::from_fn( + library::middleware::req_token::authenticate_access_token, + )); Router::new() .nest("/", open) - .nest("/v1", auth) - .layer(axum::middleware::from_fn(library::middleware::req_log::handle)) + .nest("/gm/v1", auth) + .layer(axum::middleware::from_fn( + library::middleware::req_log::handle, + )) .layer(axum::middleware::from_fn(library::middleware::cors::handle)) .layer( TraceLayer::new_for_http().make_span_with(|request: &Request| { @@ -32,5 +47,7 @@ pub(crate) fn init() -> Router { tracing::error_span!("request_id", id = req_id) }), ) - .layer(axum::middleware::from_fn(library::middleware::req_id::handle)) + .layer(axum::middleware::from_fn( + library::middleware::req_id::handle, + )) } diff --git a/domain/src/entities/account.rs b/domain/src/entities/account.rs index 7e0881a..79ecce9 100644 --- a/domain/src/entities/account.rs +++ b/domain/src/entities/account.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use chrono::{DateTime, Utc}; use sqlx::{Error, PgPool}; use sqlx::types::{chrono, JsonValue}; @@ -14,6 +16,15 @@ impl Default for Role { } } +impl Display for Role { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Role::Admin => write!(f, "admin"), + Role::User => write!(f, "user"), + } + } +} + // impl sqlx::Type for Role { // fn type_info() -> sqlx::postgres::PgTypeInfo { // sqlx::postgres::PgTypeInfo::with_name("CHAR(1)") @@ -202,4 +213,32 @@ impl Account { } } } + + pub async fn add_account(&self, db_pool: &PgPool) -> Result, Error> { + match sqlx::query_as!( + Account, + r#" + insert into account + (username, password, lang_tag, role) + values + ($1, $2, $3, $4) returning * + "#, + self.username, + self.password, + self.lang_tag, + self.role.to_string() + ).fetch_one(db_pool).await { + Ok(account) => { + return Ok(Some(account)); + } + Err(Error::RowNotFound) => { + return Ok(None); + } + Err(e) => { + tracing::error!("add_account error: {:?}", e); + return Err(e); + } + } + } + } \ No newline at end of file diff --git a/library/src/middleware/req_token.rs b/library/src/middleware/req_token.rs index ea6f770..02fbe74 100644 --- a/library/src/middleware/req_token.rs +++ b/library/src/middleware/req_token.rs @@ -7,7 +7,8 @@ use crate::{cache::login_cache::LOGIN_CACHE, config, token::Claims}; const WHITE_LIST: &[(&str, &str)] = &[ ("GET", "/api/v1/users/:id"), ("POST", "/api/v1/orders"), - ("GET", "/feedback") + ("GET", "/feedback"), + ("POST", "/account/sys"), ]; pub async fn authenticate_access_token(mut req: Request, next: Next) -> Response { diff --git a/service/src/sys_account.rs b/service/src/sys_account.rs index c6f569f..fd6573f 100644 --- a/service/src/sys_account.rs +++ b/service/src/sys_account.rs @@ -8,9 +8,10 @@ use library::{ }; -pub async fn authticate_with_password( +pub async fn authenticate_with_password( req: AuthenticateWithPassword, ) -> ResResult> { + let account = Account::find_with_password(req.username.unwrap(), req.password.unwrap(), db!()).await?; if account.is_none() { @@ -42,3 +43,21 @@ pub async fn authticate_with_password( Ok(ResOK(Some((token, refresh_token)))) } + +pub async fn add_account() -> ResResult> { + let account = Account::add_account( + &Account { + username: "admin".to_string(), + password: Some("123456".as_bytes().to_vec()), + role: Role::Admin, + ..Default::default() + }, + db!(), + ) + .await?; + if account.is_none() { + tracing::error!("添加用户失败"); + return Err(ResErr::service("添加用户失败")); + } + Ok(ResOK(None)) +} \ No newline at end of file