Freeze ChanServ MODE/ACCESS/FLAGS on suspended channels and make PEACE group-access-aware

This commit is contained in:
Jean Chevronnet 2026-07-19 15:59:00 +00:00
parent 16d2a5035a
commit 8f41fc9903
No known key found for this signature in database
4 changed files with 14 additions and 2 deletions

View file

@ -69,6 +69,7 @@ fn is_founder(me: &str, from: &Sender, chan: &str, ctx: &mut ServiceCtx, db: &dy
ctx.notice(me, from.uid, format!("Only \x02{chan}\x02's founder can change access.")); ctx.notice(me, from.uid, format!("Only \x02{chan}\x02's founder can change access."));
false false
} }
Some(_) => true, // Founder, but a staff-suspended channel is frozen — no access changes.
Some(_) => !super::suspended_block(me, from, chan, ctx, db),
} }
} }

View file

@ -45,6 +45,9 @@ pub fn handle(me: &str, from: &Sender, chan: &str, args: &[&str], ctx: &mut Serv
ctx.notice(me, from.uid, format!("You need the founder or the \x02a\x02 flag to change access on \x02{chan}\x02.")); ctx.notice(me, from.uid, format!("You need the founder or the \x02a\x02 flag to change access on \x02{chan}\x02."));
return; return;
} }
if super::suspended_block(me, from, chan, ctx, db) {
return; // a staff-suspended channel is frozen: no flag changes either
}
if info.founder.eq_ignore_ascii_case(target) { if info.founder.eq_ignore_ascii_case(target) {
ctx.notice(me, from.uid, "The founder's access is set with \x02SET FOUNDER\x02, not flags."); ctx.notice(me, from.uid, "The founder's access is set with \x02SET FOUNDER\x02, not flags.");
return; return;

View file

@ -378,7 +378,12 @@ fn peace_blocks(me: &str, from: &Sender, chan: &str, target_uid: &str, ctx: &mut
if target_uid == from.uid { if target_uid == from.uid {
return false; return false;
} }
if info.access_rank(net.account_of(target_uid)) >= info.access_rank(from.account) { // Group-aware rank: channel_caps resolves !group access (and founder), so PEACE
// protects a member whose access comes via a group, not just direct entries —
// ChannelView::access_rank is group-blind and let a plain op act against a
// group-SOP it should protect.
let rank = |account: Option<&str>| account.map_or(echo_api::Rank::None, |a| db.channel_caps(chan, a).rank);
if rank(net.account_of(target_uid)) >= rank(from.account) {
ctx.notice(me, from.uid, "\x02PEACE\x02 is set: you can't act against someone with equal or higher access."); ctx.notice(me, from.uid, "\x02PEACE\x02 is set: you can't act against someone with equal or higher access.");
return true; return true;
} }

View file

@ -24,6 +24,9 @@ pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db:
ctx.notice(me, from.uid, format!("Only \x02{chan}\x02's founder can change its modes.")); ctx.notice(me, from.uid, format!("Only \x02{chan}\x02's founder can change its modes."));
return; return;
} }
if super::suspended_block(me, from, chan, ctx, db) {
return; // a staff-suspended channel is frozen: no mode changes either
}
// Reject an extban the network has turned off, before relaying anything. // Reject an extban the network has turned off, before relaying anything.
for mask in ban_masks(&args[2..], |m, adding| db.chanmode_takes_param(m, adding)) { for mask in ban_masks(&args[2..], |m, adding| db.chanmode_takes_param(m, adding)) {
let core = mask.strip_prefix('!').unwrap_or(mask); // extbans may be inverted let core = mask.strip_prefix('!').unwrap_or(mask); // extbans may be inverted