mini_rust_auth/
wrappers.rs

1//! Provides function wrappers around the `auth` module which are ready to be used as endpoints in actix web.
2use actix_session::{self, Session};
3use actix_web::{HttpRequest, HttpResponse, Responder};
4use argon2::password_hash::rand_core::impls;
5use sqlx::prelude::FromRow;
6use sqlx::{self, Postgres};
7
8use crate::auth::{self, validate_session, SessionValidated};
9
10/// Used as the structure for when `Session` information needs to be taken as a JSON input.
11#[derive(Debug, FromRow, serde::Deserialize)]
12pub struct JsonSession {
13    user_name: String,
14    session_token: String,
15    time_to_die: String,
16}
17
18/// Wrapper for `validate_user`. Returns `202` if validated successfully and `401` if the user provided is not valid.
19pub async fn validate_user_wrapper(
20    json_creds: actix_web::web::Json<auth::Credentials>,
21    pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
22) -> impl Responder {
23    let creds = auth::Credentials {
24        password: json_creds.password.to_string(),
25        user_name: json_creds.user_name.to_string(),
26        realm: json_creds.realm.to_string(),
27    };
28
29    match auth::validate_user(&creds, pool.get_ref()).await {
30        auth::UserValidatedReturn::Validated() => HttpResponse::with_body(
31            actix_web::http::StatusCode::ACCEPTED,
32            format!("Right pass for {}", json_creds.user_name),
33        ),
34        auth::UserValidatedReturn::NotValidated() => HttpResponse::with_body(
35            actix_web::http::StatusCode::UNAUTHORIZED,
36            format!("Not Authorized"),
37        ),
38    }
39}
40
41/// 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.
42pub async fn add_user_wrapper(
43    json_creds: actix_web::web::Json<auth::Credentials>,
44    pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
45) -> impl Responder {
46    let creds = auth::Credentials {
47        password: json_creds.password.to_string(),
48        user_name: json_creds.user_name.to_string(),
49        realm: json_creds.realm.to_string(),
50    };
51
52    match auth::add_user(&creds, pool.get_ref()).await {
53        auth::AddUserReturn::Good() => HttpResponse::with_body(
54            actix_web::http::StatusCode::ACCEPTED,
55            format!("User Created {}", json_creds.user_name),
56        ),
57        auth::AddUserReturn::UserNotUnique() => HttpResponse::with_body(
58            actix_web::http::StatusCode::UNAUTHORIZED,
59            format!("User Name is already Taken"),
60        ),
61        auth::AddUserReturn::InsertError(err) => HttpResponse::with_body(
62            actix_web::http::StatusCode::UNAUTHORIZED,
63            format!("Server Error: {:?}", err),
64        ),
65        _ => HttpResponse::with_body(
66            actix_web::http::StatusCode::UNAUTHORIZED,
67            format!("Server Error"),
68        ),
69    }
70}
71
72/// 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
73/// ```json
74/// {
75///  "user_name": "odespo",
76///  "session_token": "QSoRairtJbO7XjvqwidsfkkXcYBSWEWKc0xhqf9m9wsTVvgpHowc9keItq9R5VkY1jq2RYH4mGXHEQL2O1kiBIjMq2VbzRhAouk4",
77///  "time_to_die": "2024-07-23T03:05:57.141340172+00:00"
78/// }
79/// ```
80///
81/// If it fails you will get a `401` and no body content.
82pub async fn generate_session_wrapper(
83    json_creds: actix_web::web::Json<auth::Credentials>,
84    pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
85) -> impl Responder {
86    let creds = auth::Credentials {
87        password: json_creds.password.to_string(),
88        user_name: json_creds.user_name.to_string(),
89        realm: json_creds.realm.to_string(),
90    };
91
92    match auth::generate_session(&creds, pool.get_ref(), auth::SESSION_VALID_FOR_SECONDS).await {
93        Ok(session) => actix_web::HttpResponse::Accepted().json(session),
94        Err(_) => actix_web::HttpResponse::Unauthorized().body(""),
95    }
96}
97
98/// 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
99/// ```json
100/// {
101///  "user_name": "odespo",
102///  "session_token": "QSoRairtJbO7XjvqwidsfkkXcYBSWEWKc0xhqf9m9wsTVvgpHowc9keItq9R5VkY1jq2RYH4mGXHEQL2O1kiBIjMq2VbzRhAouk4",
103///  "time_to_die": "2024-07-23T03:05:57.141340172+00:00"
104/// }
105/// ```
106///
107/// If it fails you will get a `401` with the body content `"Failed to parse time"`.
108pub async fn validate_session_wrapper(
109    json_session: actix_web::web::Json<JsonSession>,
110    pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
111) -> impl Responder {
112    let time = match chrono::DateTime::parse_from_rfc3339(&json_session.time_to_die) {
113        Ok(time) => time,
114        Err(_) => {
115            return actix_web::HttpResponse::InternalServerError().body("Failed to parse time")
116        }
117    };
118
119    let session = auth::Session {
120        user_name: json_session.user_name.to_string(),
121        session_token: json_session.session_token.to_string(),
122        time_to_die: time.into(),
123    };
124
125    match auth::validate_session(&session, &pool).await {
126        auth::SessionValidated::ValidSession() => actix_web::HttpResponse::Accepted().json(session),
127        auth::SessionValidated::InvalidSession() => {
128            actix_web::HttpResponse::Unauthorized().body("")
129        }
130    }
131}
132
133/// Wrapper for `delete_user`
134/// 
135/// 
136pub async fn delete_user_wrapper(
137    json_creds: actix_web::web::Json<auth::Credentials>,
138    pool: actix_web::web::Data<sqlx::Pool<Postgres>>,
139) -> impl Responder {
140    let creds = auth::Credentials {
141        password: json_creds.password.to_string(),
142        user_name: json_creds.user_name.to_string(),
143        realm: json_creds.realm.to_string(),
144    };
145
146    match auth::delete_user(&creds, pool.get_ref()).await {
147        auth::DeleteUserReturn::Good() => HttpResponse::with_body(
148            actix_web::http::StatusCode::ACCEPTED,
149            format!("Deleted User")),
150        auth::DeleteUserReturn::BadUserOrPassword() => HttpResponse::with_body(
151            actix_web::http::StatusCode::UNAUTHORIZED,
152            format!("User name or password dose not exist or is incorrect")),
153        auth::DeleteUserReturn::FailedToDeleteSessions(_) => HttpResponse::with_body(
154            actix_web::http::StatusCode::INTERNAL_SERVER_ERROR,
155            format!("Valid username and password but unable to delete existing sessions")),
156        auth::DeleteUserReturn::DataBaseError(_) => HttpResponse::with_body(
157            actix_web::http::StatusCode::INTERNAL_SERVER_ERROR,
158            format!("Database issue"))
159    }
160}
161