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
app_state.rs 2.24 KiB
Newer Older
Pierre Jarriges's avatar
Pierre Jarriges committed
use crate::{crypto::Encryption, env::Env, init_admin::create_default_admin_if_none};
use wither::mongodb::{options::ClientOptions, Client, Database};

#[derive(Debug, Clone)]
/// The app_state that must be given to the actix::App instance using App::new().app_data(web::Data::new(AppState::new()))
/// It holds the database client connection, an Env struct which provides all values defined in the .env file,
/// and an Encryption struct which is reponsible for encrypting and decrypting data such as passwords and auth tokens.
pub struct AppState {
    pub db: Database,
    pub env: Env,
    pub encryption: Encryption,
}

impl AppState {
    /// Creates the Mongodb database client connection
    async fn get_db_connection(host: &str, env: &Env) -> Database {
        let db_connection_string = format!(
            "mongodb://{}:{}@{}:{}/{}",
            env.db_username, env.db_user_pwd, host, env.db_port, env.db_name
        );

        let client_options = ClientOptions::parse(&db_connection_string)
            .await
            .expect("Error creating database client options");

        let client = Client::with_options(client_options).expect("Couldn't connect to database.");
        client.database(&env.db_name)
    }

    pub async fn new() -> Self {
        let env = Env::new();
        let db = Self::get_db_connection(&env.db_name, &env).await;

        let encryption = Encryption::new(env.crypt_key.to_owned());

        AppState {
            db,
            env,
            encryption,
        }
    }

    /// This calls Self::new() and creates a default administrator before returning the instance
    pub async fn with_default_admin_user() -> Self {
        let instance = Self::new().await;
        if let Err(e) = create_default_admin_if_none(&instance).await {
            panic!("Error creating admin user: {}\nWill exit process now.", e);
        };
        instance
    }

    #[cfg(test)]
    /// Provides an instance with some specificities for testing
    pub async fn for_test() -> Self {
        let env = Env::for_test();
        let db = Self::get_db_connection("localhost", &env).await;

        let encryption = Encryption::new(env.crypt_key.to_owned());

        AppState {
            db,
            env,
            encryption,
        }
    }
}