Set channel mode +r when a channel is registered
ChanServ sends FMODE to mark a registered channel +r (the m_services c_registered mode), and -r on drop. Sourced from our server, which the ircd requires for that mode, with a low TS so it applies to the existing channel.
This commit is contained in:
parent
89593ebeb4
commit
64500906d8
5 changed files with 33 additions and 6 deletions
|
|
@ -922,16 +922,20 @@ mod tests {
|
||||||
// Not identified yet: refused.
|
// Not identified yet: refused.
|
||||||
assert!(notice(&to_cs(&mut e, "000AAAAAB", "REGISTER #room"), "must be identified"));
|
assert!(notice(&to_cs(&mut e, "000AAAAAB", "REGISTER #room"), "must be identified"));
|
||||||
|
|
||||||
// Identify, then register.
|
// Identify, then register: sets +r on the channel.
|
||||||
e.handle(NetEvent::Privmsg { from: "000AAAAAB".into(), to: "42SAAAAAA".into(), text: "IDENTIFY sesame".into() });
|
e.handle(NetEvent::Privmsg { from: "000AAAAAB".into(), to: "42SAAAAAA".into(), text: "IDENTIFY sesame".into() });
|
||||||
assert!(notice(&to_cs(&mut e, "000AAAAAB", "REGISTER #room"), "now registered"));
|
let out = to_cs(&mut e, "000AAAAAB", "REGISTER #room");
|
||||||
|
assert!(notice(&out, "now registered"));
|
||||||
|
assert!(out.iter().any(|a| matches!(a, NetAction::ChannelMode { channel, modes } if channel == "#room" && modes == "+r")), "register sets +r: {out:?}");
|
||||||
assert!(notice(&to_cs(&mut e, "000AAAAAB", "INFO #room"), "alice"));
|
assert!(notice(&to_cs(&mut e, "000AAAAAB", "INFO #room"), "alice"));
|
||||||
|
|
||||||
// A different, unidentified user cannot drop it.
|
// A different, unidentified user cannot drop it.
|
||||||
e.handle(NetEvent::UserConnect { uid: "000AAAAAC".into(), nick: "bob".into() });
|
e.handle(NetEvent::UserConnect { uid: "000AAAAAC".into(), nick: "bob".into() });
|
||||||
assert!(notice(&to_cs(&mut e, "000AAAAAC", "DROP #room"), "founder"));
|
assert!(notice(&to_cs(&mut e, "000AAAAAC", "DROP #room"), "founder"));
|
||||||
|
|
||||||
// The founder can.
|
// The founder can, which also clears +r.
|
||||||
assert!(notice(&to_cs(&mut e, "000AAAAAB", "DROP #room"), "dropped"));
|
let out = to_cs(&mut e, "000AAAAAB", "DROP #room");
|
||||||
|
assert!(notice(&out, "dropped"));
|
||||||
|
assert!(out.iter().any(|a| matches!(a, NetAction::ChannelMode { channel, modes } if channel == "#room" && modes == "-r")), "drop clears +r: {out:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,4 +74,12 @@ impl ServiceCtx {
|
||||||
nick: nick.to_string(),
|
nick: nick.to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set channel modes from services, e.g. "+r" on a registered channel.
|
||||||
|
pub fn channel_mode(&mut self, channel: &str, modes: &str) {
|
||||||
|
self.actions.push(NetAction::ChannelMode {
|
||||||
|
channel: channel.to_string(),
|
||||||
|
modes: modes.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,12 @@ impl Protocol for InspIrcd {
|
||||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(self.ts);
|
let now = SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(self.ts);
|
||||||
vec![self.from_us(format!("SVSNICK {} {} {}", uid, nick, now))]
|
vec![self.from_us(format!("SVSNICK {} {} {}", uid, nick, now))]
|
||||||
}
|
}
|
||||||
|
// FMODE <chan> <ts> <modes>. The ircd drops an FMODE whose TS is newer
|
||||||
|
// than the channel's, so we send TS 1 to guarantee it applies to the
|
||||||
|
// existing channel. Sourced from our server, which +r requires.
|
||||||
|
NetAction::ChannelMode { channel, modes } => {
|
||||||
|
vec![self.from_us(format!("FMODE {} 1 {}", channel, modes))]
|
||||||
|
}
|
||||||
NetAction::Raw(s) => vec![s.clone()],
|
NetAction::Raw(s) => vec![s.clone()],
|
||||||
// Internal: the link layer handles this before serialization.
|
// Internal: the link layer handles this before serialization.
|
||||||
NetAction::DeferRegister { .. } => vec![],
|
NetAction::DeferRegister { .. } => vec![],
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ pub enum NetAction {
|
||||||
// Force a user's nick (SVSNICK), e.g. renaming to a guest nick on logout.
|
// Force a user's nick (SVSNICK), e.g. renaming to a guest nick on logout.
|
||||||
// The protocol stamps the new nick's timestamp.
|
// The protocol stamps the new nick's timestamp.
|
||||||
ForceNick { uid: String, nick: String },
|
ForceNick { uid: String, nick: String },
|
||||||
|
// Set channel modes from services, e.g. +r on a registered channel. The
|
||||||
|
// protocol stamps a timestamp the ircd will accept.
|
||||||
|
ChannelMode { channel: String, modes: String },
|
||||||
Raw(String),
|
Raw(String),
|
||||||
// Internal only, never serialized to the wire: a registration whose password
|
// Internal only, never serialized to the wire: a registration whose password
|
||||||
// still needs its (expensive) key derivation. The link layer runs the
|
// still needs its (expensive) key derivation. The link layer runs the
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,10 @@ impl Service for ChanServ {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
match db.register_channel(chan, account) {
|
match db.register_channel(chan, account) {
|
||||||
Ok(()) => ctx.notice(me, from.uid, format!("Channel \x02{chan}\x02 is now registered to \x02{account}\x02.")),
|
Ok(()) => {
|
||||||
|
ctx.channel_mode(chan, "+r"); // mark the channel registered
|
||||||
|
ctx.notice(me, from.uid, format!("Channel \x02{chan}\x02 is now registered to \x02{account}\x02."));
|
||||||
|
}
|
||||||
Err(ChanError::Exists) => ctx.notice(me, from.uid, format!("\x02{chan}\x02 is already registered.")),
|
Err(ChanError::Exists) => ctx.notice(me, from.uid, format!("\x02{chan}\x02 is already registered.")),
|
||||||
Err(_) => ctx.notice(me, from.uid, "Registration failed, please try again later."),
|
Err(_) => ctx.notice(me, from.uid, "Registration failed, please try again later."),
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +70,10 @@ impl Service for ChanServ {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match db.drop_channel(chan) {
|
match db.drop_channel(chan) {
|
||||||
Ok(()) => ctx.notice(me, from.uid, format!("Channel \x02{chan}\x02 has been dropped.")),
|
Ok(()) => {
|
||||||
|
ctx.channel_mode(chan, "-r"); // no longer registered
|
||||||
|
ctx.notice(me, from.uid, format!("Channel \x02{chan}\x02 has been dropped."));
|
||||||
|
}
|
||||||
Err(_) => ctx.notice(me, from.uid, "Drop failed, please try again later."),
|
Err(_) => ctx.notice(me, from.uid, "Drop failed, please try again later."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue