diff options
Diffstat (limited to 'src/api/ops.rs')
| -rw-r--r-- | src/api/ops.rs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/api/ops.rs b/src/api/ops.rs new file mode 100644 index 0000000..9bebc2d --- /dev/null +++ b/src/api/ops.rs @@ -0,0 +1,59 @@ +use actix_web::{http::StatusCode, post, web, HttpResponse, ResponseError, Scope}; +use raise::yeet; +use serde::Deserialize; +use sqlx::MySqlPool; +use thiserror::Error; + +use crate::services::db; + +#[derive(Debug, Clone, Deserialize)] +struct LoginRequest { + username: Box<str>, + password: Box<str>, +} + +#[derive(Debug, Clone, Error)] +enum LoginFailure { + #[error("No user found with the given username")] + UserNotFound { username: Box<str> }, + #[error("The given password is incorrect")] + IncorrectPassword { username: Box<str> }, +} + +impl ResponseError for LoginFailure { + fn status_code(&self) -> actix_web::http::StatusCode { + match self { + Self::UserNotFound { .. } => StatusCode::NOT_FOUND, + Self::IncorrectPassword { .. } => StatusCode::UNAUTHORIZED, + } + } +} + +#[post("/login")] +async fn login( + body: web::Json<LoginRequest>, + conn: web::Data<MySqlPool>, +) -> Result<HttpResponse, LoginFailure> { + let conn = conn.get_ref(); + + let user = db::get_user_by_username(conn, &body.username) + .await + .unwrap(); + let Some(user) = user else { + yeet!(LoginFailure::UserNotFound{ username: body.username.clone() }); + }; + + let good_password = user.check_password(&body.password).unwrap(); + let response = if good_password { + HttpResponse::Ok().finish() + } else { + yeet!(LoginFailure::IncorrectPassword { + username: body.username.clone() + }); + }; + Ok(response) +} + +pub fn service() -> Scope { + web::scope("").service(login) +} |
