Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
admin_auth.rs 3.95 KiB
use crate::{middleware::AuthenticatedAdminMiddleware, model::AdminAuthCredentials, AppState};
use actix_web::{
    post,
    web::{Data, Form},
    HttpMessage, HttpRequest, HttpResponse, Responder,
};

/// Performs administrator authentication from form data
/// If the authentication succeed, a cookie with an auth token is returned
/// If not, 401 is returned and if an auth cookie is found it is deleted.
#[post("/admin-auth")]
pub async fn admin_authentication<'a>(
    app_state: Data<AppState>,
    auth_mw: Data<AuthenticatedAdminMiddleware<'a>>,
    req: HttpRequest,
    form_data: Form<AdminAuthCredentials>,
) -> impl Responder {
    let cookie_opt = auth_mw.exec(&app_state, &req, Some(form_data)).await;
    match cookie_opt {
        Ok(cookie) => HttpResponse::Accepted().cookie(cookie).finish(),
        Err(_) => {
            return match req.cookie(auth_mw.cookie_name) {
                Some(c) => {
                    // Invalidate auth_cookie if auth failed in any way
                    HttpResponse::Unauthorized().del_cookie(&c).finish()
                }
                None => HttpResponse::Unauthorized().finish(),
            };
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@@
 *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@@
 *  _______   ______    ______   _______   *@@
 * |__   __@ |  ____@  /  ____@ |__   __@  *@@
 *    |  @   |  @__    \_ @_       |  @    *@@
 *    |  @   |   __@     \  @_     |  @    *@@
 *    |  @   |  @___   ____\  @    |  @    *@@
 *    |__@   |______@  \______@    |__@    *@@
 *                                         *@@
 *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@@
 *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@*/

#[cfg(test)]
mod test_admin_auth {
    use super::*;
    use crate::model::Administrator;
    use actix_web::{
        http::{Method, StatusCode},
        test,
        web::Data,
        App,
    };
    use futures::stream::StreamExt;
    use wither::prelude::Model;

    #[tokio::test]
    async fn test_admin_auth() {
        dotenv::dotenv().ok();

        let app_state = AppState::for_test().await;
        let admin_user = Administrator::find(&app_state.db, None, None)
            .await
            .unwrap()
            .next()
            .await
            .unwrap()
            .unwrap(); // Get the first admin user we find. At least one should exist.
        let password = app_state.encryption.decrypt(&admin_user.password_hash);
        let username = admin_user.username.to_owned();

        let mut app = test::init_service(
            App::new()
                .app_data(Data::new(app_state.clone()))
                .app_data(Data::new(AuthenticatedAdminMiddleware::new(
                    "kuadrado-admin-auth",
                )))
                .service(admin_authentication),
        )
        .await;

        let req = test::TestRequest::with_uri("/admin-auth")
            .method(Method::POST)
            .set_form(&AdminAuthCredentials { username, password })
            .to_request();

        let resp = test::call_service(&mut app, req).await;

        assert_eq!(resp.status(), StatusCode::ACCEPTED);
    }

    #[tokio::test]
    async fn test_admin_auth_unauthorized() {
        dotenv::dotenv().ok();

        let app_state = AppState::for_test().await;

        let mut app = test::init_service(
            App::new()
                .app_data(Data::new(app_state.clone()))
                .app_data(Data::new(AuthenticatedAdminMiddleware::new(
                    "kuadrado-admin-auth",
                )))
                .service(admin_authentication),
        )
        .await;

        let req = test::TestRequest::with_uri("/admin-auth")
            .method(Method::POST)
            .set_form(&AdminAuthCredentials {
                username: String::from("whatever"),
                password: String::from("whatever"),
            })
            .to_request();

        let resp = test::call_service(&mut app, req).await;

        assert_eq!(resp.status(), StatusCode::UNAUTHORIZED);
    }
}