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
|
||||
|
||||
use chrono::Utc;
|
||||
use oxidetalis_core::types::PublicKey;
|
||||
use oxidetalis_entities::prelude::*;
|
||||
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
|
||||
/// table
|
||||
|
@ -32,6 +33,12 @@ pub trait BlackListExt {
|
|||
blacklister: &UserModel,
|
||||
target_public_key: &PublicKey,
|
||||
) -> 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 {
|
||||
|
@ -49,4 +56,26 @@ impl BlackListExt for DatabaseConnection {
|
|||
.map(|u| u.is_some())
|
||||
.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,
|
||||
requester: &UserModel,
|
||||
recipient: &PublicKey,
|
||||
) -> ServerResult<bool>;
|
||||
) -> ServerResult<Option<OutChatRequestsModel>>;
|
||||
|
||||
/// Save the chat request in the requester table
|
||||
async fn save_out_chat_request(
|
||||
|
@ -38,6 +38,13 @@ pub trait OutChatRequestsExt {
|
|||
requester: &UserModel,
|
||||
recipient: &PublicKey,
|
||||
) -> ServerResult<()>;
|
||||
|
||||
/// Remove the chat request from requester table
|
||||
async fn remove_out_chat_request(
|
||||
&self,
|
||||
requester: &UserModel,
|
||||
recipient: &PublicKey,
|
||||
) -> ServerResult<()>;
|
||||
}
|
||||
|
||||
impl OutChatRequestsExt for DatabaseConnection {
|
||||
|
@ -46,13 +53,12 @@ impl OutChatRequestsExt for DatabaseConnection {
|
|||
&self,
|
||||
requester: &UserModel,
|
||||
recipient: &PublicKey,
|
||||
) -> ServerResult<bool> {
|
||||
) -> ServerResult<Option<OutChatRequestsModel>> {
|
||||
requester
|
||||
.find_related(OutChatRequestsEntity)
|
||||
.filter(OutChatRequestsColumn::Recipient.eq(recipient.to_string()))
|
||||
.one(self)
|
||||
.await
|
||||
.map(|user| user.is_some())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
|
@ -62,7 +68,11 @@ impl OutChatRequestsExt for DatabaseConnection {
|
|||
requester: &UserModel,
|
||||
recipient: &PublicKey,
|
||||
) -> 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());
|
||||
}
|
||||
OutChatRequestsActiveModel {
|
||||
|
@ -75,4 +85,15 @@ impl OutChatRequestsExt for DatabaseConnection {
|
|||
.await?;
|
||||
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",
|
||||
UserNotFound = "The user is not registered in the server",
|
||||
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",
|
||||
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,
|
||||
}
|
||||
|
||||
// ## Important for contuributors
|
||||
// Please make sure to order the event data alphabetically.
|
||||
|
||||
/// Client websocket event type
|
||||
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
|
||||
#[serde(rename_all = "PascalCase", tag = "event", content = "data")]
|
||||
|
@ -39,6 +42,8 @@ pub enum ClientEventType {
|
|||
Pong { timestamp: u64 },
|
||||
/// Request to chat with a user
|
||||
ChatRequest { to: PublicKey },
|
||||
/// Response to a chat request
|
||||
ChatRequestResponse { accepted: bool, to: PublicKey },
|
||||
}
|
||||
|
||||
impl ClientEventType {
|
||||
|
|
|
@ -55,6 +55,8 @@ pub enum ServerEventType {
|
|||
Message { msg: String },
|
||||
/// New chat request from someone
|
||||
ChatRequest { from: PublicKey },
|
||||
/// New chat request response from someone
|
||||
ChatRequestResponse { from: PublicKey, accepted: bool },
|
||||
/// Error event
|
||||
Error {
|
||||
name: &'static str,
|
||||
|
@ -105,6 +107,11 @@ impl ServerEvent<Unsigned> {
|
|||
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
|
||||
pub fn sign(self, shared_secret: &[u8; 32]) -> 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.",
|
||||
);
|
||||
}
|
||||
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.");
|
||||
}
|
||||
|
||||
|
@ -75,3 +75,60 @@ pub async fn handle_chat_request(
|
|||
}
|
||||
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 } => {
|
||||
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