diff --git a/src/template/src/app_error.hbs b/src/template/src/app_error.hbs index fe3f6bc..f1360f3 100644 --- a/src/template/src/app_error.hbs +++ b/src/template/src/app_error.hbs @@ -56,25 +56,4 @@ pub enum AppError { #[error("ValidationError:`{0}`")] ValidationError(#[from] validator::ValidationErrors), {{/if}} -} - -pub type AppResult = Result; - -#[async_trait] -impl Writer for AppError { - async fn write(mut self, _req: &mut Request, _depot: &mut Depot, res: &mut Response) { - {{#if is_web_site}} - res.stuff(StatusCode::INTERNAL_SERVER_ERROR, Json(self.to_string())); - {{else}} - res.render(Json(self.to_string())); - {{/if}} - } -} - -impl EndpointOutRegister for AppError { - fn register(_components: &mut salvo::oapi::Components, operation: &mut salvo::oapi::Operation) { - operation - .responses - .insert("500".to_string(), salvo::oapi::Response::new("error")); - } -} +} \ No newline at end of file diff --git a/src/template/src/app_response.hbs b/src/template/src/app_response.hbs index 8c72fa5..309f3f9 100644 --- a/src/template/src/app_response.hbs +++ b/src/template/src/app_response.hbs @@ -1,6 +1,48 @@ -use salvo::{prelude::StatusCode, writing::Json, Response}; +use salvo::{ + async_trait, + prelude::EndpointOutRegister, + writing::Json, + Depot, Request, Response, Writer, hyper::StatusCode, +}; use serde::Serialize; +use crate::app_error::AppError; + +pub struct AppResponse(pub AppResult); + +#[async_trait] +impl Writer for AppResponse { + async fn write(self, req: &mut Request, depot: &mut Depot, res: &mut Response) { + match self.0 { + Ok(data) => Res::with_data(data).into_response(res), + Err(e) => e.write(req, depot, res).await, + } + } +} + +impl EndpointOutRegister for AppResponse { + fn register(_components: &mut salvo::oapi::Components, operation: &mut salvo::oapi::Operation) { + operation + .responses + .insert("0".to_string(), salvo::oapi::Response::new("success")); + operation + .responses + .insert("500".to_string(), salvo::oapi::Response::new("error")); + } +} + +impl From> for AppResponse { + fn from(result: AppResult) -> Self { + AppResponse(result) + } +} + +impl From for AppResponse { + fn from(result: AppError) -> Self { + AppResponse(Err(result)) + } +} + #[derive(Debug, Serialize, Default)] pub struct Res { pub code: i32, @@ -17,7 +59,7 @@ pub struct ErrRes { impl Res { pub fn with_data(data: T) -> Self { Self { - code: 200, + code: 0, data, msg: "success".to_string(), } @@ -25,7 +67,7 @@ impl Res { #[allow(dead_code)] pub fn with_data_msg(data: T, msg: &str) -> Self { Self { - code: 200, + code: 0, data, msg: msg.to_string(), } @@ -51,3 +93,20 @@ impl ErrRes { res.stuff(StatusCode::INTERNAL_SERVER_ERROR, Json(self)); } } + +pub type AppResult = Result; + +#[async_trait] +impl Writer for AppError { + async fn write(mut self, _req: &mut Request, _depot: &mut Depot, res: &mut Response) { + ErrRes::with_err(&self.to_string()).into_response(res) + } +} + +impl EndpointOutRegister for AppError { + fn register(_components: &mut salvo::oapi::Components, operation: &mut salvo::oapi::Operation) { + operation + .responses + .insert("500".to_string(), salvo::oapi::Response::new("error")); + } +} diff --git a/src/template/src/dtos/user.hbs b/src/template/src/dtos/user.hbs index ddbcfd2..cbed8c7 100644 --- a/src/template/src/dtos/user.hbs +++ b/src/template/src/dtos/user.hbs @@ -1,8 +1,10 @@ use salvo::prelude::{ToSchema, Extractible}; use serde::{Deserialize, Serialize}; +use validator::Validate; -#[derive(Deserialize, Debug, ToSchema, Default)] +#[derive(Deserialize, Debug, Validate, ToSchema, Default)] pub struct UserAddRequest { + #[validate(length(min = 5, message = "username length must be greater than 5"))] pub username: String, pub password: String, } diff --git a/src/template/src/routers/demo.hbs b/src/template/src/routers/demo.hbs index dfdaf06..4cf774d 100644 --- a/src/template/src/routers/demo.hbs +++ b/src/template/src/routers/demo.hbs @@ -6,7 +6,7 @@ use salvo::{endpoint, writing::Text, Request, Response}; {{else}} use salvo::endpoint; {{/if}} -use crate::app_error::AppResult; +use crate::app_response::AppResult; {{#if is_web_site}} #[derive(Template)] diff --git a/src/template/src/routers/user.hbs b/src/template/src/routers/user.hbs index 5a54a7c..a9b6728 100644 --- a/src/template/src/routers/user.hbs +++ b/src/template/src/routers/user.hbs @@ -1,8 +1,9 @@ {{#if is_web_site}} use crate::{ - app_error::AppResult, - app_response::{ErrRes, Res}, - dtos::user::{UserAddRequest, UserLoginRequest, UserLoginResponse, UserUpdateRequest}, + app_response::{AppResponse, AppResult, ErrRes}, + dtos::user::{ + UserAddRequest, UserLoginRequest, UserLoginResponse, UserResponse, UserUpdateRequest, + }, middleware::jwt::decode_token, services::user, }; @@ -19,7 +20,7 @@ use salvo::{ #[template(path = "login.html")] struct LoginTemplate {} -#[endpoint( tags("comm"),)] +#[endpoint(tags("comm"))] pub async fn login_page(res: &mut Response) -> AppResult<()> { let cookies = res.cookies(); let cookie = cookies.get("jwt_token"); @@ -35,7 +36,31 @@ pub async fn login_page(res: &mut Response) -> AppResult<()> { res.render(Text::Html(hello_tmpl.render().unwrap())); Ok(()) } -#[endpoint( tags("comm"),)] + +#[derive(Template)] +#[template(path = "user_list_page.html")] +pub struct UserListPageTemplate {} + +#[derive(Template)] +#[template(path = "user_list.html")] +pub struct UserListTemplate {} + +#[endpoint] +pub async fn user_list_page(req: &mut Request, res: &mut Response) -> AppResult<()> { + let is_fragment = req.headers().get("X-Fragment-Header"); + match is_fragment { + Some(_) => { + let hello_tmpl = UserListTemplate {}; + res.render(Text::Html(hello_tmpl.render().unwrap())); + } + None => { + let hello_tmpl = UserListPageTemplate {}; + res.render(Text::Html(hello_tmpl.render().unwrap())); + } + } + Ok(()) +} +#[endpoint(tags("comm"))] pub async fn post_login(req: JsonBody, res: &mut Response) { let result: AppResult = user::login(req.0).await; match result { @@ -51,69 +76,34 @@ pub async fn post_login(req: JsonBody, res: &mut Response) { } } -#[endpoint( tags("users"))] -pub async fn post_add_user(req: JsonBody, res: &mut Response) { - let result = user::add_user(req.0).await; - match result { - Ok(data) => Res::with_data(data).into_response(res), - Err(e) => ErrRes::with_err(&e.to_string()).into_response(res), - } +#[endpoint(tags("users"))] +pub async fn post_add_user(new_user: JsonBody) -> AppResponse { + let result = user::add_user(new_user.0).await; + AppResponse(result) } #[endpoint( tags("users"), parameters( ("id", description = "user id"), ))] -pub async fn put_update_user(req: &mut Request, res: &mut Response) { - let req: UserUpdateRequest = req.extract().await.unwrap(); +pub async fn put_update_user(req: &mut Request) -> AppResult> { + let req: UserUpdateRequest = req.extract().await?; let result = user::update_user(req).await; - match result { - Ok(data) => Res::with_data(data).into_response(res), - Err(e) => ErrRes::with_err(&e.to_string()).into_response(res), - } + Ok(AppResponse(result)) } -#[endpoint( tags("users"),)] -pub async fn delete_user(id: PathParam, res: &mut Response) { +#[endpoint(tags("users"))] +pub async fn delete_user(id: PathParam) -> AppResponse<()> { let result = user::delete_user(id.0).await; - match result { - Ok(_) => Res::with_data(()).into_response(res), - Err(e) => ErrRes::with_err(&e.to_string()).into_response(res), - } + AppResponse(result) } -#[endpoint( tags("users"),)] -pub async fn get_users(res: &mut Response) { +#[endpoint(tags("users"))] +pub async fn get_users() -> AppResponse> { let result = user::users().await; - match result { - Ok(data) => Res::with_data(data).into_response(res), - Err(e) => ErrRes::with_err(&e.to_string()).into_response(res), - } + AppResponse(result) } -#[derive(Template)] -#[template(path = "user_list_page.html")] -pub struct UserListPageTemplate {} - -#[derive(Template)] -#[template(path = "user_list.html")] -pub struct UserListTemplate {} - -#[endpoint] -pub async fn user_list_page(req: &mut Request, res: &mut Response) -> AppResult<()> { - let is_fragment = req.headers().get("X-Fragment-Header"); - match is_fragment { - Some(_) => { - let hello_tmpl = UserListTemplate {}; - res.render(Text::Html(hello_tmpl.render().unwrap())); - } - None => { - let hello_tmpl = UserListPageTemplate {}; - res.render(Text::Html(hello_tmpl.render().unwrap())); - } - } - Ok(()) -} {{else}} use crate::{ app_error::AppResult, diff --git a/src/template/src/services/user.hbs b/src/template/src/services/user.hbs index e3a5b1e..a3a2cc1 100644 --- a/src/template/src/services/user.hbs +++ b/src/template/src/services/user.hbs @@ -436,14 +436,8 @@ pub async fn users() -> AppResult> { } {{/if}} {{#if is_mongodb}} -use std::str::FromStr; -use futures_util::StreamExt; -use mongodb::{ - bson::{doc, oid::ObjectId, Document}, - Collection, -}; use crate::{ - app_error::AppResult, + app_response::AppResult, db::{COLL_NAME, DB_NAME, MONGODB_CLIENT}, dtos::user::{ UserAddRequest, UserLoginRequest, UserLoginResponse, UserResponse, UserUpdateRequest, @@ -451,11 +445,19 @@ use crate::{ middleware::jwt::get_token, utils::rand_utils, }; +use futures_util::StreamExt; +use mongodb::{ + bson::{doc, oid::ObjectId, Document}, + Collection, +}; +use std::str::FromStr; +use validator::Validate; pub async fn add_user(req: UserAddRequest) -> AppResult { + req.validate()?; let db = MONGODB_CLIENT .get() - .ok_or(anyhow::anyhow!("{{database_connection_failed}}"))?; + .ok_or(anyhow::anyhow!("数据库连接失败"))?; let coll_users = db.database(DB_NAME).collection::(COLL_NAME); let user = doc! { @@ -466,7 +468,7 @@ pub async fn add_user(req: UserAddRequest) -> AppResult { let user = coll_users .find_one(user, None) .await? - .ok_or(anyhow::anyhow!("{{user_does_not_exist}}"))?; + .ok_or(anyhow::anyhow!("用户不存在"))?; Ok(UserResponse { id: user.get_object_id("_id")?.to_string(), username: user.get_str("username")?.to_string(),