feat: Chat request implementation #14
5 changed files with 301 additions and 0 deletions
52
crates/oxidetalis/src/database/blacklist.rs
Normal file
52
crates/oxidetalis/src/database/blacklist.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// OxideTalis Messaging Protocol homeserver implementation
|
||||||
|
// Copyright (C) 2024 OxideTalis Developers <otmp@4rs.nl>
|
||||||
|
//
|
||||||
|
// 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 <https://gnu.org/licenses/agpl-3.0>.
|
||||||
|
|
||||||
|
//! 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,
|
||||||
awiteb marked this conversation as resolved
|
|||||||
|
target_public_key: &PublicKey,
|
||||||
|
) -> ApiResult<bool>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlackListExt for DatabaseConnection {
|
||||||
|
#[logcall::logcall]
|
||||||
|
async fn is_blacklisted(
|
||||||
|
&self,
|
||||||
|
blacklister: &UserModel,
|
||||||
|
target_public_key: &PublicKey,
|
||||||
|
) -> ApiResult<bool> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
66
crates/oxidetalis/src/database/in_chat_requests.rs
Normal file
66
crates/oxidetalis/src/database/in_chat_requests.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// OxideTalis Messaging Protocol homeserver implementation
|
||||||
|
// Copyright (C) 2024 OxideTalis Developers <otmp@4rs.nl>
|
||||||
|
//
|
||||||
|
// 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 <https://gnu.org/licenses/agpl-3.0>.
|
||||||
|
|
||||||
|
//! 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()))
|
||||||
awiteb marked this conversation as resolved
Amjad50
commented
since we are not dealing with the result. maybe a one statement approach to do
here i'm updating since we are not dealing with the result. maybe a one statement approach to do
```rust
InChatRequestsEntity::insert(InChatRequestsActiveModel {
recipient_id: Set(recipient.id),
sender: Set(sender.to_string()),
in_on: Set(Utc::now()),
..Default::default()
})
.on_conflict(
OnConflict::columns([
InChatRequestsColumn::RecipientId,
InChatRequestsColumn::Sender,
])
.update_column(InChatRequestsColumn::InOn)
.to_owned(),
)
.exec(self)
```
here i'm updating `InOn` if needed, but can also be changed to `do_nothing()`
|
|||||||
|
.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(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,14 @@
|
||||||
|
|
||||||
//! Database utilities for the OxideTalis homeserver.
|
//! Database utilities for the OxideTalis homeserver.
|
||||||
|
|
||||||
|
mod blacklist;
|
||||||
|
mod in_chat_requests;
|
||||||
|
mod out_chat_requests;
|
||||||
mod user;
|
mod user;
|
||||||
|
mod whitelist;
|
||||||
|
|
||||||
|
pub use blacklist::*;
|
||||||
|
pub use in_chat_requests::*;
|
||||||
|
pub use out_chat_requests::*;
|
||||||
pub use user::*;
|
pub use user::*;
|
||||||
|
pub use whitelist::*;
|
||||||
|
|
86
crates/oxidetalis/src/database/out_chat_requests.rs
Normal file
86
crates/oxidetalis/src/database/out_chat_requests.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// OxideTalis Messaging Protocol homeserver implementation
|
||||||
|
// Copyright (C) 2024 OxideTalis Developers <otmp@4rs.nl>
|
||||||
|
//
|
||||||
|
// 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 <https://gnu.org/licenses/agpl-3.0>.
|
||||||
|
|
||||||
|
//! 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,
|
||||||
awiteb marked this conversation as resolved
Amjad50
commented
should return should return `true` based on the name and description of the func
Amjad50
commented
small nitpick (also applies to small nitpick (also applies to `have_chat_request_to` below)
I would name it `get_chat_request_to`, as `have` seems that it would be boolean
|
|||||||
|
requester: &UserModel,
|
||||||
|
recipient: &PublicKey,
|
||||||
|
) -> ApiResult<bool>;
|
||||||
|
|
||||||
|
/// 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<bool> {
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
89
crates/oxidetalis/src/database/whitelist.rs
Normal file
89
crates/oxidetalis/src/database/whitelist.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// OxideTalis Messaging Protocol homeserver implementation
|
||||||
|
// Copyright (C) 2024 OxideTalis Developers <otmp@4rs.nl>
|
||||||
|
//
|
||||||
|
// 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 <https://gnu.org/licenses/agpl-3.0>.
|
||||||
|
|
||||||
|
//! 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
|
||||||
awiteb marked this conversation as resolved
Amjad50
commented
ture ture
The whitelister has whitelisted
|
|||||||
|
/// `target_public_key`
|
||||||
|
async fn is_whitelisted(
|
||||||
|
&self,
|
||||||
|
whitelister: &UserModel,
|
||||||
|
target_public_key: &PublicKey,
|
||||||
|
) -> ApiResult<bool>;
|
||||||
|
|
||||||
|
/// 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<bool> {
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue
ture
->true
(use find and replace all, there are multiple of these)blacklister has blacklisted