//! Provides function wrappers around the `auth` module which are ready to be used as endpoints in actix web. use actix_session::{self, Session}; use actix_web::{HttpRequest, HttpResponse, Responder}; use argon2::password_hash::rand_core::impls; use sqlx::prelude::FromRow; use sqlx::{self, Postgres}; use crate::auth::{self, validate_session, SessionValidated}; /// Used as the structure for when `Session` information needs to be taken as a JSON input. #[derive(Debug, FromRow, serde::Deserialize)] pub struct JsonSession { user_name: String, session_token: String, time_to_die: String, } /// Wrapper for `validate_user`. Returns `202` if validated successfully and `401` if the user provided is not valid. pub async fn validate_user_wrapper( json_creds: actix_web::web::Json, pool: actix_web::web::Data>, ) -> impl Responder { let creds = auth::Credentials { password: json_creds.password.to_string(), user_name: json_creds.user_name.to_string(), realm: json_creds.realm.to_string(), }; match auth::validate_user(&creds, pool.get_ref()).await { auth::UserValidatedReturn::Validated() => HttpResponse::with_body( actix_web::http::StatusCode::ACCEPTED, format!("Right pass for {}", json_creds.user_name), ), auth::UserValidatedReturn::NotValidated() => HttpResponse::with_body( actix_web::http::StatusCode::UNAUTHORIZED, format!("Not Authorized"), ), } } /// Wrapper for `add_user`. Returns `202` if validated successfully and `401` if the user provided is not able to be created or there is some error. pub async fn add_user_wrapper( json_creds: actix_web::web::Json, pool: actix_web::web::Data>, ) -> impl Responder { let creds = auth::Credentials { password: json_creds.password.to_string(), user_name: json_creds.user_name.to_string(), realm: json_creds.realm.to_string(), }; match auth::add_user(&creds, pool.get_ref()).await { auth::AddUserReturn::Good() => HttpResponse::with_body( actix_web::http::StatusCode::ACCEPTED, format!("User Created {}", json_creds.user_name), ), auth::AddUserReturn::UserNotUnique() => HttpResponse::with_body( actix_web::http::StatusCode::UNAUTHORIZED, format!("User Name is already Taken"), ), auth::AddUserReturn::InsertError(err) => HttpResponse::with_body( actix_web::http::StatusCode::UNAUTHORIZED, format!("Server Error: {:?}", err), ), _ => HttpResponse::with_body( actix_web::http::StatusCode::UNAUTHORIZED, format!("Server Error"), ), } } /// Wrapper for `generate_session`. Returns `202` if validated successfully and the session was generated, it will return a json representation of the generateed session. In the form /// ```json /// { /// "user_name": "odespo", /// "session_token": "QSoRairtJbO7XjvqwidsfkkXcYBSWEWKc0xhqf9m9wsTVvgpHowc9keItq9R5VkY1jq2RYH4mGXHEQL2O1kiBIjMq2VbzRhAouk4", /// "time_to_die": "2024-07-23T03:05:57.141340172+00:00" /// } /// ``` /// /// If it fails you will get a `401` and no body content. pub async fn generate_session_wrapper( json_creds: actix_web::web::Json, pool: actix_web::web::Data>, ) -> impl Responder { let creds = auth::Credentials { password: json_creds.password.to_string(), user_name: json_creds.user_name.to_string(), realm: json_creds.realm.to_string(), }; match auth::generate_session(&creds, pool.get_ref(), auth::SESSION_VALID_FOR_SECONDS).await { Ok(session) => actix_web::HttpResponse::Accepted().json(session), Err(_) => actix_web::HttpResponse::Unauthorized().body(""), } } /// Wrapper for `validate_session_wrapper`. Returns `202` if validated successfully and the session is correct in the DB, it will return a json representation of the validated session. In the form /// ```json /// { /// "user_name": "odespo", /// "session_token": "QSoRairtJbO7XjvqwidsfkkXcYBSWEWKc0xhqf9m9wsTVvgpHowc9keItq9R5VkY1jq2RYH4mGXHEQL2O1kiBIjMq2VbzRhAouk4", /// "time_to_die": "2024-07-23T03:05:57.141340172+00:00" /// } /// ``` /// /// If it fails you will get a `401` with the body content `"Failed to parse time"`. pub async fn validate_session_wrapper( json_session: actix_web::web::Json, pool: actix_web::web::Data>, ) -> impl Responder { let time = match chrono::DateTime::parse_from_rfc3339(&json_session.time_to_die) { Ok(time) => time, Err(_) => { return actix_web::HttpResponse::InternalServerError().body("Failed to parse time") } }; let session = auth::Session { user_name: json_session.user_name.to_string(), session_token: json_session.session_token.to_string(), time_to_die: time.into(), }; match auth::validate_session(&session, &pool).await { auth::SessionValidated::ValidSession() => actix_web::HttpResponse::Accepted().json(session), auth::SessionValidated::InvalidSession() => { actix_web::HttpResponse::Unauthorized().body("") } } } /// Wrapper for `delete_user` /// /// pub async fn delete_user_wrapper( json_creds: actix_web::web::Json, pool: actix_web::web::Data>, ) -> impl Responder { let creds = auth::Credentials { password: json_creds.password.to_string(), user_name: json_creds.user_name.to_string(), realm: json_creds.realm.to_string(), }; match auth::delete_user(&creds, pool.get_ref()).await { auth::DeleteUserReturn::Good() => HttpResponse::with_body( actix_web::http::StatusCode::ACCEPTED, format!("Deleted User")), auth::DeleteUserReturn::BadUserOrPassword() => HttpResponse::with_body( actix_web::http::StatusCode::UNAUTHORIZED, format!("User name or password dose not exist or is incorrect")), auth::DeleteUserReturn::FailedToDeleteSessions(_) => HttpResponse::with_body( actix_web::http::StatusCode::INTERNAL_SERVER_ERROR, format!("Valid username and password but unable to delete existing sessions")), auth::DeleteUserReturn::DataBaseError(_) => HttpResponse::with_body( actix_web::http::StatusCode::INTERNAL_SERVER_ERROR, format!("Database issue")) } }