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
administrator.rs 2.96 KiB
Newer Older
  • Learn to ignore specific revisions
  • Pierre Jarriges's avatar
    Pierre Jarriges committed
    use crate::AppState;
    use actix_web::http::Cookie;
    use serde::{Deserialize, Serialize};
    use wither::{
        bson::{doc, oid::ObjectId},
        prelude::Model,
    };
    
    #[derive(Debug, Serialize, Deserialize)]
    /// The data type that must sent by form data POST to authenticate an administrator.
    pub struct AdminAuthCredentials {
        pub username: String,
        pub password: String,
    }
    
    #[derive(Debug, Deserialize, Serialize, Model)]
    #[model(index(
        keys = r#"doc!{"email": 1, "username": 1}"#,
        options = r#"doc!{"unique": true}"#
    ))]
    /// An administrator is a user with registered authentication credentials access right to the admin-panel and has ability to perform admin actions such as gam review, moderation, etc.
    pub struct Administrator {
        #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
        pub id: Option<ObjectId>,
        pub username: String,
        pub password_hash: String,
        pub auth_token: Option<String>,
    }
    
    impl Administrator {
        /// Creates an administrator with values for username and password.
        /// The auth_token fields remains None as it must be created if the user authenticates itself with the provided credentials
        /// The password is stored as password_hash, it is encrypted with the AppState::Encryption.
        pub fn from_values(app_state: &AppState, username: String, password: String) -> Self {
            Administrator {
                id: None,
                password_hash: app_state.encryption.encrypt(&password),
                username,
                auth_token: None,
            }
        }
    
        /// Performs authentication with form data <username, password>.
        /// Returns a Result with either an authenticated Administrator instance or an error.
        pub async fn authenticated(
            app_state: &AppState,
            credentials: AdminAuthCredentials,
        ) -> Result<Self, ()> {
            let filter_doc = doc! {
                "password_hash": app_state.encryption.encrypt(&credentials.password),
                "username": credentials.username
            };
    
            match Administrator::find_one(&app_state.db, filter_doc, None).await {
                Ok(user_option) => match user_option {
                    Some(admin) => Ok(admin),
                    None => Err(()),
                },
                Err(_) => Err(()),
            }
        }
    
        /// Performs authenticattion with auth cookie. The cookie value must match the Administrator auth_token value.
        /// Returns a result with either the authenticated admin, or an empty Err.
        pub async fn authenticated_with_cookie(
            app_state: &AppState,
            auth_cookie: &Cookie<'_>,
        ) -> Result<Self, ()> {
            let cookie_value = auth_cookie.value().to_string();
    
            let filter_doc = doc! {
                "auth_token": app_state.encryption.encrypt(&cookie_value),
            };
    
            match Administrator::find_one(&app_state.db, filter_doc, None).await {
                Ok(user_option) => match user_option {
                    Some(admin) => Ok(admin),
                    None => Err(()),
                },
                Err(_) => Err(()),
            }
        }
    }