feat: ratelimit user edit route and discriminator changes

This commit is contained in:
Paul Makles
2023-06-15 19:24:53 +01:00
parent c0ebaa0bd3
commit 49035f4817
21 changed files with 251 additions and 35 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "revolt-database"
version = "0.6.2"
version = "0.6.3"
edition = "2021"
license = "AGPL-3.0-or-later"
authors = [ "Paul Makles <me@insrt.uk>" ]
@@ -22,10 +22,10 @@ default = [ "mongodb", "async-std-runtime" ]
[dependencies]
# Core
revolt-result = { version = "0.6.2", path = "../result" }
revolt-models = { version = "0.6.2", path = "../models" }
revolt-presence = { version = "0.6.2", path = "../presence" }
revolt-permissions = { version = "0.6.2", path = "../permissions", features = [ "serde", "bson" ] }
revolt-result = { version = "0.6.3", path = "../result" }
revolt-models = { version = "0.6.3", path = "../models" }
revolt-presence = { version = "0.6.3", path = "../presence" }
revolt-permissions = { version = "0.6.3", path = "../permissions", features = [ "serde", "bson" ] }
# Utility
log = "0.4"

View File

@@ -76,6 +76,10 @@ pub async fn create_database(db: &MongoDb) {
.await
.expect("Failed to create bots collection.");
db.create_collection("ratelimit_events", None)
.await
.expect("Failed to create ratelimit_events collection.");
db.create_collection(
"pubsub",
CreateCollectionOptions::builder()
@@ -209,5 +213,24 @@ pub async fn create_database(db: &MongoDb) {
.await
.expect("Failed to save migration info.");
db.run_command(
doc! {
"createIndexes": "ratelimit_events",
"indexes": [
{
"key": {
"_id": 1_i32,
"target_id": 1_i32,
"event_type": 1_i32,
},
"name": "compound_key"
}
]
},
None,
)
.await
.expect("Failed to create ratelimit_events index.");
info!("Created database.");
}

View File

@@ -18,7 +18,7 @@ struct MigrationInfo {
revision: i32,
}
pub const LATEST_REVISION: i32 = 25;
pub const LATEST_REVISION: i32 = 26;
pub async fn migrate_database(db: &MongoDb) {
let migrations = db.col::<Document>("migrations");
@@ -947,8 +947,37 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
.expect("Failed to create username index.");
}
if revision <= 25 {
info!("Running migration [revision 25 / 15-06-2023]: Add collection `ratelimit_events` with index.");
db.db()
.create_collection("ratelimit_events", None)
.await
.ok();
db.db()
.run_command(
doc! {
"createIndexes": "ratelimit_events",
"indexes": [
{
"key": {
"_id": 1_i32,
"target_id": 1_i32,
"event_type": 1_i32,
},
"name": "compound_key"
}
]
},
None,
)
.await
.expect("Failed to create ratelimit_events index.");
}
// Need to migrate fields on attachments, change `user_id`, `object_id`, etc to `parent`.
// Reminder to update LATEST_REVISION when adding new migrations.
LATEST_REVISION
LATEST_REVISION.max(revision)
}

View File

@@ -3,6 +3,7 @@ mod bots;
mod channel_webhooks;
mod channels;
mod files;
mod ratelimit_events;
mod safety_strikes;
mod server_members;
mod servers;
@@ -14,6 +15,7 @@ pub use bots::*;
pub use channel_webhooks::*;
pub use channels::*;
pub use files::*;
pub use ratelimit_events::*;
pub use safety_strikes::*;
pub use server_members::*;
pub use servers::*;
@@ -30,6 +32,7 @@ pub trait AbstractDatabase:
+ channels::AbstractChannels
+ channel_webhooks::AbstractWebhooks
+ files::AbstractAttachments
+ ratelimit_events::AbstractRatelimitEvents
+ safety_strikes::AbstractAccountStrikes
+ server_members::AbstractServerMembers
+ servers::AbstractServers

View File

@@ -0,0 +1,5 @@
mod model;
mod ops;
pub use model::*;
pub use ops::*;

View File

@@ -0,0 +1,25 @@
use std::fmt;
auto_derived!(
/// Ratelimit Event
pub struct RatelimitEvent {
/// Id
#[serde(rename = "_id")]
pub id: String,
/// Relevant Object Id
pub target_id: String,
/// Type of event
pub event_type: RatelimitEventType,
}
/// Event type
pub enum RatelimitEventType {
DiscriminatorChange,
}
);
impl fmt::Display for RatelimitEventType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}

