hotel/src/routes/v1/user_add.rs

132 lines
No EOL
4.3 KiB
Rust

use actix_web::{HttpResponse, web};
use actix_web::post;
use actix_web::web::{Data, Json};
use log::error;
use serde::{Serialize, Deserialize};
use crate::config::CONFIG;
use crate::error::{APIError, APIErrorResponse};
use crate::models::{NewUser, User};
use crate::PgPool;
use diesel::prelude::*;
use crate::tokens::{Scope, token_has_scope};
#[derive(Serialize, Deserialize, Clone)]
pub struct UserAddRequest {
pub token: String,
pub name: String,
pub discord_id: i64,
pub password_hash: String
}
#[derive(Serialize, Deserialize, Clone)]
pub struct UserResponse {
pub id: i32,
pub name: String,
pub discord_id: i64,
pub password_hash: String
}
#[post("/v1/user/add")]
pub async fn add_user_request(pool: Data<PgPool>, req: Json<UserAddRequest>) -> HttpResponse {
use crate::schema::users;
if !token_has_scope(&req.token, &Scope::UserAdd) {
return HttpResponse::Unauthorized().json(APIErrorResponse {
errors: vec![
APIError {
code: "ERR_MISSING_SCOPE".to_string(),
message: "This endpoint requires the user:add scope".to_string(),
}
],
})
}
let req_clone = req.clone();
let pool_clone = pool.clone();
let results = match web::block(move || {
let mut conn = pool_clone.get().expect("Unable to get db pool");
users::table.filter(users::name.eq(&req_clone.name)).load::<User>(&mut conn)
}).await {
Ok(r) => r,
Err(e) => {
error!("Database error: {}", e);
return HttpResponse::InternalServerError().json(APIErrorResponse {
errors: vec![
APIError {
code: "ERR_BLOCKING_ERROR".to_string(),
message: "There was an error running the database request. Please try again later.".to_string()
}
]
})
}
};
let user_list = match results {
Ok(r) => r,
Err(e) => {
error!("Database error: {}", e);
return HttpResponse::InternalServerError().json(APIErrorResponse {
errors: vec![
APIError {
code: "ERR_DB_ERROR".to_string(),
message: "There was an error fetching the user. Please try again later.".to_string()
}
]
})
}
};
if !user_list.is_empty() {
return HttpResponse::Unauthorized().json(APIErrorResponse {
errors: vec![
APIError {
code: "ERR_USER_EXISTS".to_string(),
message: "Cannot create user that already exists".to_string()
}
]
})
}
let new_user = NewUser {
name: req.name.clone(),
discord_id: req.discord_id,
password_hash: req.password_hash.clone(),
};
let insert_result: QueryResult<User> = match web::block(move || {
let mut conn = pool.get().expect("Unable to get db pool");
diesel::insert_into(users::table).values(new_user).get_result(&mut conn)
}).await {
Ok(r) => r,
Err(e) => {
error!("Database error: {}", e);
return HttpResponse::InternalServerError().json(APIErrorResponse {
errors: vec![
APIError {
code: "ERR_BLOCKING_ERROR".to_string(),
message: "There was an error running the insert database request. Please try again later.".to_string()
}
]
})
}
};
let user = match insert_result {
Ok(r) => r,
Err(e) => {
error!("Database error: {}", e);
return HttpResponse::InternalServerError().json(APIErrorResponse {
errors: vec![
APIError {
code: "ERR_DB_ERROR".to_string(),
message: "There was an error creating the codereq. Please try again later.".to_string()
}
]
})
}
};
HttpResponse::Ok().json(UserResponse {
id: user.id,
name: user.name,
discord_id: user.discord_id,
password_hash: user.password_hash,
})
}