feat: Replace whitelist & blacklist tables with users_status table

Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
Awiteb 2024-07-17 18:34:39 +03:00
parent a894089b19
commit 3d086e511c
Signed by: awiteb
GPG key ID: 3F6B55640AA6682F
15 changed files with 383 additions and 443 deletions

View file

@ -1,135 +0,0 @@
// 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 blacklist table
use std::num::{NonZeroU32, NonZeroU8};
use chrono::Utc;
use oxidetalis_core::types::PublicKey;
use oxidetalis_entities::prelude::*;
use sea_orm::DatabaseConnection;
use super::WhiteListExt;
use crate::{errors::ServerResult, websocket::errors::WsError};
/// 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,
) -> ServerResult<bool>;
/// Add the `target_public_key` to the blacklist of the `blacklister` and
/// remove it from the whitelist table (if it's there)
async fn add_to_blacklist(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Remove the target from blacklist table
async fn remove_from_blacklist(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Returns the blacklist of the user
async fn user_blacklist(
&self,
blacklister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<BlacklistModel>>;
}
impl BlackListExt for DatabaseConnection {
#[logcall::logcall]
async fn is_blacklisted(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<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)
}
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());
}
self.remove_from_whitelist(blacklister, target_public_key)
.await?;
BlacklistActiveModel {
user_id: Set(blacklister.id),
target: Set(target_public_key.to_string()),
blacklisted_at: Set(Utc::now()),
..Default::default()
}
.save(self)
.await?;
Ok(())
}
async fn remove_from_blacklist(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
if let Some(target_user) = blacklister
.find_related(BlacklistEntity)
.filter(BlacklistColumn::Target.eq(target_public_key.to_string()))
.one(self)
.await?
{
target_user.delete(self).await?;
}
Ok(())
}
async fn user_blacklist(
&self,
blacklister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<BlacklistModel>> {
blacklister
.find_related(BlacklistEntity)
.select()
.paginate(self, u64::from(page_size.get()))
.fetch_page(u64::from(page.get() - 1))
.await
.map_err(Into::into)
}
}

View file

@ -16,14 +16,12 @@
//! Database utilities for the OxideTalis homeserver. //! Database utilities for the OxideTalis homeserver.
mod blacklist;
mod in_chat_requests; mod in_chat_requests;
mod out_chat_requests; mod out_chat_requests;
mod user; mod user;
mod whitelist; mod user_status;
pub use blacklist::*;
pub use in_chat_requests::*; pub use in_chat_requests::*;
pub use out_chat_requests::*; pub use out_chat_requests::*;
pub use user::*; pub use user::*;
pub use whitelist::*; pub use user_status::*;

View file

