Skip to content

Commit

Permalink
Improved Mongo DB templates
Browse files Browse the repository at this point in the history
  • Loading branch information
fankaiLiu committed Nov 23, 2023
1 parent 998ed5a commit edeaec7
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 89 deletions.
23 changes: 1 addition & 22 deletions src/template/src/app_error.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,4 @@ pub enum AppError {
#[error("ValidationError:`{0}`")]
ValidationError(#[from] validator::ValidationErrors),
{{/if}}
}

pub type AppResult<T> = Result<T, AppError>;

#[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"));
}
}
}
65 changes: 62 additions & 3 deletions src/template/src/app_response.hbs
Original file line number Diff line number Diff line change
@@ -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<T>(pub AppResult<T>);

#[async_trait]
impl<T: Serialize + Default + Send> Writer for AppResponse<T> {
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<T: Serialize + Default + Send> EndpointOutRegister for AppResponse<T> {
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<T> From<AppResult<T>> for AppResponse<T> {
fn from(result: AppResult<T>) -> Self {
AppResponse(result)
}
}

impl<T> From<AppError> for AppResponse<T> {
fn from(result: AppError) -> Self {
AppResponse(Err(result))
}
}

#[derive(Debug, Serialize, Default)]
pub struct Res<T> {
pub code: i32,
Expand All @@ -17,15 +59,15 @@ pub struct ErrRes {
impl<T: Serialize + Send + Default> Res<T> {
pub fn with_data(data: T) -> Self {
Self {
code: 200,
code: 0,
data,
msg: "success".to_string(),
}
}
#[allow(dead_code)]
pub fn with_data_msg(data: T, msg: &str) -> Self {
Self {
code: 200,
code: 0,
data,
msg: msg.to_string(),
}
Expand All @@ -51,3 +93,20 @@ impl ErrRes {
res.stuff(StatusCode::INTERNAL_SERVER_ERROR, Json(self));
}
}

pub type AppResult<T> = Result<T, AppError>;

#[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"));
}
}
4 changes: 3 additions & 1 deletion src/template/src/dtos/user.hbs
Original file line number Diff line number Diff line change
@@ -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,
}
Expand Down
2 changes: 1 addition & 1 deletion src/template/src/routers/demo.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
96 changes: 43 additions & 53 deletions src/template/src/routers/user.hbs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand All @@ -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");
Expand All @@ -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<UserLoginRequest>, res: &mut Response) {
let result: AppResult<UserLoginResponse> = user::login(req.0).await;
match result {
Expand All @@ -51,69 +76,34 @@ pub async fn post_login(req: JsonBody<UserLoginRequest>, res: &mut Response) {
}
}

#[endpoint( tags("users"))]
pub async fn post_add_user(req: JsonBody<UserAddRequest>, 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<UserAddRequest>) -> AppResponse<UserResponse> {
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<AppResponse<UserResponse>> {
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<String>, res: &mut Response) {
#[endpoint(tags("users"))]
pub async fn delete_user(id: PathParam<String>) -> 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<Vec<UserResponse>> {
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,
Expand Down
20 changes: 11 additions & 9 deletions src/template/src/services/user.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -436,26 +436,28 @@ pub async fn users() -> AppResult<Vec<UserResponse>> {
}
{{/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,
},
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<UserResponse> {
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::<Document>(COLL_NAME);

let user = doc! {
Expand All @@ -466,7 +468,7 @@ pub async fn add_user(req: UserAddRequest) -> AppResult<UserResponse> {
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(),
Expand Down

0 comments on commit edeaec7

Please sign in to comment.