mirror of
https://github.com/block/buzz.git
synced 2026-11-05 17:01:35 +00:00
fix(relay): let an operator rename an archived channel
The relay refused every edit of an archived channel unless it also unarchived it, so the rename script could not repair an archived duplicate such as the old square-ios copy, and the unique index could not be built. A relay operator's name-only rename now applies to an archived channel and leaves it archived. Other edits of an archived channel are still refused. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Logan Johnson <loganj@squareup.com>
This commit is contained in:
@@ -1393,6 +1393,9 @@ pub struct ChannelMetadataEdit {
|
||||
pub purpose: Option<String>,
|
||||
/// `Some(true)` archives the channel; `Some(false)` restores it.
|
||||
pub archived: Option<bool>,
|
||||
/// Lets this edit change an archived channel, which stays archived. Only
|
||||
/// a relay operator's name-only rename sets it.
|
||||
pub keep_archived: bool,
|
||||
}
|
||||
|
||||
/// The result of [`Db::apply_channel_metadata_event`].
|
||||
@@ -1450,6 +1453,7 @@ pub(crate) async fn apply_channel_metadata_event(
|
||||
// channel already in the requested state.
|
||||
match (locked.archived(), edit.archived) {
|
||||
(true, Some(false)) | (false, None | Some(true)) => {}
|
||||
(true, None) if edit.keep_archived => {}
|
||||
(true, _) => return Err(DbError::AccessDenied("channel is archived".to_string())),
|
||||
(false, Some(false)) => {
|
||||
return Err(DbError::AccessDenied("channel is not archived".to_string()));
|
||||
@@ -1462,6 +1466,7 @@ pub(crate) async fn apply_channel_metadata_event(
|
||||
topic,
|
||||
purpose,
|
||||
archived,
|
||||
keep_archived: _,
|
||||
} = edit;
|
||||
let actor = event.pubkey.to_bytes();
|
||||
if !columns.is_empty() {
|
||||
|
||||
@@ -1202,6 +1202,27 @@ async fn a_relay_operator_may_only_rename_a_channel() {
|
||||
assert_eq!(name(state.clone()).await, before);
|
||||
}
|
||||
|
||||
// The rename repairs archived duplicates too, so archive the channel. An
|
||||
// owner still may not edit it while it is archived.
|
||||
state
|
||||
.db
|
||||
.archive_channel(community_id, channel)
|
||||
.await
|
||||
.expect("archive");
|
||||
match ingest_event(
|
||||
&state,
|
||||
&tenant,
|
||||
edit(&owner, &[&["name", "by-owner"]]),
|
||||
http_auth(&owner),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(IngestError::Rejected(message)) => assert!(message.contains("archived"), "{message}"),
|
||||
Err(other) => panic!("expected a refusal, got {other:?}"),
|
||||
Ok(result) => panic!("expected a refusal, got {:?}", result.message),
|
||||
}
|
||||
assert_eq!(name(state.clone()).await, before);
|
||||
|
||||
let renamed = ingest_event(
|
||||
&state,
|
||||
&tenant,
|
||||
@@ -1212,6 +1233,16 @@ async fn a_relay_operator_may_only_rename_a_channel() {
|
||||
.unwrap_or_else(|error| panic!("operator rename: {error:?}"));
|
||||
assert!(renamed.accepted, "{}", renamed.message);
|
||||
assert_eq!(name(state.clone()).await, "renamed-by-operator");
|
||||
assert!(
|
||||
state
|
||||
.db
|
||||
.get_channel(community_id, channel)
|
||||
.await
|
||||
.expect("channel")
|
||||
.archived_at
|
||||
.is_some(),
|
||||
"the rename keeps the channel archived"
|
||||
);
|
||||
let tags = group_state_tags(&state, &tenant, channel, 39000).await;
|
||||
assert!(
|
||||
tags.iter()
|
||||
|
||||
@@ -2144,6 +2144,10 @@ pub(crate) async fn persist_edit_metadata(
|
||||
if let Some(labels) = channel_labels_from_tags(event) {
|
||||
edit.columns.labels = Some(labels.map_err(|e| anyhow::anyhow!("{e}"))?);
|
||||
}
|
||||
// An operator's rename may repair an archived duplicate name, so it
|
||||
// applies to an archived channel and leaves it archived.
|
||||
edit.keep_archived =
|
||||
is_rename_only(event) && actor_is_relay_operator(state, event.pubkey.to_bytes()).await?;
|
||||
|
||||
let now = chrono::Utc::now();
|
||||
let mut notices = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user