@ -0,0 +1,287 @@
// 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 whitelist table
use std::num::{NonZeroU32, NonZeroU8};
use chrono::Utc;
use oxidetalis_core::types::PublicKey;
use oxidetalis_entities::prelude::*;
use sea_orm::DatabaseConnection;
use crate::{errors::ServerResult, websocket::errors::WsError};
/// Extension trait for the `DatabaseConnection` to work with the whitelist
/// table
pub trait UsersStatusExt {
/// Returns ture if the `whitelister` are whitelisted the
/// `target_public_key`
async fn is_whitelisted(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<bool>;
/// Returns ture if the `blacklister` are blacklisted the
/// `target_public_key`
async fn is_blacklisted(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<bool>;
/// Add the `target_public_key` to the whitelist of the `whitelister` and
/// remove it from the blacklist table (if it's there)
async fn add_to_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Add the `target_public_key` to the blacklist of the `blacklister` and
/// remove it from the whitelist table (if it's there)
async fn add_to_blacklist(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Remove the target from whitelist table
// FIXME(awiteb): This method will be used when I work on decentralization, So, I'm keeping it
// for now
#[allow(dead_code)]
async fn remove_from_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Remove the target from blacklist table
// FIXME(awiteb): This method will be used when I work on decentralization, So, I'm keeping it
// for now
#[allow(dead_code)]
async fn remove_from_blacklist(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Returns the whitelist of the user
async fn user_whitelist(
&self,
whitelister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<UsersStatusModel>>;
/// Returns the blacklist of the user
async fn user_blacklist(
&self,
blacklister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<UsersStatusModel>>;
}
impl UsersStatusExt for DatabaseConnection {
async fn is_whitelisted(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<bool> {
whitelister
.find_related(UsersStatusEntity)
.filter(
UsersStatusColumn::Target
.eq(target_public_key.to_string())
.and(UsersStatusColumn::Status.eq(AccessStatus::Whitelisted)),
)
.one(self)
.await
.map(|u| u.is_some())
.map_err(Into::into)
}
async fn is_blacklisted(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<bool> {
blacklister
.find_related(UsersStatusEntity)
.filter(
UsersStatusColumn::Target
.eq(target_public_key.to_string())
.and(UsersStatusColumn::Status.eq(AccessStatus::Blacklisted)),
)
.one(self)
.await
.map(|u| u.is_some())
.map_err(Into::into)
}
async fn add_to_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
if self.is_whitelisted(whitelister, target_public_key).await? {
return Err(WsError::AlreadyOnTheWhitelist.into());
}
if whitelister.public_key == target_public_key.to_string() {
return Err(WsError::CannotAddSelfToWhitelist.into());
}
if let Some(mut user) = get_user_status(self, whitelister, target_public_key)
.await?
.map(IntoActiveModel::into_active_model)
{
user.status = Set(AccessStatus::Whitelisted);
user.updated_at = Set(Utc::now());
user.update(self).await?;
} else {
UsersStatusActiveModel {
user_id: Set(whitelister.id),
target: Set(target_public_key.to_string()),
status: Set(AccessStatus::Whitelisted),
updated_at: Set(Utc::now()),
..Default::default()
}
.save(self)
.await?;
}
Ok(())
}
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());
}
if let Some(mut user) = get_user_status(self, blacklister, target_public_key)
.await?
.map(IntoActiveModel::into_active_model)
{
user.status = Set(AccessStatus::Blacklisted);
user.updated_at = Set(Utc::now());
user.update(self).await?;
} else {
UsersStatusActiveModel {
user_id: Set(blacklister.id),
target: Set(target_public_key.to_string()),
status: Set(AccessStatus::Blacklisted),
updated_at: Set(Utc::now()),
..Default::default()
}
.save(self)
.await?;
}
Ok(())
}
async fn remove_from_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
if let Some(target_user) = whitelister
.find_related(UsersStatusEntity)
.filter(
UsersStatusColumn::Target
.eq(target_public_key.to_string())
.and(UsersStatusColumn::Status.eq(AccessStatus::Whitelisted)),
)
.one(self)
.await?
{
target_user.delete(self).await?;
}
Ok(())
}
async fn remove_from_blacklist(
&self,
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
if let Some(target_user) = blacklister
.find_related(UsersStatusEntity)
.filter(
UsersStatusColumn::Target
.eq(target_public_key.to_string())
.and(UsersStatusColumn::Status.eq(AccessStatus::Blacklisted)),
)
.one(self)
.await?
{
target_user.delete(self).await?;
}
Ok(())
}
async fn user_whitelist(
&self,
whitelister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<UsersStatusModel>> {
whitelister
.find_related(UsersStatusEntity)
.filter(UsersStatusColumn::Status.eq(AccessStatus::Whitelisted))
.paginate(self, u64::from(page_size.get()))
.fetch_page(u64::from(page.get() - 1))
.await
.map_err(Into::into)
}
async fn user_blacklist(
&self,
blacklister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<UsersStatusModel>> {
blacklister
.find_related(UsersStatusEntity)
.filter(UsersStatusColumn::Status.eq(AccessStatus::Blacklisted))
.paginate(self, u64::from(page_size.get()))
.fetch_page(u64::from(page.get() - 1))
.await
.map_err(Into::into)
}
}
/// Returns user from user_status table by the entered and target public key
async fn get_user_status(
conn: &DatabaseConnection,
user: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<Option<UsersStatusModel>> {
user.find_related(UsersStatusEntity)
.filter(UsersStatusColumn::Target.eq(target_public_key.to_string()))
.one(conn)
.await
.map_err(Into::into)
}

View file

@ -1,134 +0,0 @@
// 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 whitelist table
use std::num::{NonZeroU32, NonZeroU8};
use chrono::Utc;
use oxidetalis_core::types::PublicKey;
use oxidetalis_entities::prelude::*;
use sea_orm::DatabaseConnection;
use super::BlackListExt;
use crate::{errors::ServerResult, websocket::errors::WsError};
/// 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,
) -> ServerResult<bool>;
/// Add the `target_public_key` to the whitelist of the `whitelister` and
/// remove it from the blacklist table (if it's there)
async fn add_to_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Remove the target from whitelist table
async fn remove_from_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()>;
/// Returns the whitelist of the user
async fn user_whitelist(
&self,
whitelister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<WhitelistModel>>;
}
impl WhiteListExt for DatabaseConnection {
async fn is_whitelisted(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<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,
) -> ServerResult<()> {
if self.is_whitelisted(whitelister, target_public_key).await? {
return Err(WsError::AlreadyOnTheWhitelist.into());
}
if whitelister.public_key == target_public_key.to_string() {
return Err(WsError::CannotAddSelfToWhitelist.into());
}
self.remove_from_blacklist(whitelister, target_public_key)
.await?;
WhitelistActiveModel {
user_id: Set(whitelister.id),
target: Set(target_public_key.to_string()),
whitelisted_at: Set(Utc::now()),
..Default::default()
}
.save(self)
.await?;
Ok(())
}
async fn remove_from_whitelist(
&self,
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
if let Some(target_user) = whitelister
.find_related(WhitelistEntity)
.filter(WhitelistColumn::Target.eq(target_public_key.to_string()))
.one(self)
.await?
{
target_user.delete(self).await?;
}
Ok(())
}
async fn user_whitelist(
&self,
whitelister: &UserModel,
page: NonZeroU32,
page_size: NonZeroU8,
) -> ServerResult<Vec<WhitelistModel>> {
whitelister
.find_related(WhitelistEntity)
.select()
.paginate(self, u64::from(page_size.get()))
.fetch_page(u64::from(page.get() - 1))
.await
.map_err(Into::into)
}
}

View file

@ -30,7 +30,7 @@ use salvo::{
use super::{ApiError, ApiResult}; use super::{ApiError, ApiResult};
use crate::{ use crate::{
database::{BlackListExt, UserTableExt, WhiteListExt}, database::{UserTableExt, UsersStatusExt},
extensions::DepotExt, extensions::DepotExt,
middlewares, middlewares,
parameters::Pagination, parameters::Pagination,

View file

@ -57,11 +57,11 @@ impl Default for WhiteListedUser {
} }
} }
impl From<WhitelistModel> for WhiteListedUser { impl From<UsersStatusModel> for WhiteListedUser {
fn from(user: WhitelistModel) -> Self { fn from(user: UsersStatusModel) -> Self {
Self { Self {
public_key: PublicKey::from_str(&user.target).expect("Is valid public key"), public_key: PublicKey::from_str(&user.target).expect("Is valid public key"),
whitelisted_at: user.whitelisted_at, whitelisted_at: user.updated_at,
} }
} }
} }
@ -75,11 +75,11 @@ impl Default for BlackListedUser {
} }
} }
impl From<BlacklistModel> for BlackListedUser { impl From<UsersStatusModel> for BlackListedUser {
fn from(user: BlacklistModel) -> Self { fn from(user: UsersStatusModel) -> Self {
Self { Self {
public_key: PublicKey::from_str(&user.target).expect("Is valid public key"), public_key: PublicKey::from_str(&user.target).expect("Is valid public key"),
blacklisted_at: user.blacklisted_at, blacklisted_at: user.updated_at,
} }
} }
} }

View file

@ -25,7 +25,7 @@ use sea_orm::DatabaseConnection;
use crate::database::InChatRequestsExt; use crate::database::InChatRequestsExt;
use crate::extensions::OnlineUsersExt; use crate::extensions::OnlineUsersExt;
use crate::{ use crate::{
database::{BlackListExt, OutChatRequestsExt, UserTableExt, WhiteListExt}, database::{OutChatRequestsExt, UserTableExt, UsersStatusExt},
try_ws, try_ws,
websocket::{errors::WsError, ServerEvent, Unsigned, ONLINE_USERS}, websocket::{errors::WsError, ServerEvent, Unsigned, ONLINE_USERS},
}; };

View file

@ -19,9 +19,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
pub mod blacklist;
pub mod incoming_chat_requests; pub mod incoming_chat_requests;
pub mod outgoing_chat_requests; pub mod outgoing_chat_requests;
pub mod prelude; pub mod prelude;
pub mod users; pub mod users;
pub mod whitelist; pub mod users_status;

View file

@ -38,12 +38,6 @@ pub use sea_orm::{
/// User ID type /// User ID type
pub type UserId = i64; pub type UserId = i64;
pub use super::blacklist::{
ActiveModel as BlacklistActiveModel,
Column as BlacklistColumn,
Entity as BlacklistEntity,
Model as BlacklistModel,
};
pub use super::incoming_chat_requests::{ pub use super::incoming_chat_requests::{
ActiveModel as InChatRequestsActiveModel, ActiveModel as InChatRequestsActiveModel,
Column as InChatRequestsColumn, Column as InChatRequestsColumn,
@ -62,9 +56,10 @@ pub use super::users::{
Entity as UserEntity, Entity as UserEntity,
Model as UserModel, Model as UserModel,
}; };
pub use super::whitelist::{ pub use super::users_status::{
ActiveModel as WhitelistActiveModel, AccessStatus,
Column as WhitelistColumn, ActiveModel as UsersStatusActiveModel,
Entity as WhitelistEntity, Column as UsersStatusColumn,
Model as WhitelistModel, Entity as UsersStatusEntity,
Model as UsersStatusModel,
}; };

View file

@ -38,10 +38,8 @@ pub enum Relation {
InChatRequests, InChatRequests,
#[sea_orm(has_many = "OutChatRequestsEntity")] #[sea_orm(has_many = "OutChatRequestsEntity")]
OutChatRequests, OutChatRequests,
#[sea_orm(has_many = "BlacklistEntity")] #[sea_orm(has_many = "UsersStatusEntity")]
Blacklist, UsersStatus,
#[sea_orm(has_many = "WhitelistEntity")]
Whitelist,
} }
impl Related<InChatRequestsEntity> for Entity { impl Related<InChatRequestsEntity> for Entity {
@ -56,15 +54,9 @@ impl Related<OutChatRequestsEntity> for Entity {
} }
} }
impl Related<BlacklistEntity> for Entity { impl Related<UsersStatusEntity> for Entity {
fn to() -> RelationDef { fn to() -> RelationDef {
Relation::Blacklist.def() Relation::UsersStatus.def()
}
}
impl Related<WhitelistEntity> for Entity {
fn to() -> RelationDef {
Relation::Whitelist.def()
} }
} }

View file

@ -24,15 +24,25 @@ use sea_orm::entity::prelude::*;
use crate::prelude::*; use crate::prelude::*;
#[derive(Debug, Clone, Eq, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "access_status")]
pub enum AccessStatus {
#[sea_orm(string_value = "whitelisted")]
Whitelisted,
#[sea_orm(string_value = "blacklisted")]
Blacklisted,
}
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "blacklist")] #[sea_orm(table_name = "users_status")]
pub struct Model { pub struct Model {
#[sea_orm(primary_key)] #[sea_orm(primary_key)]
pub id: UserId, pub id: UserId,
pub user_id: UserId, pub user_id: UserId,
/// Public key of the target /// Public key of the target
pub target: String, pub target: String,
pub blacklisted_at: chrono::DateTime<Utc>, pub status: AccessStatus,
pub updated_at: chrono::DateTime<Utc>,
} }
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View file

