From f5c4caeb6b2b1982ad488491d8d57da14e8823c0 Mon Sep 17 00:00:00 2001
From: Awiteb
Date: Mon, 22 Jul 2024 22:47:50 +0300
Subject: [PATCH 1/6] feat: Add `sea-orm` feature to use `PublicKey` as entity
column
Signed-off-by: Awiteb
---
crates/oxidetalis_core/Cargo.toml | 2 +
.../oxidetalis_core/src/types/impl_sea_orm.rs | 74 +++++++++++++++++++
crates/oxidetalis_core/src/types/mod.rs | 2 +
3 files changed, 78 insertions(+)
create mode 100644 crates/oxidetalis_core/src/types/impl_sea_orm.rs
diff --git a/crates/oxidetalis_core/Cargo.toml b/crates/oxidetalis_core/Cargo.toml
index 36d24bb..d112c81 100644
--- a/crates/oxidetalis_core/Cargo.toml
+++ b/crates/oxidetalis_core/Cargo.toml
@@ -15,6 +15,7 @@ base58 = { workspace = true }
thiserror = { workspace = true }
salvo-oapi = { workspace = true, optional = true }
serde = { workspace = true, optional = true }
+sea-orm = { workspace = true, optional = true }
cbc = { version = "0.1.2", features = ["alloc", "std"] }
k256 = { version = "0.13.3", default-features = false, features = ["ecdh"] }
rand = { version = "0.8.5", default-features = false, features = ["std_rng", "std"] }
@@ -26,6 +27,7 @@ sha2 = "0.10.8"
[features]
openapi = ["dep:salvo-oapi"]
serde = ["dep:serde"]
+sea-orm = ["dep:sea-orm"]
[lints.rust]
diff --git a/crates/oxidetalis_core/src/types/impl_sea_orm.rs b/crates/oxidetalis_core/src/types/impl_sea_orm.rs
new file mode 100644
index 0000000..c5bc1e4
--- /dev/null
+++ b/crates/oxidetalis_core/src/types/impl_sea_orm.rs
@@ -0,0 +1,74 @@
+// OxideTalis Messaging Protocol homeserver core implementation
+// Copyright (C) 2024 Awiteb , OxideTalis Contributors
+//
+// 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.
+
+//! Implemented SeaORM support for core types, enabling the use of these types
+//! as column types in SeaORM
+
+use std::str::FromStr;
+
+use sea_orm::{
+ sea_query::{ArrayType, ValueType, ValueTypeErr},
+ ColumnType,
+ DbErr,
+ QueryResult,
+ TryGetError,
+ TryGetable,
+ Value,
+};
+
+use super::PublicKey;
+
+impl From for Value {
+ fn from(public_key: PublicKey) -> Self {
+ Self::String(Some(Box::new(public_key.to_string())))
+ }
+}
+
+impl TryGetable for PublicKey {
+ fn try_get_by(res: &QueryResult, idx: I) -> Result {
+ ::try_get_by(res, idx)
+ .map(|v| {
+ PublicKey::from_str(&v)
+ .map_err(|err| TryGetError::DbErr(DbErr::Type(err.to_string())))
+ })
+ .and_then(|res| res)
+ }
+}
+
+impl ValueType for PublicKey {
+ fn try_from(v: Value) -> Result {
+ ::try_from(v)
+ .map(|v| PublicKey::from_str(&v).map_err(|_| ValueTypeErr))
+ .and_then(|res| res)
+ }
+
+ fn type_name() -> String {
+ stringify!(PublicKey).to_owned()
+ }
+
+ fn array_type() -> ArrayType {
+ ArrayType::String
+ }
+
+ fn column_type() -> ColumnType {
+ ColumnType::String(None)
+ }
+}
diff --git a/crates/oxidetalis_core/src/types/mod.rs b/crates/oxidetalis_core/src/types/mod.rs
index b6143aa..7635eb3 100644
--- a/crates/oxidetalis_core/src/types/mod.rs
+++ b/crates/oxidetalis_core/src/types/mod.rs
@@ -22,6 +22,8 @@
//! Oxidetalis server types
mod cipher;
+#[cfg(feature = "sea-orm")]
+mod impl_sea_orm;
#[cfg(feature = "serde")]
mod impl_serde;
mod size;
--
2.45.2
From 62cfc1bd0795ba6ddfacb254b80fcdd3c1e1ff0e Mon Sep 17 00:00:00 2001
From: Awiteb
Date: Mon, 22 Jul 2024 22:48:48 +0300
Subject: [PATCH 2/6] chore: Use `oxidetalis_core` in `oxidetalis_entities`
Signed-off-by: Awiteb
---
Cargo.lock | 2 ++
crates/oxidetalis_entities/Cargo.toml | 5 +++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 5e4d355..8e6aea0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1954,6 +1954,7 @@ dependencies = [
"k256",
"rand",
"salvo-oapi",
+ "sea-orm",
"serde",
"sha2",
"thiserror",
@@ -1964,6 +1965,7 @@ name = "oxidetalis_entities"
version = "0.1.0"
dependencies = [
"chrono",
+ "oxidetalis_core",
"sea-orm",
]
diff --git a/crates/oxidetalis_entities/Cargo.toml b/crates/oxidetalis_entities/Cargo.toml
index 4a444f6..86ee7ce 100644
--- a/crates/oxidetalis_entities/Cargo.toml
+++ b/crates/oxidetalis_entities/Cargo.toml
@@ -11,8 +11,9 @@ rust-version.workspace = true
[dependencies]
-sea-orm = { workspace = true }
-chrono = { workspace = true }
+oxidetalis_core = { workspace = true, features = ["sea-orm"] }
+sea-orm = { workspace = true }
+chrono = { workspace = true }
[lints.rust]
unsafe_code = "deny"
--
2.45.2
From 79ef0d244816cc0f3d0c31cb5b0732acc2259823 Mon Sep 17 00:00:00 2001
From: Awiteb
Date: Mon, 22 Jul 2024 22:50:36 +0300
Subject: [PATCH 3/6] refactor: Update public key column type from `String` to
`PublicKey`
Signed-off-by: Awiteb
---
.../src/database/in_chat_requests.rs | 2 +-
.../src/database/out_chat_requests.rs | 2 +-
crates/oxidetalis/src/database/user.rs | 2 +-
crates/oxidetalis/src/database/user_status.rs | 8 +++----
crates/oxidetalis/src/schemas/user.rs | 4 ++--
.../src/websocket/handlers/chat_request.rs | 22 ++++++-------------
.../src/incoming_chat_requests.rs | 3 ++-
.../src/outgoing_chat_requests.rs | 3 ++-
crates/oxidetalis_entities/src/users.rs | 3 ++-
.../oxidetalis_entities/src/users_status.rs | 4 ++--
10 files changed, 24 insertions(+), 29 deletions(-)
diff --git a/crates/oxidetalis/src/database/in_chat_requests.rs b/crates/oxidetalis/src/database/in_chat_requests.rs
index 061fb84..10c150a 100644
--- a/crates/oxidetalis/src/database/in_chat_requests.rs
+++ b/crates/oxidetalis/src/database/in_chat_requests.rs
@@ -42,7 +42,7 @@ impl InChatRequestsExt for DatabaseConnection {
) -> ServerResult<()> {
InChatRequestsEntity::insert(InChatRequestsActiveModel {
recipient_id: Set(recipient.id),
- sender: Set(sender.to_string()),
+ sender: Set(*sender),
in_on: Set(Utc::now()),
..Default::default()
})
diff --git a/crates/oxidetalis/src/database/out_chat_requests.rs b/crates/oxidetalis/src/database/out_chat_requests.rs
index ed34d8a..0274eda 100644
--- a/crates/oxidetalis/src/database/out_chat_requests.rs
+++ b/crates/oxidetalis/src/database/out_chat_requests.rs
@@ -71,7 +71,7 @@ impl OutChatRequestsExt for DatabaseConnection {
) -> ServerResult<()> {
if let Err(err) = (OutChatRequestsActiveModel {
sender_id: Set(requester.id),
- recipient: Set(recipient.to_string()),
+ recipient: Set(*recipient),
out_on: Set(Utc::now()),
..Default::default()
}
diff --git a/crates/oxidetalis/src/database/user.rs b/crates/oxidetalis/src/database/user.rs
index 79fc109..90065e8 100644
--- a/crates/oxidetalis/src/database/user.rs
+++ b/crates/oxidetalis/src/database/user.rs
@@ -45,7 +45,7 @@ impl UserTableExt for DatabaseConnection {
#[logcall]
async fn register_user(&self, public_key: &PublicKey, is_admin: bool) -> ServerResult<()> {
if let Err(err) = (UserActiveModel {
- public_key: Set(public_key.to_string()),
+ public_key: Set(*public_key),
is_admin: Set(is_admin),
..Default::default()
})
diff --git a/crates/oxidetalis/src/database/user_status.rs b/crates/oxidetalis/src/database/user_status.rs
index 4daf506..43d1b36 100644
--- a/crates/oxidetalis/src/database/user_status.rs
+++ b/crates/oxidetalis/src/database/user_status.rs
@@ -138,7 +138,7 @@ impl UsersStatusExt for DatabaseConnection {
whitelister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
- if whitelister.public_key == target_public_key.to_string() {
+ if &whitelister.public_key == target_public_key {
return Err(WsError::CannotAddSelfToWhitelist.into());
}
@@ -156,7 +156,7 @@ impl UsersStatusExt for DatabaseConnection {
user.update(self).await?;
} else if let Err(err) = (UsersStatusActiveModel {
user_id: Set(whitelister.id),
- target: Set(target_public_key.to_string()),
+ target: Set(*target_public_key),
status: Set(AccessStatus::Whitelisted),
updated_at: Set(Utc::now()),
..Default::default()
@@ -181,7 +181,7 @@ impl UsersStatusExt for DatabaseConnection {
blacklister: &UserModel,
target_public_key: &PublicKey,
) -> ServerResult<()> {
- if blacklister.public_key == target_public_key.to_string() {
+ if &blacklister.public_key == target_public_key {
return Err(WsError::CannotAddSelfToBlacklist.into());
}
@@ -199,7 +199,7 @@ impl UsersStatusExt for DatabaseConnection {
user.update(self).await?;
} else if let Err(err) = (UsersStatusActiveModel {
user_id: Set(blacklister.id),
- target: Set(target_public_key.to_string()),
+ target: Set(*target_public_key),
status: Set(AccessStatus::Blacklisted),
updated_at: Set(Utc::now()),
..Default::default()
diff --git a/crates/oxidetalis/src/schemas/user.rs b/crates/oxidetalis/src/schemas/user.rs
index feec7f2..237c201 100644
--- a/crates/oxidetalis/src/schemas/user.rs
+++ b/crates/oxidetalis/src/schemas/user.rs
@@ -54,7 +54,7 @@ impl Default for WhiteListedUser {
impl From for WhiteListedUser {
fn from(user: UsersStatusModel) -> Self {
Self {
- public_key: PublicKey::from_str(&user.target).expect("Is valid public key"),
+ public_key: user.target,
whitelisted_at: user.updated_at,
}
}
@@ -72,7 +72,7 @@ impl Default for BlackListedUser {
impl From for BlackListedUser {
fn from(user: UsersStatusModel) -> Self {
Self {
- public_key: PublicKey::from_str(&user.target).expect("Is valid public key"),
+ public_key: user.target,
blacklisted_at: user.updated_at,
}
}
diff --git a/crates/oxidetalis/src/websocket/handlers/chat_request.rs b/crates/oxidetalis/src/websocket/handlers/chat_request.rs
index e18712f..222137a 100644
--- a/crates/oxidetalis/src/websocket/handlers/chat_request.rs
+++ b/crates/oxidetalis/src/websocket/handlers/chat_request.rs
@@ -16,8 +16,6 @@
//! Handler for incoming and outgoing chat requests.
-use std::str::FromStr;
-
use oxidetalis_core::types::PublicKey;
use oxidetalis_entities::prelude::*;
use sea_orm::DatabaseConnection;
@@ -47,14 +45,12 @@ pub async fn handle_chat_request(
if from_user.id == to_user.id {
return Some(WsError::CannotSendChatRequestToSelf.into());
}
- // FIXME: When change the entity public key to a PublicKey type, change this
- let from_public_key = PublicKey::from_str(&from_user.public_key).expect("Is valid public key");
if try_ws!(Some db.get_chat_request_to(from_user, to_public_key).await).is_some() {
return Some(WsError::AlreadySendChatRequest.into());
}
- if try_ws!(Some db.is_blacklisted(&to_user, &from_public_key).await) {
+ if try_ws!(Some db.is_blacklisted(&to_user, &from_user.public_key).await) {
return Some(WsError::RecipientBlacklist.into());
}
@@ -64,17 +60,17 @@ pub async fn handle_chat_request(
return Some(WsError::InternalServerError.into());
}
- if try_ws!(Some db.is_whitelisted(&to_user, &from_public_key).await) {
+ if try_ws!(Some db.is_whitelisted(&to_user, &from_user.public_key).await) {
return Some(WsError::AlreadyInRecipientWhitelist.into());
}
try_ws!(Some db.save_out_chat_request(from_user, to_public_key).await);
if let Some(conn_id) = ONLINE_USERS.is_online(to_public_key).await {
ONLINE_USERS
- .send(&conn_id, ServerEvent::chat_request(&from_public_key))
+ .send(&conn_id, ServerEvent::chat_request(&from_user.public_key))
.await;
} else {
- try_ws!(Some db.save_in_chat_request(&from_public_key, &to_user).await);
+ try_ws!(Some db.save_in_chat_request(&from_user.public_key, &to_user).await);
}
None
}
@@ -96,12 +92,8 @@ pub async fn handle_chat_response(
return Some(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!(Some
- db.get_chat_request_to(&sender_user, &recipient_public_key)
+ db.get_chat_request_to(&sender_user, &recipient_user.public_key)
.await
)
.is_none()
@@ -118,7 +110,7 @@ pub async fn handle_chat_response(
};
try_ws!(Some
- db.remove_out_chat_request(&sender_user, &recipient_public_key)
+ db.remove_out_chat_request(&sender_user, &recipient_user.public_key)
.await
);
@@ -126,7 +118,7 @@ pub async fn handle_chat_response(
ONLINE_USERS
.send(
&conn_id,
- ServerEvent::chat_request_response(recipient_public_key, accepted),
+ ServerEvent::chat_request_response(recipient_user.public_key, accepted),
)
.await;
} else {
diff --git a/crates/oxidetalis_entities/src/incoming_chat_requests.rs b/crates/oxidetalis_entities/src/incoming_chat_requests.rs
index 9c55f74..a34d7c7 100644
--- a/crates/oxidetalis_entities/src/incoming_chat_requests.rs
+++ b/crates/oxidetalis_entities/src/incoming_chat_requests.rs
@@ -22,6 +22,7 @@
//! Entity for `in_chat_requests` table
use chrono::Utc;
+use oxidetalis_core::types::PublicKey as CorePublicKey;
use sea_orm::entity::prelude::*;
use crate::prelude::*;
@@ -33,7 +34,7 @@ pub struct Model {
pub id: UserId,
pub recipient_id: UserId,
/// Public key of the sender
- pub sender: String,
+ pub sender: CorePublicKey,
/// The timestamp of the request, when it was received
pub in_on: chrono::DateTime,
}
diff --git a/crates/oxidetalis_entities/src/outgoing_chat_requests.rs b/crates/oxidetalis_entities/src/outgoing_chat_requests.rs
index 95ba3f1..0f5a614 100644
--- a/crates/oxidetalis_entities/src/outgoing_chat_requests.rs
+++ b/crates/oxidetalis_entities/src/outgoing_chat_requests.rs
@@ -22,6 +22,7 @@
//! Entity for `out_chat_requests` table
use chrono::Utc;
+use oxidetalis_core::types::PublicKey as CorePublicKey;
use sea_orm::entity::prelude::*;
use crate::prelude::*;
@@ -33,7 +34,7 @@ pub struct Model {
pub id: UserId,
pub sender_id: UserId,
/// Public key of the recipient
- pub recipient: String,
+ pub recipient: CorePublicKey,
/// The timestamp of the request, when it was sent
pub out_on: chrono::DateTime,
}
diff --git a/crates/oxidetalis_entities/src/users.rs b/crates/oxidetalis_entities/src/users.rs
index 1a7692b..df6dd82 100644
--- a/crates/oxidetalis_entities/src/users.rs
+++ b/crates/oxidetalis_entities/src/users.rs
@@ -21,6 +21,7 @@
//! Entity for `users` table
+use oxidetalis_core::types::PublicKey as CorePublicKey;
use sea_orm::entity::prelude::*;
use crate::prelude::*;
@@ -30,7 +31,7 @@ use crate::prelude::*;
pub struct Model {
#[sea_orm(primary_key)]
pub id: UserId,
- pub public_key: String,
+ pub public_key: CorePublicKey,
pub is_admin: bool,
}
diff --git a/crates/oxidetalis_entities/src/users_status.rs b/crates/oxidetalis_entities/src/users_status.rs
index 23eab9c..7651bc1 100644
--- a/crates/oxidetalis_entities/src/users_status.rs
+++ b/crates/oxidetalis_entities/src/users_status.rs
@@ -22,6 +22,7 @@
//! Entity for `users_status` table
use chrono::Utc;
+use oxidetalis_core::types::PublicKey as CorePublicKey;
use sea_orm::entity::prelude::*;
use crate::prelude::*;
@@ -41,8 +42,7 @@ pub struct Model {
#[sea_orm(primary_key)]
pub id: UserId,
pub user_id: UserId,
- /// Public key of the target
- pub target: String,
+ pub target: CorePublicKey,
pub status: AccessStatus,
pub updated_at: chrono::DateTime,
}
--
2.45.2
From 35a7354de1d1cd1bc6a0079f7876ae35fe06038d Mon Sep 17 00:00:00 2001
From: Awiteb
Date: Tue, 23 Jul 2024 11:49:55 +0300
Subject: [PATCH 4/6] refactor: Use `and_then` instead of `map`
Signed-off-by: Awiteb
---
crates/oxidetalis_core/src/types/impl_sea_orm.rs | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/crates/oxidetalis_core/src/types/impl_sea_orm.rs b/crates/oxidetalis_core/src/types/impl_sea_orm.rs
index c5bc1e4..8d6f7c5 100644
--- a/crates/oxidetalis_core/src/types/impl_sea_orm.rs
+++ b/crates/oxidetalis_core/src/types/impl_sea_orm.rs
@@ -44,24 +44,20 @@ impl From for Value {
impl TryGetable for PublicKey {
fn try_get_by(res: &QueryResult, idx: I) -> Result {
- ::try_get_by(res, idx)
- .map(|v| {
- PublicKey::from_str(&v)
- .map_err(|err| TryGetError::DbErr(DbErr::Type(err.to_string())))
- })
- .and_then(|res| res)
+ ::try_get_by(res, idx).and_then(|v| {
+ PublicKey::from_str(&v).map_err(|err| TryGetError::DbErr(DbErr::Type(err.to_string())))
+ })
}
}
impl ValueType for PublicKey {
fn try_from(v: Value) -> Result {
::try_from(v)
- .map(|v| PublicKey::from_str(&v).map_err(|_| ValueTypeErr))
- .and_then(|res| res)
+ .and_then(|v| PublicKey::from_str(&v).map_err(|_| ValueTypeErr))
}
fn type_name() -> String {
- stringify!(PublicKey).to_owned()
+ String::from("PublicKey")
}
fn array_type() -> ArrayType {
--
2.45.2
From ab4e388ff837863c20ec949f4bc047bc054e83f2 Mon Sep 17 00:00:00 2001
From: Awiteb
Date: Tue, 23 Jul 2024 17:05:35 +0300
Subject: [PATCH 5/6] change: Change public key type to binary
Signed-off-by: Awiteb
---
.../src/database/out_chat_requests.rs | 2 +-
crates/oxidetalis/src/database/user.rs | 2 +-
crates/oxidetalis/src/database/user_status.rs | 2 +-
.../oxidetalis_core/src/types/impl_sea_orm.rs | 34 +++++++++++++------
.../create_incoming_chat_requests_table.rs | 2 +-
.../create_outgoing_chat_requests_table.rs | 2 +-
.../src/create_users_status.rs | 2 +-
.../src/create_users_table.rs | 2 +-
8 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/crates/oxidetalis/src/database/out_chat_requests.rs b/crates/oxidetalis/src/database/out_chat_requests.rs
index 0274eda..586be54 100644
--- a/crates/oxidetalis/src/database/out_chat_requests.rs
+++ b/crates/oxidetalis/src/database/out_chat_requests.rs
@@ -57,7 +57,7 @@ impl OutChatRequestsExt for DatabaseConnection {
) -> ServerResult