cli: Add basic functionality to assign membership

This commit is contained in:
Lennart
2025-04-26 11:23:15 +02:00
parent 4c6de20d75
commit 8ae8a5cda7
3 changed files with 77 additions and 2 deletions

View File

@@ -0,0 +1,72 @@
use clap::{Parser, Subcommand};
use rustical_store::auth::AuthenticationProvider;
#[derive(Debug, Parser)]
pub struct AssignArgs {
id: String,
#[arg(long, help = "The principal to assign a membership to (e.g. a group)")]
to: String,
}
#[derive(Debug, Parser)]
pub struct RemoveArgs {
id: String,
#[arg(long, help = "The membership to remove")]
to: String,
}
#[derive(Debug, Parser)]
pub struct ListArgs {
id: String,
}
#[derive(Debug, Subcommand)]
pub enum MembershipCommand {
Assign(AssignArgs),
Remove(RemoveArgs),
List(ListArgs),
}
#[derive(Parser, Debug)]
pub struct MembershipArgs {
#[command(subcommand)]
command: MembershipCommand,
}
pub async fn handle_membership_command(
user_store: impl AuthenticationProvider,
MembershipArgs { command }: MembershipArgs,
) -> anyhow::Result<()> {
let id = match &command {
MembershipCommand::Assign(AssignArgs { id, .. }) => id,
MembershipCommand::Remove(RemoveArgs { id, .. }) => id,
MembershipCommand::List(ListArgs { id }) => id,
};
let mut principal = user_store
.get_principal(id)
.await?
.unwrap_or_else(|| panic!("Principal {id} does not exist"));
match command {
MembershipCommand::Assign(AssignArgs { to, .. }) => {
if principal.memberships.contains(&to) {
println!("Principal is already member of {to}");
return Ok(());
}
principal.memberships.push(to);
user_store.insert_principal(principal, true).await?;
println!("Membership assigned");
}
MembershipCommand::Remove(RemoveArgs { to, .. }) => {
principal.memberships.retain(|principal| principal != &to);
user_store.insert_principal(principal, true).await?;
println!("Membership removed");
}
MembershipCommand::List(ListArgs { .. }) => {
for membership in principal.memberships {
println!("{membership}");
}
}
}
Ok(())
}

View File

@@ -11,6 +11,7 @@ use crate::config::{
TracingConfig,
};
mod membership;
pub mod principals;
#[derive(Debug, Parser)]

View File

@@ -1,3 +1,5 @@
use super::membership::{MembershipArgs, handle_membership_command};
use crate::config::{self, Config};
use clap::{Parser, Subcommand};
use figment::{
Figment,
@@ -8,8 +10,6 @@ use password_hash::SaltString;
use rand::rngs::OsRng;
use rustical_store::auth::{AuthenticationProvider, TomlPrincipalStore, User, user::PrincipalType};
use crate::config::{self, Config};
#[derive(Parser, Debug)]
pub struct PrincipalsArgs {
#[arg(short, long, env, default_value = "/etc/rustical/config.toml")]
@@ -57,6 +57,7 @@ enum Command {
Create(CreateArgs),
Remove(RemoveArgs),
Edit(EditArgs),
Membership(MembershipArgs),
}
pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> {
@@ -155,6 +156,7 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> {
user_store.insert_principal(principal, true).await?;
println!("Principal {id} updated");
}
Command::Membership(args) => handle_membership_command(user_store, args).await?,
}
Ok(())
}