@ -1,56 +0,0 @@
// OxideTalis Messaging Protocol homeserver core implementation
// Copyright (c) 2024 OxideTalis Developers <otmp@4rs.nl>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use chrono::Utc;
use sea_orm::entity::prelude::*;
use crate::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "whitelist")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: UserId,
pub user_id: UserId,
/// Public key of the target
pub target: String,
pub whitelisted_at: chrono::DateTime<Utc>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "UserEntity",
from = "Column::UserId",
to = "super::users::Column::Id"
on_update = "NoAction",
on_delete = "Cascade"
)]
UserId,
}
impl Related<UserEntity> for Entity {
fn to() -> RelationDef {
Relation::UserId.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View file

@ -19,31 +19,59 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
use std::fmt;
use sea_orm::sea_query::extension::postgres::Type;
use sea_orm_migration::prelude::*; use sea_orm_migration::prelude::*;
use super::create_users_table::Users;
#[derive(DeriveMigrationName)] #[derive(DeriveMigrationName)]
pub struct Migration; pub struct Migration;
#[async_trait::async_trait] #[async_trait::async_trait]
impl MigrationTrait for Migration { impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_type(
Type::create()
.as_enum(AccessStatus::Name)
.values(vec![AccessStatus::Whitelisted, AccessStatus::Blacklisted])
.to_owned(),
)
.await?;
manager manager
.create_table( .create_table(
Table::create() Table::create()
.table(Blacklist::Table) .table(UsersStatus::Table)
.if_not_exists() .if_not_exists()
.col( .col(
ColumnDef::new(Blacklist::Id) ColumnDef::new(UsersStatus::Id)
.big_integer() .big_integer()
.not_null() .not_null()
.auto_increment() .auto_increment()
.primary_key(), .primary_key(),
) )
.col(ColumnDef::new(Blacklist::UserId).big_integer().not_null()) .foreign_key(
.col(ColumnDef::new(Blacklist::Target).string().not_null()) ForeignKey::create()
.col(ColumnDef::new(Blacklist::Reason).string_len(400)) .name("fk-users_status-users")
.from(UsersStatus::Table, UsersStatus::UserId)
.to(Users::Table, Users::Id)
.on_update(ForeignKeyAction::NoAction)
.on_delete(ForeignKeyAction::Cascade),
)
.col(ColumnDef::new(UsersStatus::Target).string().not_null())
.col( .col(
ColumnDef::new(Blacklist::BlacklistedAt) ColumnDef::new(UsersStatus::Status)
.enumeration(
AccessStatus::Name,
[AccessStatus::Whitelisted, AccessStatus::Blacklisted],
)
.not_null(),
)
.col(
ColumnDef::new(UsersStatus::UpdatedAt)
.timestamp_with_time_zone() .timestamp_with_time_zone()
.not_null(), .not_null(),
) )
@ -53,13 +81,34 @@ impl MigrationTrait for Migration {
} }
} }
enum AccessStatus {
Name,
Whitelisted,
Blacklisted,
}
#[derive(DeriveIden)] #[derive(DeriveIden)]
enum Blacklist { enum UsersStatus {
Table, Table,
Id, Id,
UserId, UserId,
/// Public key of the target /// Public key of the target
Target, Target,
Reason, Status,
BlacklistedAt, UpdatedAt,
}
impl Iden for AccessStatus {
fn unquoted(&self, s: &mut dyn fmt::Write) {
write!(
s,
"{}",
match self {
Self::Name => "access_status",
Self::Whitelisted => "whitelisted",
Self::Blacklisted => "blacklisted",
}
)
.expect("is a string")
}
} }

View file

@ -1,63 +0,0 @@
// OxideTalis Messaging Protocol homeserver core implementation
// Copyright (c) 2024 OxideTalis Developers <otmp@4rs.nl>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Whitelist::Table)
.if_not_exists()
.col(
ColumnDef::new(Whitelist::Id)
.big_integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Whitelist::UserId).big_integer().not_null())
.col(ColumnDef::new(Whitelist::Target).string().not_null())
.col(
ColumnDef::new(Whitelist::WhitelistedAt)
.timestamp_with_time_zone()
.not_null(),
)
.to_owned(),
)
.await
}
}
#[derive(DeriveIden)]
enum Whitelist {
Table,
Id,
UserId,
/// Public key of the target
Target,
WhitelistedAt,
}

View file

@ -21,11 +21,10 @@
pub use sea_orm_migration::prelude::*; pub use sea_orm_migration::prelude::*;
mod create_blacklist_table;
mod create_incoming_chat_requests_table; mod create_incoming_chat_requests_table;
mod create_outgoing_chat_requests_table; mod create_outgoing_chat_requests_table;
mod create_users_status;
mod create_users_table; mod create_users_table;
mod create_whitelist_table;
pub struct Migrator; pub struct Migrator;
@ -36,8 +35,7 @@ impl MigratorTrait for Migrator {
Box::new(create_users_table::Migration), Box::new(create_users_table::Migration),
Box::new(create_incoming_chat_requests_table::Migration), Box::new(create_incoming_chat_requests_table::Migration),
Box::new(create_outgoing_chat_requests_table::Migration), Box::new(create_outgoing_chat_requests_table::Migration),
Box::new(create_blacklist_table::Migration), Box::new(create_users_status::Migration),
Box::new(create_whitelist_table::Migration),
] ]
} }
} }