You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
2.6 KiB

  1. use actix_web::web;
  2. use actix_web_httpauth::extractors::basic::BasicAuth;
  3. use crate::errors::DomainError;
  4. use crate::{actions::users, AppData};
  5. use actix_identity::Identity;
  6. use actix_web::{get, Error, HttpResponse};
  7. #[get("/login")]
  8. pub async fn login(
  9. id: Identity,
  10. credentials: BasicAuth,
  11. app_data: web::Data<AppData>,
  12. ) -> Result<HttpResponse, DomainError> {
  13. let maybe_identity = id.identity();
  14. let response = if let Some(identity) = maybe_identity {
  15. Ok(HttpResponse::Found()
  16. .header("location", "/")
  17. .content_type("text/plain")
  18. .json(format!("Already logged in as {}", identity)))
  19. } else {
  20. let credentials2 = credentials.clone();
  21. let valid =
  22. web::block(move || validate_basic_auth(credentials2, &app_data))
  23. .await
  24. .map_err(|_err| {
  25. DomainError::new_thread_pool_error(_err.to_string())
  26. })?;
  27. if valid {
  28. id.remember(credentials.user_id().to_string());
  29. Ok(HttpResponse::Found().header("location", "/").finish())
  30. } else {
  31. Err(DomainError::new_auth_error(
  32. "Wrong password or account does not exist".to_owned(),
  33. ))
  34. }
  35. };
  36. response
  37. }
  38. //TODO: fix the response
  39. #[get("/logout")]
  40. pub async fn logout(
  41. id: Identity,
  42. _credentials: BasicAuth,
  43. ) -> Result<HttpResponse, Error> {
  44. let maybe_identity = id.identity();
  45. let response = if let Some(identity) = maybe_identity {
  46. let _ = tracing::info!("Logging out {user}", user = identity);
  47. id.forget();
  48. HttpResponse::Found().header("location", "/").finish()
  49. } else {
  50. HttpResponse::Found()
  51. .header("location", "/")
  52. .content_type("text/plain")
  53. .json("Not logged in")
  54. };
  55. Ok(response)
  56. }
  57. #[get("/")]
  58. pub async fn index(id: Identity) -> String {
  59. format!(
  60. "Hello {}",
  61. id.identity().unwrap_or_else(|| "Anonymous".to_owned())
  62. )
  63. }
  64. /// basic auth middleware function
  65. pub fn validate_basic_auth(
  66. credentials: BasicAuth,
  67. app_data: &AppData,
  68. ) -> Result<bool, DomainError> {
  69. let result = if let Some(password_ref) = credentials.password() {
  70. let pool = &app_data.pool;
  71. let conn = pool.get()?;
  72. let password = password_ref.clone().into_owned();
  73. let valid = users::verify_password(
  74. &credentials.user_id().clone().into_owned(),
  75. &password,
  76. &conn,
  77. )?;
  78. Ok(valid)
  79. } else {
  80. Err(DomainError::new_password_error(
  81. "No password given".to_owned(),
  82. ))
  83. };
  84. result
  85. }