Implement responses for more error cases
Diff
src/channel.rs | 34 ++++++++++++++++++++++++++++++++--
src/client.rs | 15 ++++++++++++---
src/connection.rs | 6 +++---
src/channel/permissions.rs | 4 ++--
src/channel/response.rs | 36 ++++++++++++++++++++++++++++++++++++
5 files changed, 80 insertions(+), 15 deletions(-)
@@ -9,7 +9,7 @@
};
use chrono::{DateTime, Utc};
use futures::future::Either;
use irc_proto::{Command, Message, Mode};
use irc_proto::{Command, Message, Mode, Response};
use tracing::{debug, error, info, instrument, warn, Span};
use crate::{
@@ -17,6 +17,7 @@
permissions::Permission,
response::{
ChannelInviteResult, ChannelJoinRejectionReason, ChannelNamesList, ChannelTopic,
MissingPrivileges,
},
},
client::Client,
@@ -137,8 +138,22 @@
};
if !self.get_user_permissions(sender.user_id).can_chatter() {
error!("User cannot send message to channel");
msg.client.do_send(Broadcast {
message: Message {
tags: None,
prefix: None,
command: Command::Response(
Response::ERR_CANNOTSENDTOCHAN,
vec![
sender.to_nick().to_string(),
self.name.to_string(),
"Cannot send to channel".to_string(),
],
),
},
span: Span::current(),
});
return;
}
@@ -421,8 +436,12 @@
.get_user_permissions(client_info.user_id)
.can_set_topic()
{
error!("User cannot set channel topic");
error!("User attempted to set channel topic without privileges");
msg.client.do_send(Broadcast {
message: MissingPrivileges(client_info.to_nick(), self.name.to_string())
.into_message(),
span: Span::current(),
});
return;
}
@@ -455,8 +474,11 @@
};
if !self.get_user_permissions(kicker.user_id).can_kick() {
error!("Kicker can not kick people from the channel");
msg.client.do_send(Broadcast {
message: MissingPrivileges(kicker.to_nick(), self.name.to_string()).into_message(),
span: Span::current(),
});
return;
}
@@ -15,7 +15,10 @@
use crate::{
channel::Channel,
connection::{sasl::SaslAlreadyAuthenticated, Capability, InitiatedConnection, MessageSink},
connection::{
sasl::SaslAlreadyAuthenticated, Capability, InitiatedConnection, MessageSink,
NickNotOwnedByUser,
},
messages::{
Broadcast, ChannelFetchTopic, ChannelInvite, ChannelJoin, ChannelKickUser, ChannelList,
ChannelMemberList, ChannelMessage, ChannelPart, ChannelSetMode, ChannelUpdateTopic,
@@ -263,7 +266,8 @@
let handle = match handle {
Ok(v) => v,
Err(error) => {
error!(?error, "Failed to join user to channel");
error!(?error, "User failed to join channel");
this.writer.write(error.into_message());
continue;
}
};
@@ -346,7 +350,10 @@
.into_actor(self)
.map(|res, this, ctx| {
if !res.unwrap() {
ctx.notify(Broadcast {
message: NickNotOwnedByUser(msg.new_nick).into_message(),
span: Span::current(),
});
return;
}
@@ -667,7 +674,7 @@
self.writer.write(Message {
tags: None,
prefix: Some(Prefix::ServerName(SERVER_NAME.to_string())),
prefix: None,
command: Command::Response(
Response::RPL_TIME,
vec![
@@ -226,7 +226,7 @@
Ok(Some(initiated))
}
pub struct NickNotOwnedByUser(String);
pub struct NickNotOwnedByUser(pub String);
impl NickNotOwnedByUser {
#[must_use]
@@ -235,8 +235,8 @@
tags: None,
prefix: None,
command: Command::Response(
Response::ERR_NICKLOCKED,
vec![self.0, "You must use a nick assigned to you".to_string()],
Response::ERR_NICKNAMEINUSE,
vec![self.0, "Nickname is already in use".to_string()],
),
}
}
@@ -90,8 +90,8 @@
#[must_use]
pub fn can_kick(self) -> bool {
self == Self::Operator
pub const fn can_kick(self) -> bool {
(self as i16) >= (Self::HalfOperator as i16)
}
@@ -183,3 +183,39 @@
pub enum ChannelJoinRejectionReason {
Banned,
}
impl ChannelJoinRejectionReason {
#[must_use]
pub fn into_message(self) -> Message {
match self {
Self::Banned => Message {
tags: None,
prefix: Some(Prefix::ServerName(SERVER_NAME.to_string())),
command: Command::Response(
Response::ERR_BANNEDFROMCHAN,
vec!["Cannot join channel (+b)".to_string()],
),
},
}
}
}
pub struct MissingPrivileges(pub Prefix, pub String);
impl MissingPrivileges {
#[must_use]
pub fn into_message(self) -> Message {
Message {
tags: None,
prefix: None,
command: Command::Response(
Response::ERR_CHANOPRIVSNEEDED,
vec![
self.0.to_string(),
self.1,
"You're not channel operator".to_string(),
],
),
}
}
}