From 90cd947e717947efb02f60a4e18a0c494fac2c9e Mon Sep 17 00:00:00 2001
From: Awiteb
Date: Fri, 12 Jul 2024 22:51:57 +0300
Subject: [PATCH] feat: New tables utils
The tables is:
- `blacklist`
- `incoming_chat_requests`
- `whitelist`
- `outgoing_chat_requests`
Signed-off-by: Awiteb
---
crates/oxidetalis/src/database/blacklist.rs | 52 +++++++++++
.../src/database/in_chat_requests.rs | 66 ++++++++++++++
crates/oxidetalis/src/database/mod.rs | 8 ++
.../src/database/out_chat_requests.rs | 86 ++++++++++++++++++
crates/oxidetalis/src/database/whitelist.rs | 89 +++++++++++++++++++
5 files changed, 301 insertions(+)
create mode 100644 crates/oxidetalis/src/database/blacklist.rs
create mode 100644 crates/oxidetalis/src/database/in_chat_requests.rs
create mode 100644 crates/oxidetalis/src/database/out_chat_requests.rs
create mode 100644 crates/oxidetalis/src/database/whitelist.rs
diff --git a/crates/oxidetalis/src/database/blacklist.rs b/crates/oxidetalis/src/database/blacklist.rs
new file mode 100644
index 0000000..a35eccb
--- /dev/null
+++ b/crates/oxidetalis/src/database/blacklist.rs
@@ -0,0 +1,52 @@
+// OxideTalis Messaging Protocol homeserver implementation
+// Copyright (C) 2024 OxideTalis Developers
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//! Database extension to work with the balcklist table
+
+use oxidetalis_core::types::PublicKey;
+use oxidetalis_entities::prelude::*;
+use sea_orm::DatabaseConnection;
+
+use crate::errors::ApiResult;
+
+/// Extension trait for the `DatabaseConnection` to work with the blacklist
+/// table
+pub trait BlackListExt {
+ /// Returns ture if the `blacklister` are blacklisted the
+ /// `target_public_key`
+ async fn is_blacklisted(
+ &self,
+ blacklister: &UserModel,
+ target_public_key: &PublicKey,
+ ) -> ApiResult;
+}
+
+impl BlackListExt for DatabaseConnection {
+ #[logcall::logcall]
+ async fn is_blacklisted(
+ &self,
+ blacklister: &UserModel,
+ target_public_key: &PublicKey,
+ ) -> ApiResult {
+ blacklister
+ .find_related(BlacklistEntity)
+ .filter(BlacklistColumn::Target.eq(target_public_key.to_string()))
+ .one(self)
+ .await
+ .map(|u| u.is_some())
+ .map_err(Into::into)
+ }
+}
diff --git a/crates/oxidetalis/src/database/in_chat_requests.rs b/crates/oxidetalis/src/database/in_chat_requests.rs
new file mode 100644
index 0000000..137fee3
--- /dev/null
+++ b/crates/oxidetalis/src/database/in_chat_requests.rs
@@ -0,0 +1,66 @@
+// OxideTalis Messaging Protocol homeserver implementation
+// Copyright (C) 2024 OxideTalis Developers
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//! Database extension for the `in_chat_requests` table.
+
+use chrono::Utc;
+use oxidetalis_core::types::PublicKey;
+use oxidetalis_entities::prelude::*;
+use sea_orm::DatabaseConnection;
+
+use crate::websocket::errors::{WsError, WsResult};
+
+/// Extension trait for the `in_chat_requests` table.
+pub trait InChatRequestsExt {
+ /// Save the chat request in the recipient table
+ async fn save_in_chat_request(
+ &self,
+ requester: &PublicKey,
+ recipient: &UserModel,
+ ) -> WsResult<()>;
+}
+
+impl InChatRequestsExt for DatabaseConnection {
+ #[logcall::logcall]
+ async fn save_in_chat_request(
+ &self,
+ sender: &PublicKey,
+ recipient: &UserModel,
+ ) -> WsResult<()> {
+ if sender.to_string() == recipient.public_key {
+ return Err(WsError::CannotSendChatRequestToSelf);
+ }
+ if recipient
+ .find_related(InChatRequestsEntity)
+ .filter(InChatRequestsColumn::Sender.eq(sender.to_string()))
+ .one(self)
+ .await
+ .map_err(|_| WsError::InternalServerError)?
+ .is_none()
+ {
+ InChatRequestsActiveModel {
+ recipient_id: Set(recipient.id),
+ sender: Set(sender.to_string()),
+ in_on: Set(Utc::now()),
+ ..Default::default()
+ }
+ .save(self)
+ .await
+ .map_err(|_| WsError::InternalServerError)?;
+ }
+ Ok(())
+ }
+}
diff --git a/crates/oxidetalis/src/database/mod.rs b/crates/oxidetalis/src/database/mod.rs
index a9578ae..dc03f6a 100644
--- a/crates/oxidetalis/src/database/mod.rs
+++ b/crates/oxidetalis/src/database/mod.rs
@@ -16,6 +16,14 @@
//! Database utilities for the OxideTalis homeserver.
+mod blacklist;
+mod in_chat_requests;
+mod out_chat_requests;
mod user;
+mod whitelist;
+pub use blacklist::*;
+pub use in_chat_requests::*;
+pub use out_chat_requests::*;
pub use user::*;
+pub use whitelist::*;
diff --git a/crates/oxidetalis/src/database/out_chat_requests.rs b/crates/oxidetalis/src/database/out_chat_requests.rs
new file mode 100644
index 0000000..b687997
--- /dev/null
+++ b/crates/oxidetalis/src/database/out_chat_requests.rs
@@ -0,0 +1,86 @@
+// OxideTalis Messaging Protocol homeserver implementation
+// Copyright (C) 2024 OxideTalis Developers
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//! Database extension for the `out_chat_requests` table.
+
+use chrono::Utc;
+use oxidetalis_core::types::PublicKey;
+use oxidetalis_entities::prelude::*;
+use sea_orm::DatabaseConnection;
+
+use crate::{
+ errors::ApiResult,
+ websocket::errors::{WsError, WsResult},
+};
+
+/// Extension trait for the `out_chat_requests` table.
+pub trait OutChatRequestsExt {
+ /// Returns true if the `user` have a sended chat request to the `recipient`
+ async fn have_chat_request_to(
+ &self,
+ requester: &UserModel,
+ recipient: &PublicKey,
+ ) -> ApiResult;
+
+ /// Save the chat request in the requester table
+ async fn save_out_chat_request(
+ &self,
+ requester: &UserModel,
+ recipient: &PublicKey,
+ ) -> WsResult<()>;
+}
+
+impl OutChatRequestsExt for DatabaseConnection {
+ #[logcall::logcall]
+ async fn have_chat_request_to(
+ &self,
+ requester: &UserModel,
+ recipient: &PublicKey,
+ ) -> ApiResult {
+ requester
+ .find_related(OutChatRequestsEntity)
+ .filter(OutChatRequestsColumn::Recipient.eq(recipient.to_string()))
+ .one(self)
+ .await
+ .map(|user| user.is_some())
+ .map_err(Into::into)
+ }
+
+ #[logcall::logcall]
+ async fn save_out_chat_request(
+ &self,
+ requester: &UserModel,
+ recipient: &PublicKey,
+ ) -> WsResult<()> {
+ if self
+ .have_chat_request_to(requester, recipient)
+ .await
+ .map_err(|_| WsError::InternalServerError)?
+ {
+ return Err(WsError::AlreadySendChatRequest);
+ }
+ OutChatRequestsActiveModel {
+ sender_id: Set(requester.id),
+ recipient: Set(recipient.to_string()),
+ out_on: Set(Utc::now()),
+ ..Default::default()
+ }
+ .save(self)
+ .await
+ .map_err(|_| WsError::InternalServerError)?;
+ Ok(())
+ }
+}
diff --git a/crates/oxidetalis/src/database/whitelist.rs b/crates/oxidetalis/src/database/whitelist.rs
new file mode 100644
index 0000000..7a810d2
--- /dev/null
+++ b/crates/oxidetalis/src/database/whitelist.rs
@@ -0,0 +1,89 @@
+// OxideTalis Messaging Protocol homeserver implementation
+// Copyright (C) 2024 OxideTalis Developers
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//! 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::ApiResult,
+ websocket::errors::{WsError, WsResult},
+};
+
+/// Extension trait for the `DatabaseConnection` to work with the whitelist
+/// table
+pub trait WhiteListExt {
+ /// Returns ture if the `whitelister` are whitelisted the
+ /// `target_public_key`
+ async fn is_whitelisted(
+ &self,
+ whitelister: &UserModel,
+ target_public_key: &PublicKey,
+ ) -> ApiResult;
+
+ /// Add the `target_public_key` to the whitelist of the `whitelister`
+ async fn add_to_whitelist(
+ &self,
+ whitelister: &UserModel,
+ target_public_key: &PublicKey,
+ ) -> WsResult<()>;
+}
+
+impl WhiteListExt for DatabaseConnection {
+ async fn is_whitelisted(
+ &self,
+ whitelister: &UserModel,
+ target_public_key: &PublicKey,
+ ) -> ApiResult {
+ whitelister
+ .find_related(WhitelistEntity)
+ .filter(WhitelistColumn::Target.eq(target_public_key.to_string()))
+ .one(self)
+ .await
+ .map(|u| u.is_some())
+ .map_err(Into::into)
+ }
+
+ async fn add_to_whitelist(
+ &self,
+ whitelister: &UserModel,
+ target_public_key: &PublicKey,
+ ) -> WsResult<()> {
+ if self
+ .is_whitelisted(whitelister, target_public_key)
+ .await
+ .map_err(|_| WsError::InternalServerError)?
+ {
+ return Err(WsError::AlreadyOnTheWhitelist);
+ }
+ if whitelister.public_key == target_public_key.to_string() {
+ return Err(WsError::CannotAddSelfToWhitelist);
+ }
+ WhitelistActiveModel {
+ user_id: Set(whitelister.id),
+ target: Set(target_public_key.to_string()),
+ whitelisted_at: Set(Utc::now()),
+ ..Default::default()
+ }
+ .save(self)
+ .await
+ .map_err(|_| WsError::InternalServerError)?;
+ Ok(())
+ }
+}