129 lines
No EOL
4.1 KiB
Rust
129 lines
No EOL
4.1 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::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 UserGetRequest {
|
|
pub token: String,
|
|
pub name: Option<String>,
|
|
pub discord_id: Option<i64>,
|
|
pub id: Option<i32>
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct UserResponse {
|
|
pub id: i32,
|
|
pub name: String,
|
|
pub discord_id: i64,
|
|
pub password_hash: String
|
|
}
|
|
|
|
#[post("/v1/user/get")]
|
|
pub async fn get_user_request(pool: Data<PgPool>, req: Json<UserGetRequest>) -> HttpResponse {
|
|
use crate::schema::users;
|
|
|
|
if !token_has_scope(&req.token, &Scope::UserRead) {
|
|
return HttpResponse::Unauthorized().json(APIErrorResponse {
|
|
errors: vec![
|
|
APIError {
|
|
code: "ERR_MISSING_SCOPE".to_string(),
|
|
message: "This endpoint requires the user:read scope".to_string(),
|
|
}
|
|
],
|
|
})
|
|
}
|
|
|
|
let mut amt = 0;
|
|
if req.id.is_some() { amt += 1; }
|
|
if req.name.is_some() { amt += 1; }
|
|
if req.discord_id.is_some() { amt += 1; }
|
|
|
|
if amt == 0 {
|
|
return HttpResponse::BadRequest().json(APIErrorResponse {
|
|
errors: vec![
|
|
APIError {
|
|
code: "ERR_NOT_SPECIFIC_ENOUGH".to_string(),
|
|
message: "One filter must be provided".to_string(),
|
|
}
|
|
],
|
|
})
|
|
} else if amt != 1 {
|
|
return HttpResponse::BadRequest().json(APIErrorResponse {
|
|
errors: vec![
|
|
APIError {
|
|
code: "ERR_TOO_SPECIFIC".to_string(),
|
|
message: "Only one filter may be provided".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");
|
|
|
|
if let Some(id) = req_clone.id {
|
|
users::table.filter(users::id.eq(id)).load::<User>(&mut conn)
|
|
} else if let Some(name) = req_clone.name {
|
|
users::table.filter(users::name.eq(name)).load::<User>(&mut conn)
|
|
} else if let Some(discord_id) = req_clone.discord_id {
|
|
users::table.filter(users::discord_id.eq(discord_id)).load::<User>(&mut conn)
|
|
} else {
|
|
unreachable!()
|
|
}
|
|
}).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_DOES_NOT_EXIST".to_string(),
|
|
message: "Unable to find a user by that search query".to_string()
|
|
}
|
|
]
|
|
})
|
|
}
|
|
let user = &user_list[0];
|
|
|
|
HttpResponse::Ok().json(UserResponse {
|
|
id: user.id,
|
|
name: user.name.clone(),
|
|
discord_id: user.discord_id,
|
|
password_hash: user.password_hash.clone(),
|
|
})
|
|
} |