use actix_web::{HttpResponse, web, post}; use serde::{Serialize, Deserialize}; use sqlx::PgPool; use jsonwebtoken::{encode, Header, EncodingKey}; use std::time::{SystemTime, UNIX_EPOCH}; use serde_json::json; use uuid::Uuid; use crate::{ http_error::HttpError, models::user::User, logic::{compare_password, create_cookie}, JWT_SECRET }; #[derive(Deserialize)] struct Body { email: String, password: String } #[derive(Serialize)] struct Claims { id: Uuid, session_token: Uuid, exp: usize } #[post("/user/login")] pub async fn route( db: web::Data, web::Json(body): web::Json ) -> Result { let user = User::find_one_by_email(&db, body.email).await?; compare_password(&body.password, &user.pass_hash)?; let jwt = create_jwt(user.id, user.session_token)?; let cookie = create_cookie("user".to_string(), jwt); Ok(HttpResponse::Ok().cookie(cookie).json(json!({"success": true}))) } fn create_jwt(user_id: Uuid, user_token: Uuid) -> Result { let claims = Claims { id: user_id, session_token: user_token, exp: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs() as usize + (90 * 24 * 60 * 60) }; let token = encode( &Header::default(), &claims, &EncodingKey::from_secret(JWT_SECRET.get().unwrap().as_bytes()) )?; Ok(token) }