login.rs 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. use actix_web::{HttpResponse, web, post};
  2. use serde::{Serialize, Deserialize};
  3. use sqlx::PgPool;
  4. use jsonwebtoken::{encode, Header, EncodingKey};
  5. use std::time::{SystemTime, UNIX_EPOCH};
  6. use serde_json::json;
  7. use uuid::Uuid;
  8. use crate::{
  9. http_error::HttpError,
  10. models::user::User,
  11. logic::{compare_password, create_cookie},
  12. JWT_SECRET
  13. };
  14. #[derive(Deserialize)]
  15. struct Body {
  16. email: String,
  17. password: String
  18. }
  19. #[derive(Serialize)]
  20. struct Claims {
  21. id: Uuid,
  22. session_token: Uuid,
  23. exp: usize
  24. }
  25. #[post("/user/login")]
  26. pub async fn route(
  27. db: web::Data<PgPool>,
  28. web::Json(body): web::Json<Body>
  29. ) -> Result<HttpResponse, HttpError> {
  30. let user = User::find_one_by_email(&db, body.email).await?;
  31. compare_password(&body.password, &user.pass_hash)?;
  32. let jwt = create_jwt(user.id, user.session_token)?;
  33. let cookie = create_cookie("user".to_string(), jwt);
  34. Ok(HttpResponse::Ok().cookie(cookie).json(json!({"success": true})))
  35. }
  36. fn create_jwt(user_id: Uuid, user_token: Uuid) -> Result<String, HttpError> {
  37. let claims = Claims {
  38. id: user_id,
  39. session_token: user_token,
  40. exp: SystemTime::now()
  41. .duration_since(UNIX_EPOCH)
  42. .unwrap()
  43. .as_secs() as usize + (90 * 24 * 60 * 60)
  44. };
  45. let token = encode(
  46. &Header::default(),
  47. &claims,
  48. &EncodingKey::from_secret(JWT_SECRET.get().unwrap().as_bytes())
  49. )?;
  50. Ok(token)
  51. }