Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions crates/buzz-cli/src/commands/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,11 +829,27 @@ fn validate_ttl_seconds(secs: i64) -> Result<i32, CliError> {
.map_err(|_| CliError::Usage(format!("--ttl is too large (max {} seconds)", i32::MAX)))
}

fn validate_update_channel_fields(
name: Option<&str>,
description: Option<&str>,
visibility: Option<&str>,
ttl_change: Option<Option<i32>>,
) -> Result<(), CliError> {
if name.is_none() && description.is_none() && visibility.is_none() && ttl_change.is_none() {
return Err(CliError::Usage(
"at least one field required (--name, --description, --visibility, --ttl, --no-ttl)"
.into(),
));
}
Ok(())
}

pub async fn cmd_update_channel(
client: &BuzzClient,
channel_id: &str,
name: Option<&str>,
description: Option<&str>,
visibility: Option<&str>,
ttl: Option<i64>,
no_ttl: bool,
) -> Result<(), CliError> {
Expand All @@ -845,15 +861,12 @@ pub async fn cmd_update_channel(
(None, false) => None,
};

if name.is_none() && description.is_none() && ttl_change.is_none() {
return Err(CliError::Usage(
"at least one field required (--name, --description, --ttl, --no-ttl)".into(),
));
}
validate_update_channel_fields(name, description, visibility, ttl_change)?;
let channel_uuid = parse_uuid(channel_id)?;

let builder = buzz_sdk::build_update_channel(channel_uuid, name, description, None, ttl_change)
.map_err(|e| CliError::Other(format!("build_update_channel failed: {e}")))?;
let builder =
buzz_sdk::build_update_channel(channel_uuid, name, description, visibility, ttl_change)
.map_err(|e| CliError::Other(format!("build_update_channel failed: {e}")))?;

let event = client.sign_event(builder)?;
let resp = client.submit_event(event).await?;
Expand Down Expand Up @@ -1128,14 +1141,17 @@ pub async fn dispatch(
channel,
name,
description,
visibility,
ttl,
no_ttl,
} => {
let visibility = visibility.as_ref().map(|v| v.to_string());
cmd_update_channel(
client,
&channel,
name.as_deref(),
description.as_deref(),
visibility.as_deref(),
ttl,
no_ttl,
)
Expand Down Expand Up @@ -1178,8 +1194,8 @@ mod tests {
use super::{
apply_cardinality_rule, build_template_report, cmd_set_add_policy,
finalize_roster_resolution, name_matches, resolve_roster_with_archive_filter,
validate_ttl_seconds, ArchivedExclusion, ChannelSummary, ResolvedAgent, RosterResolution,
SkippedSlug,
validate_ttl_seconds, validate_update_channel_fields, ArchivedExclusion, ChannelSummary,
ResolvedAgent, RosterResolution, SkippedSlug,
};
use crate::client::BuzzClient;
use crate::CliError;
Expand Down Expand Up @@ -1291,6 +1307,21 @@ mod tests {
assert!(validate_ttl_seconds(i32::MAX as i64 + 1).is_err());
}

#[test]
fn update_channel_fields_rejects_empty_update() {
let result = validate_update_channel_fields(None, None, None, None);
assert!(matches!(result, Err(CliError::Usage(_))));
let msg = result.unwrap_err().to_string();
assert!(msg.contains("at least one field required"));
assert!(msg.contains("--visibility"));
}

#[test]
fn update_channel_fields_accepts_visibility_only_update() {
let result = validate_update_channel_fields(None, None, Some("open"), None);
assert!(result.is_ok(), "visibility-only update should be accepted");
}

// --- BUZZ_ACP_ALLOWED_CHANNEL_ADD_POLICIES gate ---

fn check_allowed_channel_add_policy(allowed_raw: &str, policy: &str) -> Result<(), CliError> {
Expand Down
8 changes: 7 additions & 1 deletion crates/buzz-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,10 @@ pub enum ChannelsCmd {
#[arg(long, value_name = "PATH")]
templates_file: Option<String>,
},
/// Update channel name, description, or ephemeral TTL
/// Update channel name, description, visibility, or ephemeral TTL
#[command(
after_help = "Examples:\n buzz channels update --channel <uuid> --name general\n buzz channels update --channel <uuid> --visibility open\n buzz channels update --channel <uuid> --visibility private"
)]
Update {
/// Channel UUID
#[arg(long)]
Expand All @@ -588,6 +591,9 @@ pub enum ChannelsCmd {
/// New channel description
#[arg(long)]
description: Option<String>,
/// New channel visibility
#[arg(long, value_enum)]
visibility: Option<ChannelVisibility>,
/// Make the channel ephemeral (or change its lifetime): seconds until
/// the relay archives it after the last message. Conflicts with --no-ttl.
#[arg(long, value_name = "SECONDS", conflicts_with = "no_ttl")]
Expand Down
Loading