quokka-admin 0.1.0

An admin panel for quokka
Documentation
use quokka::{
    helper::database::BaseRepository,
    state::{CommandHandler, FromState},
};

use crate::{
    entity::group::{GroupRepository, UserGroup, UserGroupRepository},
    service::user_service::UserService,
};

#[derive(Clone, FromState)]
pub struct AdminCreateCommand {
    user_service: UserService,
    group_repository: GroupRepository,
    user_group_repository: UserGroupRepository,
}

impl CommandHandler for AdminCreateCommand {
    fn args() -> clap::Command
    where
        Self: Sized,
    {
        clap::Command::new("quokka-admin:user:admin:create")
            .arg(clap::arg!(<username> "The name of the admin user"))
            .arg(clap::arg!(<email> "The name of the admin user"))
            .arg(clap::arg!(--password <password> "The password for the user"))
            .arg(clap::arg!(--admin_group <group> "The admin group").default_value("admin"))
    }

    async fn call(self, args: clap::ArgMatches) -> quokka::Result<()> {
        let username = args.get_one::<String>("username").cloned().unwrap();
        let email = args.get_one::<String>("email").cloned().unwrap();
        let password = args.get_one::<String>("password").cloned();
        let admin_group = args.get_one::<String>("admin_group").unwrap();

        let password = if let Some(password) = password {
            password
        } else {
            println!("Enter a password for {username}");

            let password1 = rpassword::read_password().map_err(quokka::Error::wrap_error(
                "Error while reading password",
                500,
            ))?;

            println!("Confirm the password");

            let password2 = rpassword::read_password().map_err(quokka::Error::wrap_error(
                "Error while reading password",
                500,
            ))?;

            if password1 == password2 {
                password2
            } else {
                return Err(quokka::Error::new("Passwords not matching"));
            }
        };

        let user = self
            .user_service
            .register_user(crate::service::user_service::UserRegistration {
                username,
                password,
                email,
            })
            .await?;

        tracing::info!("User {} with id {} added", user.username, user.id);

        if let Some(group) = self.group_repository.get_group_by_name(admin_group).await? {
            self.user_group_repository
                .create_entity(UserGroup {
                    user_id: user.id,
                    group_id: group.id,
                    created_at: time::OffsetDateTime::now_utc(),
                    updated_at: time::OffsetDateTime::now_utc(),
                })
                .await?;
            tracing::info!("Adding user to group \"admin\"")
        } else {
            tracing::info!("Admin group missing. User will not be assigned to it.")
        }

        Ok(())
    }
}