View File

@@ -0,0 +1,20 @@
use std::time::Duration;
use crate::{revolt_result::Result, RatelimitEvent, RatelimitEventType};
mod mongodb;
mod reference;
#[async_trait]
pub trait AbstractRatelimitEvents: Sync + Send {
/// Insert a new ratelimit event
async fn insert_ratelimit_event(&self, event: &RatelimitEvent) -> Result<()>;
/// Count number of events in given duration and check if we've hit the limit
async fn has_ratelimited(
&self,
target_id: &str,
event_type: RatelimitEventType,
period: Duration,
count: usize,
) -> Result<bool>;
}

View File

@@ -0,0 +1,40 @@
use std::time::{Duration, SystemTime};
use super::AbstractRatelimitEvents;
use crate::{MongoDb, RatelimitEvent, RatelimitEventType};
use revolt_result::Result;
use ulid::Ulid;
static COL: &str = "ratelimit_events";
#[async_trait]
impl AbstractRatelimitEvents for MongoDb {
/// Insert a new ratelimit event
async fn insert_ratelimit_event(&self, event: &RatelimitEvent) -> Result<()> {
query!(self, insert_one, COL, &event).map(|_| ())
}
/// Count number of events in given duration and check if we've hit the limit
async fn has_ratelimited(
&self,
target_id: &str,
event_type: RatelimitEventType,
period: Duration,
count: usize,
) -> Result<bool> {
self.col::<RatelimitEvent>(COL)
.count_documents(
doc! {
"_id": {
"$gte": Ulid::from_datetime(SystemTime::now() - period).to_string()
},
"target_id": target_id,
"event_type": event_type.to_string()
},
None,
)
.await
.map(|c| c as usize >= count)
.map_err(|_| create_database_error!("count_documents", COL))
}
}

View File

@@ -0,0 +1,28 @@
use std::time::Duration;
use super::AbstractRatelimitEvents;
use crate::RatelimitEvent;
use crate::RatelimitEventType;
use crate::ReferenceDb;
use revolt_result::Result;
#[async_trait]
impl AbstractRatelimitEvents for ReferenceDb {
/// Insert a new ratelimit event
async fn insert_ratelimit_event(&self, _event: &RatelimitEvent) -> Result<()> {
// TODO: implement
unimplemented!()
}
/// Count number of events in given duration and check if we've hit the limit
async fn has_ratelimited(
&self,
_target_id: &str,
_event_type: RatelimitEventType,
_period: Duration,
_count: usize,
) -> Result<bool> {
// TODO: implement
unimplemented!()
}
}

View File

@@ -1,6 +1,6 @@
[package]
name = "revolt-models"
version = "0.6.2"
version = "0.6.3"
edition = "2021"
license = "AGPL-3.0-or-later"
authors = [ "Paul Makles <me@insrt.uk>" ]
@@ -18,7 +18,7 @@ default = [ "serde", "partials" ]
[dependencies]
# Core
revolt-permissions = { version = "0.6.2", path = "../permissions" }
revolt-permissions = { version = "0.6.3", path = "../permissions" }
# Serialisation
revolt_optional_struct = { version = "0.2.0", optional = true }

View File

@@ -1,6 +1,6 @@
[package]
name = "revolt-permissions"
version = "0.6.2"
version = "0.6.3"
edition = "2021"
license = "AGPL-3.0-or-later"
authors = [ "Paul Makles <me@insrt.uk>" ]

View File

@@ -1,6 +1,6 @@
[package]
name = "revolt-presence"
version = "0.6.2"
version = "0.6.3"
edition = "2021"
license = "AGPL-3.0-or-later"
authors = [ "Paul Makles <me@insrt.uk>" ]

View File

@@ -1,6 +1,6 @@
[package]
name = "revolt-result"
version = "0.6.2"
version = "0.6.3"
edition = "2021"
license = "AGPL-3.0-or-later"
authors = [ "Paul Makles <me@insrt.uk>" ]