feat: ChatRequestResponse event
Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
parent
2bfff6c05d
commit
24e038f482
7 changed files with 133 additions and 7 deletions
|
@ -16,11 +16,12 @@
|
||||||
|
|
||||||
//! Database extension to work with the balcklist table
|
//! Database extension to work with the balcklist table
|
||||||
|
|
||||||
|
use chrono::Utc;
|
||||||
use oxidetalis_core::types::PublicKey;
|
use oxidetalis_core::types::PublicKey;
|
||||||
use oxidetalis_entities::prelude::*;
|
use oxidetalis_entities::prelude::*;
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
|
|
||||||
use crate::errors::ServerResult;
|
use crate::{errors::ServerResult, websocket::errors::WsError};
|
||||||
|
|
||||||
/// Extension trait for the `DatabaseConnection` to work with the blacklist
|
/// Extension trait for the `DatabaseConnection` to work with the blacklist
|
||||||
/// table
|
/// table
|
||||||
|
@ -32,6 +33,12 @@ pub trait BlackListExt {
|
||||||
blacklister: &UserModel,
|
blacklister: &UserModel,
|
||||||
target_public_key: &PublicKey,
|
target_public_key: &PublicKey,
|
||||||
) -> ServerResult<bool>;
|
) -> ServerResult<bool>;
|
||||||
|
/// Add the `target_public_key` to the blacklist of the `blacklister`
|
||||||
|
async fn add_to_blacklist(
|
||||||
|
&self,
|
||||||
|
blacklister: &UserModel,
|
||||||
|
target_public_key: &PublicKey,
|
||||||
|
) -> ServerResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlackListExt for DatabaseConnection {
|
impl BlackListExt for DatabaseConnection {
|
||||||
|
@ -49,4 +56,26 @@ impl BlackListExt for DatabaseConnection {
|
||||||
.map(|u| u.is_some())
|
.map(|u| u.is_some())
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn add_to_blacklist(
|
||||||
|
&self,
|
||||||
|
blacklister: &UserModel,
|
||||||
|
target_public_key: &PublicKey,
|
||||||
|
) -> ServerResult<()> {
|
||||||
|
if self.is_blacklisted(blacklister, target_public_key).await? {
|
||||||
|
return Err(WsError::AlreadyOnTheblacklist.into());
|
||||||
|
}
|
||||||
|
if blacklister.public_key == target_public_key.to_string() {
|
||||||
|
return Err(WsError::CannotAddSelfToBlacklist.into());
|
||||||
|
}
|
||||||
|
BlacklistActiveModel {
|
||||||
|
user_id: Set(blacklister.id),
|
||||||
|
target: Set(target_public_key.to_string()),
|
||||||
|
blacklisted_at: Set(Utc::now()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.save(self)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub trait OutChatRequestsExt {
|
||||||
&self,
|
&self,
|
||||||
requester: &UserModel,
|
requester: &UserModel,
|
||||||
recipient: &PublicKey,
|
recipient: &PublicKey,
|
||||||
) -> ServerResult<bool>;
|
) -> ServerResult<Option<OutChatRequestsModel>>;
|
||||||
|
|
||||||
/// Save the chat request in the requester table
|
/// Save the chat request in the requester table
|
||||||
async fn save_out_chat_request(
|
async fn save_out_chat_request(
|
||||||
|
@ -38,6 +38,13 @@ pub trait OutChatRequestsExt {
|
||||||
requester: &UserModel,
|
requester: &UserModel,
|
||||||
recipient: &PublicKey,
|
recipient: &PublicKey,
|
||||||
) -> ServerResult<()>;
|
) -> ServerResult<()>;
|
||||||
|
|
||||||
|
/// Remove the chat request from requester table
|
||||||
|
async fn remove_out_chat_request(
|
||||||
|
&self,
|
||||||
|
requester: &UserModel,
|
||||||
|
recipient: &PublicKey,
|
||||||
|
) -> ServerResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutChatRequestsExt for DatabaseConnection {
|
impl OutChatRequestsExt for DatabaseConnection {
|
||||||
|
@ -46,13 +53,12 @@ impl OutChatRequestsExt for DatabaseConnection {
|
||||||
&self,
|
&self,
|
||||||
requester: &UserModel,
|
requester: &UserModel,
|
||||||
recipient: &PublicKey,
|
recipient: &PublicKey,
|
||||||
) -> ServerResult<bool> {
|
) -> ServerResult<Option<OutChatRequestsModel>> {
|
||||||
requester
|
requester
|
||||||
.find_related(OutChatRequestsEntity)
|
.find_related(OutChatRequestsEntity)
|
||||||
.filter(OutChatRequestsColumn::Recipient.eq(recipient.to_string()))
|
.filter(OutChatRequestsColumn::Recipient.eq(recipient.to_string()))
|
||||||
.one(self)
|
.one(self)
|
||||||
.await
|
.await
|
||||||
.map(|user| user.is_some())
|
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +68,11 @@ impl OutChatRequestsExt for DatabaseConnection {
|
||||||
requester: &UserModel,
|
requester: &UserModel,
|
||||||
recipient: &PublicKey,
|
recipient: &PublicKey,
|
||||||
) -> ServerResult<()> {
|
) -> ServerResult<()> {
|
||||||
if self.have_chat_request_to(requester, recipient).await? {
|
if self
|
||||||
|
.have_chat_request_to(requester, recipient)
|
||||||
|
.await?
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
return Err(WsError::AlreadySendChatRequest.into());
|
return Err(WsError::AlreadySendChatRequest.into());
|
||||||
}
|
}
|
||||||
OutChatRequestsActiveModel {
|
OutChatRequestsActiveModel {
|
||||||
|
@ -75,4 +85,15 @@ impl OutChatRequestsExt for DatabaseConnection {
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn remove_out_chat_request(
|
||||||
|
&self,
|
||||||
|
requester: &UserModel,
|
||||||
|
recipient: &PublicKey,
|
||||||
|
) -> ServerResult<()> {
|
||||||
|
if let Some(out_model) = self.have_chat_request_to(requester, recipient).await? {
|
||||||
|
out_model.delete(self).await?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,11 @@ ws_errors! {
|
||||||
RegistredUserEvent = "The event is only for registred users",
|
RegistredUserEvent = "The event is only for registred users",
|
||||||
UserNotFound = "The user is not registered in the server",
|
UserNotFound = "The user is not registered in the server",
|
||||||
AlreadyOnTheWhitelist = "The user is already on your whitelist",
|
AlreadyOnTheWhitelist = "The user is already on your whitelist",
|
||||||
|
CannotAddSelfToWhitelist = "You cannot add yourself to the whitelist",
|
||||||
|
AlreadyOnTheblacklist = "The user is already on your blacklist",
|
||||||
|
CannotAddSelfToBlacklist = "You cannot add yourself to the blacklist",
|
||||||
AlreadySendChatRequest = "You have already sent a chat request to this user",
|
AlreadySendChatRequest = "You have already sent a chat request to this user",
|
||||||
CannotSendChatRequestToSelf = "You cannot send a chat request to yourself",
|
CannotSendChatRequestToSelf = "You cannot send a chat request to yourself",
|
||||||
CannotAddSelfToWhitelist = "You cannot add yourself to the whitelist",
|
CannotRespondToOwnChatRequest = "You cannot respond to your own chat request",
|
||||||
|
NoChatRequestFromRecipient = "You do not have a chat request from the recipient",
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ pub struct ClientEvent {
|
||||||
signature: Signature,
|
signature: Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ## Important for contuributors
|
||||||
|
// Please make sure to order the event data alphabetically.
|
||||||
|
|
||||||
/// Client websocket event type
|
/// Client websocket event type
|
||||||
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
|
||||||
#[serde(rename_all = "PascalCase", tag = "event", content = "data")]
|
#[serde(rename_all = "PascalCase", tag = "event", content = "data")]
|
||||||
|
@ -39,6 +42,8 @@ pub enum ClientEventType {
|
||||||
Pong { timestamp: u64 },
|
Pong { timestamp: u64 },
|
||||||
/// Request to chat with a user
|
/// Request to chat with a user
|
||||||
ChatRequest { to: PublicKey },
|
ChatRequest { to: PublicKey },
|
||||||
|
/// Response to a chat request
|
||||||
|
ChatRequestResponse { accepted: bool, to: PublicKey },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientEventType {
|
impl ClientEventType {
|
||||||
|
|
|
@ -55,6 +55,8 @@ pub enum ServerEventType {
|
||||||
Message { msg: String },
|
Message { msg: String },
|
||||||
/// New chat request from someone
|
/// New chat request from someone
|
||||||
ChatRequest { from: PublicKey },
|
ChatRequest { from: PublicKey },
|
||||||
|
/// New chat request response from someone
|
||||||
|
ChatRequestResponse { from: PublicKey, accepted: bool },
|
||||||
/// Error event
|
/// Error event
|
||||||
Error {
|
Error {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
|
@ -105,6 +107,11 @@ impl ServerEvent<Unsigned> {
|
||||||
Self::new(ServerEventType::ChatRequest { from: *from })
|
Self::new(ServerEventType::ChatRequest { from: *from })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create chat request response event
|
||||||
|
pub fn chat_request_response(from: PublicKey, accepted: bool) -> Self {
|
||||||
|
Self::new(ServerEventType::ChatRequestResponse { from, accepted })
|
||||||
|
}
|
||||||
|
|
||||||
/// Sign the event
|
/// Sign the event
|
||||||
pub fn sign(self, shared_secret: &[u8; 32]) -> ServerEvent<Signed> {
|
pub fn sign(self, shared_secret: &[u8; 32]) -> ServerEvent<Signed> {
|
||||||
ServerEvent::<Signed> {
|
ServerEvent::<Signed> {
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub async fn handle_chat_request(
|
||||||
"You are unable to send a chat request because you are on the recipient's blacklist.",
|
"You are unable to send a chat request because you are on the recipient's blacklist.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if try_ws!(db.have_chat_request_to(from_user, to_public_key).await) {
|
if try_ws!(db.have_chat_request_to(from_user, to_public_key).await).is_some() {
|
||||||
return ServerEvent::message("You have already sent a chat request to this user.");
|
return ServerEvent::message("You have already sent a chat request to this user.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,3 +75,60 @@ pub async fn handle_chat_request(
|
||||||
}
|
}
|
||||||
ServerEvent::message("Chat request sent successfully.")
|
ServerEvent::message("Chat request sent successfully.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_chat_response(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
recipient: Option<&UserModel>,
|
||||||
|
sender_public_key: &PublicKey,
|
||||||
|
accepted: bool,
|
||||||
|
) -> ServerEvent<Unsigned> {
|
||||||
|
let Some(recipient_user) = recipient else {
|
||||||
|
return WsError::RegistredUserEvent.into();
|
||||||
|
};
|
||||||
|
let Some(sender_user) = try_ws!(db.get_user_by_pubk(sender_public_key).await) else {
|
||||||
|
return WsError::UserNotFound.into();
|
||||||
|
};
|
||||||
|
if recipient_user.id == sender_user.id {
|
||||||
|
return WsError::CannotRespondToOwnChatRequest.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: When change the entity public key to a PublicKey type, change this
|
||||||
|
let recipient_public_key =
|
||||||
|
PublicKey::from_str(&recipient_user.public_key).expect("Is valid public key");
|
||||||
|
|
||||||
|
if try_ws!(
|
||||||
|
db.have_chat_request_to(&sender_user, &recipient_public_key)
|
||||||
|
.await
|
||||||
|
)
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
return WsError::NoChatRequestFromRecipient.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(conn_id) = ONLINE_USERS.is_online(sender_public_key).await {
|
||||||
|
ONLINE_USERS
|
||||||
|
.send(
|
||||||
|
&conn_id,
|
||||||
|
ServerEvent::chat_request_response(recipient_public_key, accepted),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
// TODO: Create a table for chat request responses, and send them when
|
||||||
|
// the user logs in
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't need to handle the case where the sender is blacklisted or
|
||||||
|
// whitelisted already, just add it if it is not already there
|
||||||
|
let _ = if accepted {
|
||||||
|
db.add_to_whitelist(recipient_user, sender_public_key).await
|
||||||
|
} else {
|
||||||
|
db.add_to_blacklist(recipient_user, sender_public_key).await
|
||||||
|
};
|
||||||
|
|
||||||
|
try_ws!(
|
||||||
|
db.remove_out_chat_request(&sender_user, &recipient_public_key)
|
||||||
|
.await
|
||||||
|
);
|
||||||
|
|
||||||
|
ServerEvent::message("Chat request response sent successfully.")
|
||||||
|
}
|
||||||
|
|
|
@ -219,6 +219,9 @@ async fn handle_events(
|
||||||
ClientEventType::ChatRequest { to } => {
|
ClientEventType::ChatRequest { to } => {
|
||||||
Some(handlers::handle_chat_request(db, user, to).await)
|
Some(handlers::handle_chat_request(db, user, to).await)
|
||||||
}
|
}
|
||||||
|
ClientEventType::ChatRequestResponse { to, accepted } => {
|
||||||
|
Some(handlers::handle_chat_response(db, user, to, *accepted).await)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue