use axum::{Router, routing::post, response::Response}; use serde::Deserialize; use time::{OffsetDateTime, Duration}; use tower_cookies::{Cookies, Cookie}; use crate::types::{user::User, response::ResponseCode, session::Session, extract::{Json, AuthorizedUser, Check, CheckResult}}; #[derive(Deserialize)] struct RegistrationRequet { firstname: String, lastname: String, email: String, password: String, gender: String, day: u8, month: u8, year: u32 } impl Check for RegistrationRequet { fn check(&self) -> CheckResult { Self::assert_length(&self.firstname, 1, 20, "First name can only by 1-20 characters long")?; Self::assert_length(&self.lastname, 1, 20, "Last name can only by 1-20 characters long")?; Self::assert_length(&self.email, 1, 50, "Email can only by 1-50 characters long")?; Self::assert_length(&self.password, 1, 50, "Password can only by 1-50 characters long")?; Self::assert_length(&self.gender, 1, 100, "Gender can only by 1-100 characters long")?; Self::assert_range(self.day as u64, 1, 255, "Birthday day can only be between 1-255")?; Self::assert_range(self.month as u64, 1, 255, "Birthday month can only be between 1-255")?; Self::assert_range(self.year as u64, 1, 2147483647, "Birthday year can only be between 1-2147483647")?; Ok(()) } } async fn register(cookies: Cookies, Json(body): Json) -> Response { let user = match User::new(body.firstname, body.lastname, body.email, body.password, body.gender, body.day, body.month, body.year) { Ok(user) => user, Err(err) => return err }; let session = match Session::new(user.user_id) { Ok(session) => session, Err(err) => return err }; let mut now = OffsetDateTime::now_utc(); now += Duration::weeks(52); let mut cookie = Cookie::new("auth", session.token); cookie.set_secure(false); cookie.set_http_only(false); cookie.set_expires(now); cookie.set_path("/"); cookies.add(cookie); ResponseCode::Created.msg("Successfully created new user") } #[derive(Deserialize)] struct LoginRequest { email: String, password: String, } impl Check for LoginRequest { fn check(&self) -> CheckResult { Ok(()) } } async fn login(cookies: Cookies, Json(body): Json) -> Response { let Ok(user) = User::from_email(&body.email) else { return ResponseCode::BadRequest.msg("Email is not registered") }; if user.password != body.password { return ResponseCode::BadRequest.msg("Password is not correct") } let session = match Session::new(user.user_id) { Ok(session) => session, Err(err) => return err }; let mut now = OffsetDateTime::now_utc(); now += Duration::weeks(52); let mut cookie = Cookie::new("auth", session.token); cookie.set_secure(false); cookie.set_http_only(false); cookie.set_expires(now); cookie.set_path("/"); cookies.add(cookie); ResponseCode::Success.msg("Successfully logged in") } async fn logout(cookies: Cookies, AuthorizedUser(user): AuthorizedUser) -> Response { cookies.remove(Cookie::new("auth", "")); if let Err(err) = Session::delete(user.user_id) { return err } ResponseCode::Success.msg("Successfully logged out") } pub fn router() -> Router { Router::new() .route("/register", post(register)) .route("/login", post(login)) .route("/logout", post(logout)) }