From 6be9ce5c1d53639c6cfcc71fa5d6c252cb1a1390 Mon Sep 17 00:00:00 2001 From: Quentin Boyer Date: Sat, 20 May 2023 11:40:50 +0200 Subject: [PATCH] Implement route for logging in --- src/routes/mod.rs | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/routes/mod.rs b/src/routes/mod.rs index e14056f..815a1d6 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -8,12 +8,21 @@ use axum::{ routing::post, Json, Router, }; +use jwt_simple::prelude::*; +use sea_orm::prelude::*; +use sha2::{Digest, Sha512}; use tower_http::cors::{self, AllowOrigin, CorsLayer}; +use crate::entity::{prelude::*, user}; + #[derive(thiserror::Error, Debug)] enum RouteError { #[error("This account does not exist")] UnknownAccount, + #[error("Database encountered an error")] + Db(#[from] DbErr), + #[error("JWT error encountered")] + Jwt(#[from] jwt_simple::Error), } impl IntoResponse for RouteError { @@ -22,6 +31,10 @@ impl IntoResponse for RouteError { RouteError::UnknownAccount => { (StatusCode::NOT_FOUND, "Account not found").into_response() } + e => { + tracing::error!("Internal error: {e:?}"); + StatusCode::INTERNAL_SERVER_ERROR.into_response() + } } } } @@ -31,10 +44,31 @@ type JsonResult = Result, E>; type AppState = Arc; async fn login( - State(_state): State, - Json(_req): Json, + State(state): State, + Json(req): Json, ) -> JsonResult { - Err(RouteError::UnknownAccount) + let Some(user) = User::find() + .filter(user::Column::Name.eq(&req.username)) + .one(&state.db) + .await? else { + return Err(RouteError::UnknownAccount) + }; + + let mut hasher = Sha512::new(); + hasher.update(user.id.as_bytes()); + hasher.update(req.password.as_bytes()); + let hash = hasher.finalize(); + + if hash[..] != user.password { + return Err(RouteError::UnknownAccount); + } + + let mut claims = Claims::create(Duration::from_secs(3600 * 24 * 31 * 6)); + claims.subject = Some(user.id.to_string()); + + let token = state.jwt_secret.0.authenticate(claims)?; + + Ok(Json(LoginResponse { token })) } pub(crate) fn router(api_allowed: Option) -> Router {