use actix_web::{get, post, web, HttpResponse, ResponseError}; use actix_web_httpauth::middleware::HttpAuthentication; use siren::ServiceError; use crate::auth::{LoginRequest, RegisterUser, InsertUser, QueryUser, verify_password, create_token, LoginResponse}; use super::validator; #[post("/register")] async fn register(user: web::Json) -> HttpResponse { let register_user = user.0; let insert_user: InsertUser = match register_user.convert_to_insert() { Ok(user) => user, Err(err) => return ResponseError::error_response(&err) }; match InsertUser::insert(insert_user) { Ok(_) => { HttpResponse::Created().finish() }, Err(err) => { // Obfuscate the service error message to prevent leaking database details if err.status == 409 { return HttpResponse::Conflict().finish(); } else { return ResponseError::error_response(&err); } } } } #[post("/login")] async fn login(request: web::Json) -> HttpResponse { let email = request.email.clone(); let query_user = match QueryUser::get_by_email(&email) { Ok(query_user) => query_user, Err(err) => return ResponseError::error_response(&err) }; let hash = query_user.hash; let password = request.password.as_bytes(); match verify_password(&hash, password) { Ok(_) => { let token = create_token(&email); HttpResponse::Ok().json(LoginResponse { token }) }, Err(err) => ResponseError::error_response(&ServiceError { status: 401, message: err.to_string() }) } } #[post("/logout")] async fn logout() -> HttpResponse { HttpResponse::Ok().finish() } #[get("/ping")] async fn ping() -> HttpResponse { HttpResponse::Ok().finish() } pub fn init_routes(config: &mut web::ServiceConfig) { let auth = HttpAuthentication::bearer(validator); config.service(web::scope("auth") .service(register) .service(login) .service(web::scope("") .wrap(auth) .service(logout) .service(ping) )); }