From 1d1bb962bb95e4fc6d9c821accb1df116a1bc759 Mon Sep 17 00:00:00 2001 From: Awiteb Date: Wed, 24 Jul 2024 01:19:34 +0300 Subject: [PATCH] refactor: Update public key column type from `String` to `PublicKey` Reviewed-on: https://git.4rs.nl/OxideTalis/oxidetalis/pulls/29 Reviewed-by: Amjad Alsharafi Helped-by: Amjad Alsharafi Signed-off-by: Awiteb --- Cargo.lock | 2 + .../src/database/in_chat_requests.rs | 2 +- .../src/database/out_chat_requests.rs | 4 +- crates/oxidetalis/src/database/user.rs | 4 +- crates/oxidetalis/src/database/user_status.rs | 10 +-- crates/oxidetalis/src/schemas/user.rs | 4 +- .../src/websocket/handlers/chat_request.rs | 22 ++--- crates/oxidetalis_core/Cargo.toml | 2 + .../oxidetalis_core/src/types/impl_sea_orm.rs | 84 +++++++++++++++++++ crates/oxidetalis_core/src/types/mod.rs | 2 + crates/oxidetalis_entities/Cargo.toml | 5 +- .../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 +- .../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 +- 19 files changed, 124 insertions(+), 38 deletions(-) create mode 100644 crates/oxidetalis_core/src/types/impl_sea_orm.rs 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/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..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> { requester .find_related(OutChatRequestsEntity) - .filter(OutChatRequestsColumn::Recipient.eq(recipient.to_string())) + .filter(OutChatRequestsColumn::Recipient.eq(recipient)) .one(self) .await .map_err(Into::into) @@ -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..d43301d 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() }) @@ -63,7 +63,7 @@ impl UserTableExt for DatabaseConnection { #[logcall] async fn get_user_by_pubk(&self, public_key: &PublicKey) -> ServerResult> { UserEntity::find() - .filter(UserColumn::PublicKey.eq(public_key.to_string())) + .filter(UserColumn::PublicKey.eq(public_key)) .one(self) .await .map_err(Into::into) diff --git a/crates/oxidetalis/src/database/user_status.rs b/crates/oxidetalis/src/database/user_status.rs index 4daf506..76643ed 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() @@ -297,7 +297,7 @@ async fn get_user_status( user.find_related(UsersStatusEntity) .filter( UsersStatusColumn::Target - .eq(target_public_key.to_string()) + .eq(target_public_key) .and(UsersStatusColumn::Status.eq(status)), ) .one(conn) 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_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..f5f5b6f --- /dev/null +++ b/crates/oxidetalis_core/src/types/impl_sea_orm.rs @@ -0,0 +1,84 @@ +// 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 sea_orm::{ + sea_query::{ArrayType, BlobSize, ValueType, ValueTypeErr}, + ColumnType, + DbErr, + QueryResult, + TryGetError, + TryGetable, + Value, +}; + +use super::PublicKey; + +impl From for Value { + fn from(public_key: PublicKey) -> Self { + public_key.as_bytes().as_slice().into() + } +} + +impl From<&PublicKey> for Value { + fn from(public_key: &PublicKey) -> Self { + public_key.as_bytes().as_slice().into() + } +} + +impl TryGetable for PublicKey { + fn try_get_by(res: &QueryResult, idx: I) -> Result { + let db_err = |err: &str| TryGetError::DbErr(DbErr::Type(err.to_owned())); + + as TryGetable>::try_get_by(res, idx).and_then(|v| { + v.try_into() + .map_err(|_| db_err("Invalid binary length")) + .and_then(|bytes| { + >::try_from(bytes) + .map_err(|_| db_err("Invalid Public Key")) + }) + }) + } +} + +impl ValueType for PublicKey { + fn try_from(v: Value) -> Result { + as ValueType>::try_from(v).and_then(|v| { + v.try_into().map_err(|_| ValueTypeErr).and_then(|bytes| { + >::try_from(bytes).map_err(|_| ValueTypeErr) + }) + }) + } + + fn type_name() -> String { + String::from("PublicKey") + } + + fn array_type() -> ArrayType { + ArrayType::Bytes + } + + fn column_type() -> ColumnType { + ColumnType::Binary(BlobSize::Blob(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; 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" diff --git a/crates/oxidetalis_entities/src/incoming_chat_requests.rs b/crates/oxidetalis_entities/src/incoming_chat_requests.rs index 9c55f74..ed6ff3c 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; 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: PublicKey, /// 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..2f5642c 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; 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: PublicKey, /// 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..66e3db9 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; 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: PublicKey, pub is_admin: bool, } diff --git a/crates/oxidetalis_entities/src/users_status.rs b/crates/oxidetalis_entities/src/users_status.rs index 23eab9c..2f66883 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; 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: PublicKey, pub status: AccessStatus, pub updated_at: chrono::DateTime, } diff --git a/crates/oxidetalis_migrations/src/create_incoming_chat_requests_table.rs b/crates/oxidetalis_migrations/src/create_incoming_chat_requests_table.rs index 1af430c..3cd6fed 100644 --- a/crates/oxidetalis_migrations/src/create_incoming_chat_requests_table.rs +++ b/crates/oxidetalis_migrations/src/create_incoming_chat_requests_table.rs @@ -57,7 +57,7 @@ impl MigrationTrait for Migration { .on_update(ForeignKeyAction::NoAction) .on_delete(ForeignKeyAction::Cascade), ) - .col(ColumnDef::new(InChatRequests::Sender).string().not_null()) + .col(ColumnDef::new(InChatRequests::Sender).binary().not_null()) .col( ColumnDef::new(InChatRequests::InOn) .timestamp_with_time_zone() diff --git a/crates/oxidetalis_migrations/src/create_outgoing_chat_requests_table.rs b/crates/oxidetalis_migrations/src/create_outgoing_chat_requests_table.rs index 6130d87..daa1092 100644 --- a/crates/oxidetalis_migrations/src/create_outgoing_chat_requests_table.rs +++ b/crates/oxidetalis_migrations/src/create_outgoing_chat_requests_table.rs @@ -59,7 +59,7 @@ impl MigrationTrait for Migration { ) .col( ColumnDef::new(OutChatRequests::Recipient) - .string() + .binary() .not_null(), ) .col( diff --git a/crates/oxidetalis_migrations/src/create_users_status.rs b/crates/oxidetalis_migrations/src/create_users_status.rs index beba81b..aae3804 100644 --- a/crates/oxidetalis_migrations/src/create_users_status.rs +++ b/crates/oxidetalis_migrations/src/create_users_status.rs @@ -65,7 +65,7 @@ impl MigrationTrait for Migration { .on_update(ForeignKeyAction::NoAction) .on_delete(ForeignKeyAction::Cascade), ) - .col(ColumnDef::new(UsersStatus::Target).string().not_null()) + .col(ColumnDef::new(UsersStatus::Target).binary().not_null()) .col( ColumnDef::new(UsersStatus::Status) .enumeration( diff --git a/crates/oxidetalis_migrations/src/create_users_table.rs b/crates/oxidetalis_migrations/src/create_users_table.rs index d8f2956..9a52372 100644 --- a/crates/oxidetalis_migrations/src/create_users_table.rs +++ b/crates/oxidetalis_migrations/src/create_users_table.rs @@ -43,7 +43,7 @@ impl MigrationTrait for Migration { ) .col( ColumnDef::new(Users::PublicKey) - .string() + .binary() .not_null() .unique_key(), )