From cf4fe859bf9ed014690e2efaa447e7e3d2b1d39f Mon Sep 17 00:00:00 2001 From: Zomatree Date: Tue, 1 Jul 2025 21:42:45 +0100 Subject: [PATCH] feat: move all json and validate to new utils --- clippy.toml | 4 + .../database/src/models/messages/model.rs | 7 -- crates/core/models/src/v0/mod.rs | 2 + crates/core/models/src/v0/onboard.rs | 15 ++++ crates/core/models/src/v0/safety_reports.rs | 11 +++ crates/core/models/src/v0/servers.rs | 20 ++++- crates/core/models/src/v0/users.rs | 11 +++ crates/delta/src/routes/bots/create.rs | 14 +-- crates/delta/src/routes/bots/edit.rs | 12 +-- crates/delta/src/routes/bots/fetch.rs | 3 +- crates/delta/src/routes/bots/fetch_owned.rs | 2 +- crates/delta/src/routes/bots/fetch_public.rs | 2 +- crates/delta/src/routes/bots/invite.rs | 2 +- .../delta/src/routes/channels/channel_edit.rs | 13 +-- .../src/routes/channels/channel_fetch.rs | 3 +- .../delta/src/routes/channels/group_create.rs | 12 +-- .../src/routes/channels/invite_create.rs | 3 +- .../src/routes/channels/members_fetch.rs | 3 +- .../routes/channels/message_bulk_delete.rs | 13 +-- .../delta/src/routes/channels/message_edit.rs | 13 +-- .../src/routes/channels/message_fetch.rs | 3 +- .../src/routes/channels/message_query.rs | 14 +-- .../src/routes/channels/message_search.rs | 13 +-- .../delta/src/routes/channels/message_send.rs | 5 +- .../src/routes/channels/permissions_set.rs | 3 +- .../channels/permissions_set_default.rs | 3 +- .../delta/src/routes/channels/voice_join.rs | 3 +- .../src/routes/channels/webhook_create.rs | 13 +-- .../src/routes/channels/webhook_fetch_all.rs | 3 +- .../src/routes/customisation/emoji_create.rs | 14 +-- .../src/routes/customisation/emoji_fetch.rs | 3 +- .../delta/src/routes/invites/invite_fetch.rs | 3 +- .../delta/src/routes/invites/invite_join.rs | 3 +- crates/delta/src/routes/onboard/complete.rs | 29 +------ crates/delta/src/routes/onboard/hello.rs | 15 +--- crates/delta/src/routes/push/subscribe.rs | 3 +- crates/delta/src/routes/root.rs | 2 +- .../delta/src/routes/safety/report_content.rs | 28 ++---- crates/delta/src/routes/servers/ban_create.rs | 13 +-- crates/delta/src/routes/servers/ban_list.rs | 2 +- .../src/routes/servers/channel_create.rs | 14 +-- crates/delta/src/routes/servers/emoji_list.rs | 3 +- .../delta/src/routes/servers/invites_fetch.rs | 3 +- .../delta/src/routes/servers/member_edit.rs | 13 +-- .../servers/member_experimental_query.rs | 29 ++----- .../delta/src/routes/servers/member_fetch.rs | 3 +- .../src/routes/servers/member_fetch_all.rs | 3 +- .../src/routes/servers/permissions_set.rs | 3 +- .../routes/servers/permissions_set_default.rs | 3 +- .../delta/src/routes/servers/roles_create.rs | 13 +-- crates/delta/src/routes/servers/roles_edit.rs | 13 +-- .../routes/servers/roles_edit_positions.rs | 3 +- .../delta/src/routes/servers/roles_fetch.rs | 3 +- .../delta/src/routes/servers/server_create.rs | 12 +-- .../delta/src/routes/servers/server_edit.rs | 13 +-- .../delta/src/routes/servers/server_fetch.rs | 3 +- crates/delta/src/routes/sync/get_settings.rs | 2 +- crates/delta/src/routes/sync/get_unreads.rs | 2 +- crates/delta/src/routes/sync/set_settings.rs | 3 +- crates/delta/src/routes/users/add_friend.rs | 2 +- crates/delta/src/routes/users/block_user.rs | 2 +- .../delta/src/routes/users/change_username.rs | 33 +------ crates/delta/src/routes/users/edit_user.rs | 12 +-- crates/delta/src/routes/users/fetch_dms.rs | 3 +- .../delta/src/routes/users/fetch_profile.rs | 3 +- crates/delta/src/routes/users/fetch_self.rs | 2 +- crates/delta/src/routes/users/fetch_user.rs | 3 +- .../src/routes/users/fetch_user_flags.rs | 3 +- crates/delta/src/routes/users/find_mutual.rs | 2 +- crates/delta/src/routes/users/open_dm.rs | 3 +- .../delta/src/routes/users/remove_friend.rs | 2 +- .../src/routes/users/send_friend_request.rs | 2 +- crates/delta/src/routes/users/unblock_user.rs | 2 +- .../delta/src/routes/webhooks/webhook_edit.rs | 15 ++-- .../src/routes/webhooks/webhook_edit_token.rs | 15 ++-- .../src/routes/webhooks/webhook_execute.rs | 16 ++-- .../routes/webhooks/webhook_execute_github.rs | 14 +-- .../src/routes/webhooks/webhook_fetch.rs | 3 +- .../routes/webhooks/webhook_fetch_token.rs | 3 +- crates/delta/src/util/{ => json}/json.rs | 85 ++---------------- crates/delta/src/util/json/mod.rs | 27 ++++++ crates/delta/src/util/json/validator.rs | 87 +++++++++++++++++++ crates/delta/src/util/ratelimiter.rs | 2 +- 83 files changed, 371 insertions(+), 451 deletions(-) create mode 100644 crates/core/models/src/v0/onboard.rs rename crates/delta/src/util/{ => json}/json.rs (54%) create mode 100644 crates/delta/src/util/json/mod.rs create mode 100644 crates/delta/src/util/json/validator.rs diff --git a/clippy.toml b/clippy.toml index a3563b4d..adfd9947 100644 --- a/clippy.toml +++ b/clippy.toml @@ -26,3 +26,7 @@ disallowed-methods = [ # Prefer to use Object::delete(&self) "revolt_database::models::bots::ops::AbstractBots::delete_bot", ] + +disallowed-types = [ + "rocket::serde::json::Json", +] \ No newline at end of file diff --git a/crates/core/database/src/models/messages/model.rs b/crates/core/database/src/models/messages/model.rs index 53d38012..6a629775 100644 --- a/crates/core/database/src/models/messages/model.rs +++ b/crates/core/database/src/models/messages/model.rs @@ -10,7 +10,6 @@ use revolt_models::v0::{ use revolt_permissions::{calculate_channel_permissions, ChannelPermission, PermissionValue}; use revolt_result::{ErrorType, Result}; use ulid::Ulid; -use validator::Validate; use crate::{ events::client::EventV1, @@ -717,12 +716,6 @@ impl Message { /// Create text embed from sendable embed pub async fn create_embed(&self, db: &Database, embed: SendableEmbed) -> Result { - embed.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; - let media = if let Some(id) = embed.media { Some(File::use_attachment(db, &id, &self.id, &self.author).await?) } else { diff --git a/crates/core/models/src/v0/mod.rs b/crates/core/models/src/v0/mod.rs index 0468493b..40f1b256 100644 --- a/crates/core/models/src/v0/mod.rs +++ b/crates/core/models/src/v0/mod.rs @@ -7,6 +7,7 @@ mod embeds; mod emojis; mod files; mod messages; +mod onboard; mod policy_changes; mod safety_reports; mod server_bans; @@ -24,6 +25,7 @@ pub use embeds::*; pub use emojis::*; pub use files::*; pub use messages::*; +pub use onboard::*; pub use policy_changes::*; pub use safety_reports::*; pub use server_bans::*; diff --git a/crates/core/models/src/v0/onboard.rs b/crates/core/models/src/v0/onboard.rs new file mode 100644 index 00000000..02efb15c --- /dev/null +++ b/crates/core/models/src/v0/onboard.rs @@ -0,0 +1,15 @@ +auto_derived!( + /// # New User Data + #[derive(validator::Validate)] + pub struct DataOnboard { + /// New username which will be used to identify the user on the platform + #[validate(length(min = 2, max = 32), regex = "super::RE_USERNAME")] + pub username: String, + } + + /// # Onboarding Status + pub struct DataHello { + /// Whether onboarding is required + pub onboarding: bool, + } +); \ No newline at end of file diff --git a/crates/core/models/src/v0/safety_reports.rs b/crates/core/models/src/v0/safety_reports.rs index 0d8ee5d7..73be203d 100644 --- a/crates/core/models/src/v0/safety_reports.rs +++ b/crates/core/models/src/v0/safety_reports.rs @@ -1,6 +1,17 @@ use iso8601_timestamp::Timestamp; auto_derived!( + /// # Report Data + #[derive(validator::Validate)] + pub struct DataReportContent { + /// Content being reported + pub content: ReportedContent, + /// Additional report description + #[validate(length(min = 0, max = 1000))] + #[serde(default)] + pub additional_context: String, + } + /// User-generated platform moderation report pub struct Report { /// Unique Id diff --git a/crates/core/models/src/v0/servers.rs b/crates/core/models/src/v0/servers.rs index c3ed20a8..43e00df7 100644 --- a/crates/core/models/src/v0/servers.rs +++ b/crates/core/models/src/v0/servers.rs @@ -1,4 +1,4 @@ -use super::{Channel, File, RE_COLOUR}; +use super::{Channel, File, Member, User, RE_COLOUR}; use revolt_permissions::{Override, OverrideField}; use std::collections::HashMap; @@ -293,4 +293,22 @@ auto_derived!( pub struct DataEditRoleRanks { pub ranks: Vec, } + + /// # Query Parameters + #[derive(FromForm)] + pub struct OptionsQueryMembers { + /// String to search for + pub query: String, + + /// Discourage use of this API + pub experimental_api: bool, + } + + /// # Query members by name + pub struct MemberQueryResponse { + /// List of members + pub members: Vec, + /// List of users + pub users: Vec, + } ); diff --git a/crates/core/models/src/v0/users.rs b/crates/core/models/src/v0/users.rs index ef1c8f1a..0a5fae5e 100644 --- a/crates/core/models/src/v0/users.rs +++ b/crates/core/models/src/v0/users.rs @@ -275,6 +275,17 @@ auto_derived!( /// Username and discriminator combo separated by # pub username: String, } + + /// # Username Information + #[derive(Validate)] + pub struct DataChangeUsername { + /// New username + #[validate(length(min = 2, max = 32), regex = "super::RE_USERNAME")] + pub username: String, + /// Current account password + #[validate(length(min = 8, max = 1024))] + pub password: String, + } ); pub trait CheckRelationship { diff --git a/crates/delta/src/routes/bots/create.rs b/crates/delta/src/routes/bots/create.rs index 67a97f07..ff7729bb 100644 --- a/crates/delta/src/routes/bots/create.rs +++ b/crates/delta/src/routes/bots/create.rs @@ -1,9 +1,8 @@ +use crate::util::json::{Json, Validate}; use revolt_database::{Bot, Database, User}; use revolt_models::v0; -use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use revolt_result::Result; use rocket::State; -use validator::Validate; /// # Create Bot /// @@ -13,14 +12,9 @@ use validator::Validate; pub async fn create_bot( db: &State, user: User, - info: Json, + info: Validate>, ) -> Result> { - let info = info.into_inner(); - info.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let info = info.into_inner().into_inner(); let (bot, user) = Bot::create(db, info.name, &user, None).await?; Ok(Json(v0::BotWithUserResponse { diff --git a/crates/delta/src/routes/bots/edit.rs b/crates/delta/src/routes/bots/edit.rs index 6c454e13..70e72632 100644 --- a/crates/delta/src/routes/bots/edit.rs +++ b/crates/delta/src/routes/bots/edit.rs @@ -3,8 +3,7 @@ use revolt_models::v0::{self, DataEditBot}; use revolt_result::{create_error, Result}; use rocket::State; -use rocket::serde::json::Json; -use validator::Validate; +use crate::util::json::{Json, Validate}; /// # Edit Bot /// @@ -15,14 +14,9 @@ pub async fn edit_bot( db: &State, user: User, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut bot = target.as_bot(db).await?; if bot.owner != user.id { diff --git a/crates/delta/src/routes/bots/fetch.rs b/crates/delta/src/routes/bots/fetch.rs index 586ce124..af195072 100644 --- a/crates/delta/src/routes/bots/fetch.rs +++ b/crates/delta/src/routes/bots/fetch.rs @@ -1,7 +1,8 @@ use revolt_database::{util::reference::Reference, Database, User}; use revolt_models::v0::FetchBotResponse; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Bot /// diff --git a/crates/delta/src/routes/bots/fetch_owned.rs b/crates/delta/src/routes/bots/fetch_owned.rs index 9eb320ef..d6b200c4 100644 --- a/crates/delta/src/routes/bots/fetch_owned.rs +++ b/crates/delta/src/routes/bots/fetch_owned.rs @@ -2,7 +2,7 @@ use futures::future::join_all; use revolt_database::{Database, User}; use revolt_models::v0::OwnedBotsResponse; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Fetch Owned Bots diff --git a/crates/delta/src/routes/bots/fetch_public.rs b/crates/delta/src/routes/bots/fetch_public.rs index 7ad97e00..1d130de4 100644 --- a/crates/delta/src/routes/bots/fetch_public.rs +++ b/crates/delta/src/routes/bots/fetch_public.rs @@ -2,7 +2,7 @@ use revolt_database::{util::reference::Reference, Database, User}; use revolt_models::v0::PublicBot; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Fetch Public Bot diff --git a/crates/delta/src/routes/bots/invite.rs b/crates/delta/src/routes/bots/invite.rs index 39517c51..684021da 100644 --- a/crates/delta/src/routes/bots/invite.rs +++ b/crates/delta/src/routes/bots/invite.rs @@ -8,7 +8,7 @@ use revolt_permissions::{ use revolt_result::{create_error, Result}; use rocket::State; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket_empty::EmptyResponse; /// # Invite Bot diff --git a/crates/delta/src/routes/channels/channel_edit.rs b/crates/delta/src/routes/channels/channel_edit.rs index 881656f6..e47cd299 100644 --- a/crates/delta/src/routes/channels/channel_edit.rs +++ b/crates/delta/src/routes/channels/channel_edit.rs @@ -5,8 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Edit Channel /// @@ -18,14 +18,9 @@ pub async fn edit( amqp: &State, user: User, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut channel = target.as_channel(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).channel(&channel); diff --git a/crates/delta/src/routes/channels/channel_fetch.rs b/crates/delta/src/routes/channels/channel_fetch.rs index b08239bb..95e4fff5 100644 --- a/crates/delta/src/routes/channels/channel_fetch.rs +++ b/crates/delta/src/routes/channels/channel_fetch.rs @@ -6,7 +6,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Channel /// diff --git a/crates/delta/src/routes/channels/group_create.rs b/crates/delta/src/routes/channels/group_create.rs index bf6387c5..b8d36232 100644 --- a/crates/delta/src/routes/channels/group_create.rs +++ b/crates/delta/src/routes/channels/group_create.rs @@ -2,9 +2,8 @@ use revolt_database::{Channel, Database, RelationshipStatus, User}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::{Json, Validate}; use rocket::State; -use validator::Validate; /// # Create Group /// @@ -14,18 +13,13 @@ use validator::Validate; pub async fn create_group( db: &State, user: User, - data: Json, + data: Validate>, ) -> Result> { if user.bot.is_some() { return Err(create_error!(IsBot)); } - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); for target in &data.users { match user.relationship_with(target) { diff --git a/crates/delta/src/routes/channels/invite_create.rs b/crates/delta/src/routes/channels/invite_create.rs index 104f3398..be9d0cbc 100644 --- a/crates/delta/src/routes/channels/invite_create.rs +++ b/crates/delta/src/routes/channels/invite_create.rs @@ -6,7 +6,8 @@ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Create Invite /// diff --git a/crates/delta/src/routes/channels/members_fetch.rs b/crates/delta/src/routes/channels/members_fetch.rs index dc681519..2871e911 100644 --- a/crates/delta/src/routes/channels/members_fetch.rs +++ b/crates/delta/src/routes/channels/members_fetch.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Group Members /// diff --git a/crates/delta/src/routes/channels/message_bulk_delete.rs b/crates/delta/src/routes/channels/message_bulk_delete.rs index fdd538ff..34f0bfeb 100644 --- a/crates/delta/src/routes/channels/message_bulk_delete.rs +++ b/crates/delta/src/routes/channels/message_bulk_delete.rs @@ -6,9 +6,9 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; use rocket_empty::EmptyResponse; -use validator::Validate; +use crate::util::json::{Json, Validate}; /// # Bulk Delete Messages /// @@ -23,14 +23,9 @@ pub async fn bulk_delete_messages( db: &State, user: User, target: Reference<'_>, - options: Json, + options: Validate>, ) -> Result { - let options = options.into_inner(); - options.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let options = options.into_inner().into_inner(); for id in &options.ids { if ulid::Ulid::from_string(id) diff --git a/crates/delta/src/routes/channels/message_edit.rs b/crates/delta/src/routes/channels/message_edit.rs index 53426ec0..95e51c5e 100644 --- a/crates/delta/src/routes/channels/message_edit.rs +++ b/crates/delta/src/routes/channels/message_edit.rs @@ -7,8 +7,8 @@ use revolt_database::{ use revolt_models::v0::{self, Embed}; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Edit Message /// @@ -20,14 +20,9 @@ pub async fn edit( user: User, target: Reference<'_>, msg: Reference<'_>, - edit: Json, + edit: Validate>, ) -> Result> { - let edit = edit.into_inner(); - edit.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let edit = edit.into_inner().into_inner(); Message::validate_sum( &edit.content, diff --git a/crates/delta/src/routes/channels/message_fetch.rs b/crates/delta/src/routes/channels/message_fetch.rs index 8f09d47f..23d76139 100644 --- a/crates/delta/src/routes/channels/message_fetch.rs +++ b/crates/delta/src/routes/channels/message_fetch.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Message /// diff --git a/crates/delta/src/routes/channels/message_query.rs b/crates/delta/src/routes/channels/message_query.rs index 27df85e4..867869a9 100644 --- a/crates/delta/src/routes/channels/message_query.rs +++ b/crates/delta/src/routes/channels/message_query.rs @@ -5,8 +5,8 @@ use revolt_database::{ use revolt_models::v0::{self, MessageSort}; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Fetch Messages /// @@ -17,14 +17,8 @@ pub async fn query( db: &State, user: User, target: Reference<'_>, - options: v0::OptionsQueryMessages, + options: Validate, ) -> Result> { - options.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; - if let Some(MessageSort::Relevance) = options.sort { return Err(create_error!(InvalidOperation)); } @@ -43,7 +37,7 @@ pub async fn query( sort, nearby, include_users, - } = options; + } = options.into_inner(); Message::fetch_with_users( db, diff --git a/crates/delta/src/routes/channels/message_search.rs b/crates/delta/src/routes/channels/message_search.rs index 85676823..ca8374c0 100644 --- a/crates/delta/src/routes/channels/message_search.rs +++ b/crates/delta/src/routes/channels/message_search.rs @@ -5,8 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Search for Messages /// @@ -17,18 +17,13 @@ pub async fn search( db: &State, user: User, target: Reference<'_>, - options: Json, + options: Validate>, ) -> Result> { if user.bot.is_some() { return Err(create_error!(IsBot)); } - let options = options.into_inner(); - options.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let options = options.into_inner().into_inner(); if options.query.is_some() && options.pinned.is_some() { return Err(create_error!(InvalidOperation)) diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index e20438a9..b44372d5 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -7,10 +7,9 @@ use revolt_database::{Interactions, Message, AMQP}; use revolt_models::v0; use revolt_permissions::PermissionQuery; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; -use revolt_result::{create_error, Result}; +use revolt_result::Result; use crate::util::json::{Json, Validate}; use rocket::State; -// use validator::Validate; /// # Send Message /// @@ -25,7 +24,7 @@ pub async fn message_send( data: Validate>, idempotency: IdempotencyKey, ) -> Result> { - let data = data.into_inner(); + let data = data.into_inner().into_inner(); // Ensure we have permissions to send a message let channel = target.as_channel(db).await?; diff --git a/crates/delta/src/routes/channels/permissions_set.rs b/crates/delta/src/routes/channels/permissions_set.rs index ee42e403..55a3c448 100644 --- a/crates/delta/src/routes/channels/permissions_set.rs +++ b/crates/delta/src/routes/channels/permissions_set.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission, Override}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Set Role Permission /// diff --git a/crates/delta/src/routes/channels/permissions_set_default.rs b/crates/delta/src/routes/channels/permissions_set_default.rs index 700b29e4..f0e07b0f 100644 --- a/crates/delta/src/routes/channels/permissions_set_default.rs +++ b/crates/delta/src/routes/channels/permissions_set_default.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0::{self, DataDefaultChannelPermissions}; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Set Default Permission /// diff --git a/crates/delta/src/routes/channels/voice_join.rs b/crates/delta/src/routes/channels/voice_join.rs index c04e0011..061fa031 100644 --- a/crates/delta/src/routes/channels/voice_join.rs +++ b/crates/delta/src/routes/channels/voice_join.rs @@ -6,7 +6,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Join Call /// diff --git a/crates/delta/src/routes/channels/webhook_create.rs b/crates/delta/src/routes/channels/webhook_create.rs index 71f8e8de..e1f7143f 100644 --- a/crates/delta/src/routes/channels/webhook_create.rs +++ b/crates/delta/src/routes/channels/webhook_create.rs @@ -7,9 +7,9 @@ use revolt_permissions::{ calculate_channel_permissions, ChannelPermission, DEFAULT_WEBHOOK_PERMISSIONS, }; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::{Json, Validate}; use ulid::Ulid; -use validator::Validate; /// # Creates a webhook /// @@ -20,14 +20,9 @@ pub async fn create_webhook( db: &State, user: User, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let channel = target.as_channel(db).await?; diff --git a/crates/delta/src/routes/channels/webhook_fetch_all.rs b/crates/delta/src/routes/channels/webhook_fetch_all.rs index 4c4fdfd8..76c3b73a 100644 --- a/crates/delta/src/routes/channels/webhook_fetch_all.rs +++ b/crates/delta/src/routes/channels/webhook_fetch_all.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0::Webhook; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Gets all webhooks /// diff --git a/crates/delta/src/routes/customisation/emoji_create.rs b/crates/delta/src/routes/customisation/emoji_create.rs index d8288dae..7efde298 100644 --- a/crates/delta/src/routes/customisation/emoji_create.rs +++ b/crates/delta/src/routes/customisation/emoji_create.rs @@ -3,9 +3,8 @@ use revolt_database::{util::permissions::DatabasePermissionQuery, Database, Emoj use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use validator::Validate; - -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Create New Emoji /// @@ -16,16 +15,11 @@ pub async fn create_emoji( db: &State, user: User, id: String, - data: Json, + data: Validate>, ) -> Result> { let config = config().await; - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); // Validate we have permission to write into parent match &data.parent { diff --git a/crates/delta/src/routes/customisation/emoji_fetch.rs b/crates/delta/src/routes/customisation/emoji_fetch.rs index cdc9aaed..ecc5d8a9 100644 --- a/crates/delta/src/routes/customisation/emoji_fetch.rs +++ b/crates/delta/src/routes/customisation/emoji_fetch.rs @@ -2,7 +2,8 @@ use revolt_database::{util::reference::Reference, Database}; use revolt_models::v0; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Emoji /// diff --git a/crates/delta/src/routes/invites/invite_fetch.rs b/crates/delta/src/routes/invites/invite_fetch.rs index 7c44d4ae..ff8c84d7 100644 --- a/crates/delta/src/routes/invites/invite_fetch.rs +++ b/crates/delta/src/routes/invites/invite_fetch.rs @@ -1,7 +1,8 @@ use revolt_database::{util::reference::Reference, Channel, Database, Invite}; use revolt_models::v0; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Invite /// diff --git a/crates/delta/src/routes/invites/invite_join.rs b/crates/delta/src/routes/invites/invite_join.rs index a18213f3..93abdc1d 100644 --- a/crates/delta/src/routes/invites/invite_join.rs +++ b/crates/delta/src/routes/invites/invite_join.rs @@ -1,7 +1,8 @@ use revolt_database::{util::reference::Reference, Channel, Database, Invite, Member, User, AMQP}; use revolt_models::v0::{self, InviteJoinResponse}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Join Invite /// diff --git a/crates/delta/src/routes/onboard/complete.rs b/crates/delta/src/routes/onboard/complete.rs index e3621a19..3bfc9cfb 100644 --- a/crates/delta/src/routes/onboard/complete.rs +++ b/crates/delta/src/routes/onboard/complete.rs @@ -1,27 +1,11 @@ use authifier::models::Session; -use once_cell::sync::Lazy; -use regex::Regex; use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use serde::{Deserialize, Serialize}; -use validator::Validate; +use rocket::State; +use crate::util::json::{Json, Validate}; -/// Regex for valid usernames -/// -/// Block zero width space -/// Block lookalike characters -pub static RE_USERNAME: Lazy = Lazy::new(|| Regex::new(r"^(\p{L}|[\d_.-])+$").unwrap()); - -/// # New User Data -#[derive(Validate, Serialize, Deserialize, JsonSchema)] -pub struct DataOnboard { - /// New username which will be used to identify the user on the platform - #[validate(length(min = 2, max = 32), regex = "RE_USERNAME")] - username: String, -} /// # Complete Onboarding /// @@ -32,18 +16,13 @@ pub async fn complete( db: &State, session: Session, user: Option, - data: Json, + data: Validate>, ) -> Result> { if user.is_some() { return Err(create_error!(AlreadyOnboarded)); } - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); Ok(Json( User::create(db, data.username, session.user_id, None) diff --git a/crates/delta/src/routes/onboard/hello.rs b/crates/delta/src/routes/onboard/hello.rs index 92a0a8dd..35f3888e 100644 --- a/crates/delta/src/routes/onboard/hello.rs +++ b/crates/delta/src/routes/onboard/hello.rs @@ -1,23 +1,16 @@ use authifier::models::Session; use revolt_database::User; +use revolt_models::v0; -use rocket::serde::json::Json; -use serde::Serialize; - -/// # Onboarding Status -#[derive(Serialize, JsonSchema)] -pub struct DataHello { - /// Whether onboarding is required - onboarding: bool, -} +use crate::util::json::Json; /// # Check Onboarding Status /// /// This will tell you whether the current account requires onboarding or whether you can continue to send requests as usual. You may skip calling this if you're restoring an existing session. #[openapi(tag = "Onboarding")] #[get("/hello")] -pub async fn hello(_session: Session, user: Option) -> Json { - Json(DataHello { +pub async fn hello(_session: Session, user: Option) -> Json { + Json(v0::DataHello { onboarding: user.is_none(), }) } diff --git a/crates/delta/src/routes/push/subscribe.rs b/crates/delta/src/routes/push/subscribe.rs index 0d3d09e4..f42a889a 100644 --- a/crates/delta/src/routes/push/subscribe.rs +++ b/crates/delta/src/routes/push/subscribe.rs @@ -3,7 +3,8 @@ use authifier::{ Authifier, }; use revolt_result::{create_database_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; use rocket_empty::EmptyResponse; /// # Push Subscribe diff --git a/crates/delta/src/routes/root.rs b/crates/delta/src/routes/root.rs index c90c53c0..e2159f64 100644 --- a/crates/delta/src/routes/root.rs +++ b/crates/delta/src/routes/root.rs @@ -1,6 +1,6 @@ +use crate::util::json::Json; use revolt_config::config; use revolt_result::Result; -use rocket::serde::json::Json; use serde::Serialize; /// # hCaptcha Configuration diff --git a/crates/delta/src/routes/safety/report_content.rs b/crates/delta/src/routes/safety/report_content.rs index 1d5c2356..ce08057a 100644 --- a/crates/delta/src/routes/safety/report_content.rs +++ b/crates/delta/src/routes/safety/report_content.rs @@ -1,22 +1,9 @@ use revolt_database::{events::client::EventV1, Database, Report, Snapshot, SnapshotContent, User}; -use revolt_models::v0::{ReportStatus, ReportedContent}; +use revolt_models::v0::{DataReportContent, ReportStatus, ReportedContent}; use revolt_result::{create_error, Result}; -use serde::Deserialize; use ulid::Ulid; -use validator::Validate; - -use rocket::{serde::json::Json, State}; - -/// # Report Data -#[derive(Validate, Deserialize, JsonSchema)] -pub struct DataReportContent { - /// Content being reported - content: ReportedContent, - /// Additional report description - #[validate(length(min = 0, max = 1000))] - #[serde(default)] - additional_context: String, -} +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Report Content /// @@ -26,14 +13,9 @@ pub struct DataReportContent { pub async fn report_content( db: &State, user: User, - data: Json, + data: Validate>, ) -> Result<()> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); // Bots cannot create reports if user.bot.is_some() { diff --git a/crates/delta/src/routes/servers/ban_create.rs b/crates/delta/src/routes/servers/ban_create.rs index 13c0ef3b..1eafed6f 100644 --- a/crates/delta/src/routes/servers/ban_create.rs +++ b/crates/delta/src/routes/servers/ban_create.rs @@ -6,8 +6,8 @@ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use rocket::State; +use crate::util::json::{Json, Validate}; /// # Ban User /// @@ -19,14 +19,9 @@ pub async fn ban( user: User, server: Reference<'_>, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let server = server.as_server(db).await?; diff --git a/crates/delta/src/routes/servers/ban_list.rs b/crates/delta/src/routes/servers/ban_list.rs index 827e7dc3..718a5c44 100644 --- a/crates/delta/src/routes/servers/ban_list.rs +++ b/crates/delta/src/routes/servers/ban_list.rs @@ -6,7 +6,7 @@ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Fetch Bans diff --git a/crates/delta/src/routes/servers/channel_create.rs b/crates/delta/src/routes/servers/channel_create.rs index 53aa616d..50d2e125 100644 --- a/crates/delta/src/routes/servers/channel_create.rs +++ b/crates/delta/src/routes/servers/channel_create.rs @@ -2,11 +2,10 @@ use revolt_database::util::permissions::DatabasePermissionQuery; use revolt_database::{util::reference::Reference, Channel, Database, User}; use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; -use revolt_result::{create_error, Result}; +use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::{Json, Validate}; use rocket::State; -use validator::Validate; /// # Create Channel /// @@ -17,14 +16,9 @@ pub async fn create_server_channel( db: &State, user: User, server: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut server = server.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/emoji_list.rs b/crates/delta/src/routes/servers/emoji_list.rs index bd19c73e..ee2ded82 100644 --- a/crates/delta/src/routes/servers/emoji_list.rs +++ b/crates/delta/src/routes/servers/emoji_list.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::PermissionQuery; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Server Emoji /// diff --git a/crates/delta/src/routes/servers/invites_fetch.rs b/crates/delta/src/routes/servers/invites_fetch.rs index b6314207..bda750cc 100644 --- a/crates/delta/src/routes/servers/invites_fetch.rs +++ b/crates/delta/src/routes/servers/invites_fetch.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Invites /// diff --git a/crates/delta/src/routes/servers/member_edit.rs b/crates/delta/src/routes/servers/member_edit.rs index e33935e8..9a095751 100644 --- a/crates/delta/src/routes/servers/member_edit.rs +++ b/crates/delta/src/routes/servers/member_edit.rs @@ -8,8 +8,8 @@ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Edit Member /// @@ -21,14 +21,9 @@ pub async fn edit( user: User, server: Reference<'_>, member: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); // Fetch server and member let mut server = server.as_server(db).await?; diff --git a/crates/delta/src/routes/servers/member_experimental_query.rs b/crates/delta/src/routes/servers/member_experimental_query.rs index 8126b9f2..e42976b9 100644 --- a/crates/delta/src/routes/servers/member_experimental_query.rs +++ b/crates/delta/src/routes/servers/member_experimental_query.rs @@ -6,27 +6,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::PermissionQuery; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use serde::{Deserialize, Serialize}; - -/// # Query Parameters -#[derive(Deserialize, JsonSchema, FromForm)] -pub struct OptionsQueryMembers { - /// String to search for - query: String, - - /// Discourage use of this API - experimental_api: bool, -} - -/// # Query members by name -#[derive(Serialize, JsonSchema)] -pub struct MemberQueryResponse { - /// List of members - members: Vec, - /// List of users - users: Vec, -} +use rocket::State; +use crate::util::json::Json; /// # Query members by name /// @@ -37,8 +18,8 @@ pub async fn member_experimental_query( db: &State, user: User, target: Reference<'_>, - options: OptionsQueryMembers, -) -> Result> { + options: v0::OptionsQueryMembers, +) -> Result> { if !options.experimental_api { return Err(create_error!(InternalError)); } @@ -84,7 +65,7 @@ pub async fn member_experimental_query( // Take the first ten and return them let (members, users): (Vec, Vec) = zipped_vec.into_iter().take(10).unzip(); - Ok(Json(MemberQueryResponse { + Ok(Json(v0::MemberQueryResponse { members: members.into_iter().map(Into::into).collect(), users: join_all( users diff --git a/crates/delta/src/routes/servers/member_fetch.rs b/crates/delta/src/routes/servers/member_fetch.rs index c05935be..59a2a71a 100644 --- a/crates/delta/src/routes/servers/member_fetch.rs +++ b/crates/delta/src/routes/servers/member_fetch.rs @@ -1,3 +1,4 @@ +use crate::util::json::Json; use revolt_database::{ util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, User, @@ -5,7 +6,7 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::PermissionQuery; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; /// # Fetch Member /// diff --git a/crates/delta/src/routes/servers/member_fetch_all.rs b/crates/delta/src/routes/servers/member_fetch_all.rs index cc85b968..f89ab238 100644 --- a/crates/delta/src/routes/servers/member_fetch_all.rs +++ b/crates/delta/src/routes/servers/member_fetch_all.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::PermissionQuery; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Members /// diff --git a/crates/delta/src/routes/servers/permissions_set.rs b/crates/delta/src/routes/servers/permissions_set.rs index f0d8099f..88283b68 100644 --- a/crates/delta/src/routes/servers/permissions_set.rs +++ b/crates/delta/src/routes/servers/permissions_set.rs @@ -1,3 +1,4 @@ +use crate::util::json::Json; use revolt_database::{ util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, User, @@ -5,7 +6,7 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission, Override}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; /// # Set Role Permission /// diff --git a/crates/delta/src/routes/servers/permissions_set_default.rs b/crates/delta/src/routes/servers/permissions_set_default.rs index 6ee5b813..6fd4ec3d 100644 --- a/crates/delta/src/routes/servers/permissions_set_default.rs +++ b/crates/delta/src/routes/servers/permissions_set_default.rs @@ -7,7 +7,8 @@ use revolt_permissions::{ calculate_server_permissions, ChannelPermission, DataPermissionsValue, Override, }; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Set Default Permission /// diff --git a/crates/delta/src/routes/servers/roles_create.rs b/crates/delta/src/routes/servers/roles_create.rs index e68d5ea6..7b3e638b 100644 --- a/crates/delta/src/routes/servers/roles_create.rs +++ b/crates/delta/src/routes/servers/roles_create.rs @@ -6,8 +6,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Create Role /// @@ -18,14 +18,9 @@ pub async fn create( db: &State, user: User, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let server = target.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/roles_edit.rs b/crates/delta/src/routes/servers/roles_edit.rs index f18bd7d3..630d7c26 100644 --- a/crates/delta/src/routes/servers/roles_edit.rs +++ b/crates/delta/src/routes/servers/roles_edit.rs @@ -5,8 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Edit Role /// @@ -18,14 +18,9 @@ pub async fn edit( user: User, target: Reference<'_>, role_id: String, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut server = target.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/roles_edit_positions.rs b/crates/delta/src/routes/servers/roles_edit_positions.rs index d27259e5..1a46996e 100644 --- a/crates/delta/src/routes/servers/roles_edit_positions.rs +++ b/crates/delta/src/routes/servers/roles_edit_positions.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Edits server roles ranks /// diff --git a/crates/delta/src/routes/servers/roles_fetch.rs b/crates/delta/src/routes/servers/roles_fetch.rs index d26365a9..d2903b6f 100644 --- a/crates/delta/src/routes/servers/roles_fetch.rs +++ b/crates/delta/src/routes/servers/roles_fetch.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::PermissionQuery; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Role /// diff --git a/crates/delta/src/routes/servers/server_create.rs b/crates/delta/src/routes/servers/server_create.rs index 82f0a8aa..e740ea71 100644 --- a/crates/delta/src/routes/servers/server_create.rs +++ b/crates/delta/src/routes/servers/server_create.rs @@ -2,9 +2,8 @@ use revolt_database::{Database, Member, Server, User}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::{Json, Validate}; use rocket::State; -use validator::Validate; /// # Create Server /// @@ -14,18 +13,13 @@ use validator::Validate; pub async fn create_server( db: &State, user: User, - data: Json, + data: Validate>, ) -> Result> { if user.bot.is_some() { return Err(create_error!(IsBot)); } - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); user.can_acquire_server(db).await?; diff --git a/crates/delta/src/routes/servers/server_edit.rs b/crates/delta/src/routes/servers/server_edit.rs index 23d79c34..7b7fc921 100644 --- a/crates/delta/src/routes/servers/server_edit.rs +++ b/crates/delta/src/routes/servers/server_edit.rs @@ -7,8 +7,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_server_permissions, ChannelPermission}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Edit Server /// @@ -19,14 +19,9 @@ pub async fn edit( db: &State, user: User, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut server = target.as_server(db).await?; let mut query = DatabasePermissionQuery::new(db, &user).server(&server); diff --git a/crates/delta/src/routes/servers/server_fetch.rs b/crates/delta/src/routes/servers/server_fetch.rs index 82eb0c7c..7a058602 100644 --- a/crates/delta/src/routes/servers/server_fetch.rs +++ b/crates/delta/src/routes/servers/server_fetch.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_channel_permissions, ChannelPermission, PermissionQuery}; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Server /// diff --git a/crates/delta/src/routes/sync/get_settings.rs b/crates/delta/src/routes/sync/get_settings.rs index 12302925..e8bb73cb 100644 --- a/crates/delta/src/routes/sync/get_settings.rs +++ b/crates/delta/src/routes/sync/get_settings.rs @@ -1,7 +1,7 @@ use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Fetch Settings diff --git a/crates/delta/src/routes/sync/get_unreads.rs b/crates/delta/src/routes/sync/get_unreads.rs index 90efcf68..6422e21e 100644 --- a/crates/delta/src/routes/sync/get_unreads.rs +++ b/crates/delta/src/routes/sync/get_unreads.rs @@ -1,7 +1,7 @@ use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Fetch Unreads diff --git a/crates/delta/src/routes/sync/set_settings.rs b/crates/delta/src/routes/sync/set_settings.rs index 361d5871..82ff2ad7 100644 --- a/crates/delta/src/routes/sync/set_settings.rs +++ b/crates/delta/src/routes/sync/set_settings.rs @@ -3,7 +3,8 @@ use revolt_models::v0; use chrono::prelude::*; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; use rocket_empty::EmptyResponse; use std::collections::HashMap; diff --git a/crates/delta/src/routes/users/add_friend.rs b/crates/delta/src/routes/users/add_friend.rs index 946c3296..9a88a894 100644 --- a/crates/delta/src/routes/users/add_friend.rs +++ b/crates/delta/src/routes/users/add_friend.rs @@ -2,7 +2,7 @@ use revolt_database::util::reference::Reference; use revolt_database::{Database, User, AMQP}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Accept Friend Request diff --git a/crates/delta/src/routes/users/block_user.rs b/crates/delta/src/routes/users/block_user.rs index cfce993c..472fa8f1 100644 --- a/crates/delta/src/routes/users/block_user.rs +++ b/crates/delta/src/routes/users/block_user.rs @@ -2,7 +2,7 @@ use revolt_database::util::reference::Reference; use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Block User diff --git a/crates/delta/src/routes/users/change_username.rs b/crates/delta/src/routes/users/change_username.rs index 7c3f98c9..066c9ec0 100644 --- a/crates/delta/src/routes/users/change_username.rs +++ b/crates/delta/src/routes/users/change_username.rs @@ -1,29 +1,9 @@ use authifier::models::Account; -use once_cell::sync::Lazy; -use regex::Regex; use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use serde::{Deserialize, Serialize}; -use validator::Validate; - -/// Regex for valid usernames -/// -/// Block zero width space -/// Block lookalike characters -pub static RE_USERNAME: Lazy = Lazy::new(|| Regex::new(r"^(\p{L}|[\d_.-])+$").unwrap()); - -/// # Username Information -#[derive(Validate, Serialize, Deserialize, JsonSchema)] -pub struct DataChangeUsername { - /// New username - #[validate(length(min = 2, max = 32), regex = "RE_USERNAME")] - username: String, - /// Current account password - #[validate(length(min = 8, max = 1024))] - password: String, -} +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Change Username /// @@ -34,14 +14,9 @@ pub async fn change_username( db: &State, account: Account, mut user: User, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); account .verify_password(&data.password) diff --git a/crates/delta/src/routes/users/edit_user.rs b/crates/delta/src/routes/users/edit_user.rs index 535fc05c..ac2f8b2b 100644 --- a/crates/delta/src/routes/users/edit_user.rs +++ b/crates/delta/src/routes/users/edit_user.rs @@ -2,9 +2,8 @@ use revolt_database::FieldsUser; use revolt_database::{util::reference::Reference, Database, File, PartialUser, User}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::{Json, Validate}; use rocket::State; -use validator::Validate; /// # Edit User /// @@ -15,14 +14,9 @@ pub async fn edit( db: &State, mut user: User, target: Reference<'_>, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); // Filter out invalid edit fields if !user.privileged && (data.badges.is_some() || data.flags.is_some()) { diff --git a/crates/delta/src/routes/users/fetch_dms.rs b/crates/delta/src/routes/users/fetch_dms.rs index d0b39e63..d4715c71 100644 --- a/crates/delta/src/routes/users/fetch_dms.rs +++ b/crates/delta/src/routes/users/fetch_dms.rs @@ -1,7 +1,8 @@ use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch Direct Message Channels /// diff --git a/crates/delta/src/routes/users/fetch_profile.rs b/crates/delta/src/routes/users/fetch_profile.rs index e0718d4b..5a9fabf4 100644 --- a/crates/delta/src/routes/users/fetch_profile.rs +++ b/crates/delta/src/routes/users/fetch_profile.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_user_permissions, UserPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch User Profile /// diff --git a/crates/delta/src/routes/users/fetch_self.rs b/crates/delta/src/routes/users/fetch_self.rs index 02257be9..e1edd0d0 100755 --- a/crates/delta/src/routes/users/fetch_self.rs +++ b/crates/delta/src/routes/users/fetch_self.rs @@ -1,7 +1,7 @@ use revolt_database::User; use revolt_models::v0; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; /// # Fetch Self /// diff --git a/crates/delta/src/routes/users/fetch_user.rs b/crates/delta/src/routes/users/fetch_user.rs index e6aba68e..9d136606 100644 --- a/crates/delta/src/routes/users/fetch_user.rs +++ b/crates/delta/src/routes/users/fetch_user.rs @@ -6,7 +6,8 @@ use revolt_models::v0; use revolt_permissions::{calculate_user_permissions, UserPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch User /// diff --git a/crates/delta/src/routes/users/fetch_user_flags.rs b/crates/delta/src/routes/users/fetch_user_flags.rs index df021abb..d834880f 100644 --- a/crates/delta/src/routes/users/fetch_user_flags.rs +++ b/crates/delta/src/routes/users/fetch_user_flags.rs @@ -1,7 +1,8 @@ use revolt_database::{util::reference::Reference, Database}; use revolt_models::v0; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Fetch User Flags /// diff --git a/crates/delta/src/routes/users/find_mutual.rs b/crates/delta/src/routes/users/find_mutual.rs index 9f7fd950..3004de43 100644 --- a/crates/delta/src/routes/users/find_mutual.rs +++ b/crates/delta/src/routes/users/find_mutual.rs @@ -5,7 +5,7 @@ use revolt_models::v0; use revolt_permissions::{calculate_user_permissions, UserPermission}; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Fetch Mutual Friends And Servers diff --git a/crates/delta/src/routes/users/open_dm.rs b/crates/delta/src/routes/users/open_dm.rs index 78486523..eb161823 100644 --- a/crates/delta/src/routes/users/open_dm.rs +++ b/crates/delta/src/routes/users/open_dm.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0; use revolt_permissions::{calculate_user_permissions, UserPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Open Direct Message /// diff --git a/crates/delta/src/routes/users/remove_friend.rs b/crates/delta/src/routes/users/remove_friend.rs index 59b85ecb..c27f210d 100644 --- a/crates/delta/src/routes/users/remove_friend.rs +++ b/crates/delta/src/routes/users/remove_friend.rs @@ -2,7 +2,7 @@ use revolt_database::util::reference::Reference; use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Deny Friend Request / Remove Friend diff --git a/crates/delta/src/routes/users/send_friend_request.rs b/crates/delta/src/routes/users/send_friend_request.rs index a87334af..fb3378f8 100644 --- a/crates/delta/src/routes/users/send_friend_request.rs +++ b/crates/delta/src/routes/users/send_friend_request.rs @@ -2,7 +2,7 @@ use revolt_database::{Database, User, AMQP}; use revolt_models::v0; use revolt_result::{create_error, Result}; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Send Friend Request diff --git a/crates/delta/src/routes/users/unblock_user.rs b/crates/delta/src/routes/users/unblock_user.rs index a464ecc5..e34932fa 100644 --- a/crates/delta/src/routes/users/unblock_user.rs +++ b/crates/delta/src/routes/users/unblock_user.rs @@ -2,7 +2,7 @@ use revolt_database::util::reference::Reference; use revolt_database::{Database, User}; use revolt_models::v0; use revolt_result::Result; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::State; /// # Unblock User diff --git a/crates/delta/src/routes/webhooks/webhook_edit.rs b/crates/delta/src/routes/webhooks/webhook_edit.rs index aa06930a..daa6cc42 100644 --- a/crates/delta/src/routes/webhooks/webhook_edit.rs +++ b/crates/delta/src/routes/webhooks/webhook_edit.rs @@ -4,9 +4,9 @@ use revolt_database::{ }; use revolt_models::v0::{DataEditWebhook, Webhook}; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; -use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; -use validator::Validate; +use revolt_result::Result; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Edits a webhook /// @@ -17,14 +17,9 @@ pub async fn webhook_edit( db: &State, webhook_id: Reference<'_>, user: User, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut webhook = webhook_id.as_webhook(db).await?; let channel = db.fetch_channel(&webhook.channel_id).await?; diff --git a/crates/delta/src/routes/webhooks/webhook_edit_token.rs b/crates/delta/src/routes/webhooks/webhook_edit_token.rs index 4f4dde0d..ad6748d9 100644 --- a/crates/delta/src/routes/webhooks/webhook_edit_token.rs +++ b/crates/delta/src/routes/webhooks/webhook_edit_token.rs @@ -1,9 +1,9 @@ use revolt_database::util::reference::Reference; use revolt_database::{Database, File, PartialWebhook}; use revolt_models::v0::{DataEditWebhook, Webhook}; -use revolt_models::validator::Validate; -use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; +use revolt_result::Result; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Edits a webhook /// @@ -14,14 +14,9 @@ pub async fn webhook_edit_token( db: &State, webhook_id: Reference<'_>, token: String, - data: Json, + data: Validate>, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let mut webhook = webhook_id.as_webhook(db).await?; webhook.assert_token(&token)?; diff --git a/crates/delta/src/routes/webhooks/webhook_execute.rs b/crates/delta/src/routes/webhooks/webhook_execute.rs index f46004f7..2ff4baf7 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute.rs @@ -5,10 +5,9 @@ use revolt_database::{ }; use revolt_models::v0; use revolt_permissions::{ChannelPermission, PermissionValue}; -use revolt_result::{create_error, Result}; -use rocket::{serde::json::Json, State}; - -use validator::Validate; +use revolt_result::Result; +use crate::util::json::{Json, Validate}; +use rocket::State; /// # Executes a webhook /// @@ -20,15 +19,10 @@ pub async fn webhook_execute( amqp: &State, webhook_id: Reference<'_>, token: String, - data: Json, + data: Validate>, idempotency: IdempotencyKey, ) -> Result> { - let data = data.into_inner(); - data.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + let data = data.into_inner().into_inner(); let webhook = webhook_id.as_webhook(db).await?; webhook.assert_token(&token)?; diff --git a/crates/delta/src/routes/webhooks/webhook_execute_github.rs b/crates/delta/src/routes/webhooks/webhook_execute_github.rs index 7f2f475a..8d98efce 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute_github.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute_github.rs @@ -1,6 +1,6 @@ use revolt_database::{util::reference::Reference, Database, Message, AMQP}; use revolt_models::v0::{MessageAuthor, SendableEmbed, Webhook}; -use revolt_result::{create_error, Error, Result}; +use revolt_result::{create_error, Error, Result, ToRevoltError}; use revolt_rocket_okapi::{ gen::OpenApiGenerator, request::{OpenApiFromRequest, RequestHeaderInput}, @@ -1061,11 +1061,13 @@ pub async fn webhook_execute_github( }, }; - sendable_embed.validate().map_err(|error| { - create_error!(FailedValidation { - error: error.to_string() - }) - })?; + sendable_embed.validate() + .capture_error() + .map_err(|error| { + create_error!(FailedValidation { + error: error.to_string() + }) + })?; let message_id = Ulid::new().to_string(); diff --git a/crates/delta/src/routes/webhooks/webhook_fetch.rs b/crates/delta/src/routes/webhooks/webhook_fetch.rs index c8569e17..4f073d37 100644 --- a/crates/delta/src/routes/webhooks/webhook_fetch.rs +++ b/crates/delta/src/routes/webhooks/webhook_fetch.rs @@ -5,7 +5,8 @@ use revolt_database::{ use revolt_models::v0::{ResponseWebhook, Webhook}; use revolt_permissions::{calculate_channel_permissions, ChannelPermission}; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Gets a webhook /// diff --git a/crates/delta/src/routes/webhooks/webhook_fetch_token.rs b/crates/delta/src/routes/webhooks/webhook_fetch_token.rs index 70c95825..e8f8668d 100644 --- a/crates/delta/src/routes/webhooks/webhook_fetch_token.rs +++ b/crates/delta/src/routes/webhooks/webhook_fetch_token.rs @@ -1,7 +1,8 @@ use revolt_database::{util::reference::Reference, Database}; use revolt_models::v0::Webhook; use revolt_result::Result; -use rocket::{serde::json::Json, State}; +use rocket::State; +use crate::util::json::Json; /// # Gets a webhook /// diff --git a/crates/delta/src/util/json.rs b/crates/delta/src/util/json/json.rs similarity index 54% rename from crates/delta/src/util/json.rs rename to crates/delta/src/util/json/json.rs index f2c5a32e..1422d41a 100644 --- a/crates/delta/src/util/json.rs +++ b/crates/delta/src/util/json/json.rs @@ -2,16 +2,11 @@ use std::fmt::Debug; use revolt_rocket_okapi::{ r#gen::OpenApiGenerator, - response::OpenApiResponderInner, - revolt_okapi::openapi3::Responses, - util::add_schema_response, request::OpenApiFromData, - revolt_okapi::{ - openapi3::{MediaType, RequestBody}, - Map, - }, + response::OpenApiResponderInner, + revolt_okapi::openapi3::{RequestBody, Responses}, util::add_schema_response }; -use rocket::data::{Data, FromData, Limits, Outcome}; +use rocket::{data::{Data, FromData, Limits, Outcome}}; use rocket::response::{self, Responder, content}; use rocket::request::{local_cache, Request}; use schemars::JsonSchema; @@ -21,27 +16,6 @@ use revolt_result::{create_error, Error, ToRevoltError}; // A lot of this code is modified versions of rocket::serde::json so we can store // the error so it can be passed to the error catcher. -macro_rules! fn_request_body { - ($gen:ident, $ty:path, $mime_type:expr) => {{ - let schema = $gen.json_schema::<$ty>(); - Ok(RequestBody { - content: { - let mut map = Map::new(); - map.insert( - $mime_type.to_owned(), - MediaType { - schema: Some(schema), - ..MediaType::default() - }, - ); - map - }, - required: true, - ..revolt_rocket_okapi::revolt_okapi::openapi3::RequestBody::default() - }) - }}; -} - #[derive(Debug, Clone)] pub struct Json(pub T); @@ -107,11 +81,11 @@ impl<'r, T: Serialize> Responder<'r, 'static> for Json { impl<'r, T: JsonSchema + Deserialize<'r> + Debug> OpenApiFromData<'r> for Json { fn request_body(gen: &mut OpenApiGenerator) -> revolt_rocket_okapi::Result { - fn_request_body!(gen, T, "application/json") + crate::fn_request_body!(gen, T, "application/json") } } -impl OpenApiResponderInner for Json { +impl OpenApiResponderInner for Json { fn responses(gen: &mut OpenApiGenerator) -> revolt_rocket_okapi::Result { let mut responses = Responses::default(); let schema = gen.json_schema::(); @@ -125,52 +99,3 @@ impl validator::Validate for Json { self.0.validate() } } - -pub struct Validate(pub T); - -impl Validate> { - pub fn into_inner(self) -> T { - self.0.0 - } -} - -#[async_trait] -impl<'r, T: validator::Validate + Deserialize<'r> + Debug> FromData<'r> for Validate> { - type Error = Error; - - async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { - as FromData<'r>>::from_data(req, data).await.and_then(|inner| { - if let Err(e) = inner.validate() { - let error = create_error!(FailedValidation { error: e.to_string() }); - req.local_cache(|| Some(error.clone())); - - return Outcome::Error((error.rocket_status(), error)) - }; - - Outcome::Success(Self(inner)) - }) - } -} - -impl<'r, T: JsonSchema + Deserialize<'r> + validator::Validate + Debug> OpenApiFromData<'r> for Validate> { - fn request_body(gen: &mut OpenApiGenerator) -> revolt_rocket_okapi::Result { - fn_request_body!(gen, T, "application/json") - } -} - -impl OpenApiResponderInner for Validate> { - fn responses(gen: &mut OpenApiGenerator) -> revolt_rocket_okapi::Result { - let mut responses = Responses::default(); - let schema = gen.json_schema::(); - add_schema_response(&mut responses, 200, "application/json", schema)?; - Ok(responses) - } -} - -impl std::ops::Deref for Validate { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/crates/delta/src/util/json/mod.rs b/crates/delta/src/util/json/mod.rs new file mode 100644 index 00000000..862fbb91 --- /dev/null +++ b/crates/delta/src/util/json/mod.rs @@ -0,0 +1,27 @@ +pub mod json; +pub mod validator; + +pub use json::Json; +pub use validator::Validate; + +#[macro_export] +macro_rules! fn_request_body { + ($gen:ident, $ty:path, $mime_type:expr) => {{ + let schema = $gen.json_schema::<$ty>(); + Ok(revolt_rocket_okapi::revolt_okapi::openapi3::RequestBody { + content: { + let mut map = revolt_rocket_okapi::revolt_okapi::Map::new(); + map.insert( + $mime_type.to_owned(), + revolt_rocket_okapi::revolt_okapi::openapi3::MediaType { + schema: Some(schema), + ..Default::default() + }, + ); + map + }, + required: true, + ..Default::default() + }) + }}; +} \ No newline at end of file diff --git a/crates/delta/src/util/json/validator.rs b/crates/delta/src/util/json/validator.rs new file mode 100644 index 00000000..bad81f8f --- /dev/null +++ b/crates/delta/src/util/json/validator.rs @@ -0,0 +1,87 @@ +use revolt_rocket_okapi::{ + r#gen::OpenApiGenerator, + request::OpenApiFromData, + response::OpenApiResponderInner, + revolt_okapi::{openapi3::{RequestBody, Responses}}, +}; +use rocket::{data::{Data, FromData, Outcome}, form}; +use rocket::request::Request; +use schemars::JsonSchema; +use revolt_result::{create_error, Error}; + +pub struct Validate(pub T); + +impl Validate { + pub fn into_inner(self) -> T { + self.0 + } +} + +#[async_trait] +impl<'r, T: FromData<'r, Error = Error> + validator::Validate> FromData<'r> for Validate { + type Error = Error; + + async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { + T::from_data(req, data).await.and_then(|inner| { + if let Err(e) = inner.validate() { + let error = create_error!(FailedValidation { error: e.to_string() }); + req.local_cache(|| Some(error.clone())); + + return Outcome::Error((error.rocket_status(), error)) + }; + + Outcome::Success(Self(inner)) + }) + } +} + +#[async_trait] +impl<'r, T: form::FromForm<'r> + JsonSchema> form::FromForm<'r> for Validate { + type Context = T::Context; + + fn init(opts: form::Options) -> Self::Context { + >::init(opts) + } + + fn push_value(ctxt: &mut Self::Context, field: form::ValueField<'r>) { + >::push_value(ctxt, field); + } + + async fn push_data(ctxt: &mut Self::Context, field: form::DataField<'r, '_>) { + >::push_data(ctxt, field).await; + } + + fn finalize(ctxt: Self::Context) -> form::Result<'r, Self> { + >::finalize(ctxt).map(Self) + } +} + +impl<'r, T: FromData<'r, Error = Error> + OpenApiFromData<'r> + validator::Validate> OpenApiFromData<'r> for Validate { + fn request_body(gen: &mut OpenApiGenerator) -> revolt_rocket_okapi::Result { + T::request_body(gen) + } +} + +impl JsonSchema for Validate { + fn schema_name() -> String { + T::schema_name() + } + + fn json_schema(generator: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + T::json_schema(generator) + } +} + +impl OpenApiResponderInner for Validate { + fn responses(gen: &mut OpenApiGenerator) -> revolt_rocket_okapi::Result { + T::responses(gen) + } +} + +impl std::ops::Deref for Validate { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/crates/delta/src/util/ratelimiter.rs b/crates/delta/src/util/ratelimiter.rs index 5527ee42..25d45840 100644 --- a/crates/delta/src/util/ratelimiter.rs +++ b/crates/delta/src/util/ratelimiter.rs @@ -8,7 +8,7 @@ use rocket::fairing::{Fairing, Info, Kind}; use rocket::http::uri::Origin; use rocket::http::{Method, Status}; use rocket::request::{FromRequest, Outcome}; -use rocket::serde::json::Json; +use crate::util::json::Json; use rocket::{Data, Request, Response}; use revolt_rocket_okapi::gen::OpenApiGenerator;