forked from jmug/stoatchat
Compare commits
13
Commits
20240210-1
...
20240212-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b18e983c9 | ||
|
|
c0e64c9052 | ||
|
|
0d54ccd342 | ||
|
|
d4d5b23c7d | ||
|
|
a641034895 | ||
|
|
9dd24526ef | ||
|
|
6d4f772d78 | ||
|
|
4c4dada3da | ||
|
|
cf82972a80 | ||
|
|
ea00f0fec1 | ||
|
|
226dbca6e0 | ||
|
|
e4b5a23f71 | ||
|
|
9663caa1ff |
@@ -57,7 +57,7 @@ jobs:
|
||||
env:
|
||||
TEST_DB: REFERENCE
|
||||
run: |
|
||||
cargo run --bin revolt-delta &
|
||||
cargo build --bin revolt-delta && (cargo run --bin revolt-delta &)
|
||||
|
||||
- name: Wait for API to go up
|
||||
if: github.event_name != 'pull_request' && github.ref_name == 'master'
|
||||
|
||||
Generated
+9
-9
@@ -3580,7 +3580,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-tungstenite",
|
||||
@@ -3600,7 +3600,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-config"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"cached",
|
||||
@@ -3612,7 +3612,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-database"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"async-recursion",
|
||||
@@ -3657,7 +3657,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-delta"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-std",
|
||||
@@ -3703,7 +3703,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-models"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"iso8601-timestamp 0.2.11",
|
||||
@@ -3719,7 +3719,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-permissions"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-trait",
|
||||
@@ -3734,7 +3734,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-presence"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"log",
|
||||
@@ -3745,7 +3745,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-quark"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"async-recursion",
|
||||
@@ -3798,7 +3798,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-result"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"revolt_okapi",
|
||||
"revolt_rocket_okapi",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
license = "AGPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
@@ -37,4 +37,4 @@ revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] }
|
||||
sentry = "0.31.5"
|
||||
|
||||
# redis
|
||||
fred = { version = "8.0.1", features = ["subscriber-client"] }
|
||||
fred = { version = "8.0.1", features = ["subscriber-client"] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-config"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-database"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -23,11 +23,11 @@ default = ["mongodb", "async-std-runtime", "tasks"]
|
||||
|
||||
[dependencies]
|
||||
# Core
|
||||
revolt-config = { version = "0.6.11", path = "../config" }
|
||||
revolt-result = { version = "0.6.11", path = "../result" }
|
||||
revolt-models = { version = "0.6.11", path = "../models" }
|
||||
revolt-presence = { version = "0.6.11", path = "../presence" }
|
||||
revolt-permissions = { version = "0.6.11", path = "../permissions", features = [
|
||||
revolt-config = { version = "0.6.13", path = "../config" }
|
||||
revolt-result = { version = "0.6.13", path = "../result" }
|
||||
revolt-models = { version = "0.6.13", path = "../models" }
|
||||
revolt-presence = { version = "0.6.13", path = "../presence" }
|
||||
revolt-permissions = { version = "0.6.13", path = "../permissions", features = [
|
||||
"serde",
|
||||
"bson",
|
||||
] }
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
[
|
||||
{
|
||||
"_object_type": "User",
|
||||
"_id": "__ID:0__",
|
||||
"username": "Owner",
|
||||
"discriminator": "0001"
|
||||
},
|
||||
{
|
||||
"_object_type": "User",
|
||||
"_id": "__ID:1__",
|
||||
"username": "Member",
|
||||
"discriminator": "0001"
|
||||
},
|
||||
{
|
||||
"_object_type": "User",
|
||||
"_id": "__ID:2__",
|
||||
"username": "Member",
|
||||
"discriminator": "0002"
|
||||
},
|
||||
{
|
||||
"_object_type": "Channel",
|
||||
"_id": "__ID:3__",
|
||||
"channel_type": "Group",
|
||||
"name": "My Group",
|
||||
"owner": "__ID:0__",
|
||||
"recipients": ["__ID:0__", "__ID:1__"]
|
||||
}
|
||||
]
|
||||
@@ -695,6 +695,32 @@ mod tests {
|
||||
|
||||
use crate::{fixture, util::permissions::DatabasePermissionQuery};
|
||||
|
||||
#[async_std::test]
|
||||
async fn permissions_group_channel() {
|
||||
database_test!(|db| async move {
|
||||
fixture!(db, "group_with_members",
|
||||
owner user 0
|
||||
member1 user 1
|
||||
member2 user 2
|
||||
channel channel 3);
|
||||
|
||||
let mut query = DatabasePermissionQuery::new(&db, &owner).channel(&channel);
|
||||
assert!(calculate_channel_permissions(&mut query)
|
||||
.await
|
||||
.has_channel_permission(ChannelPermission::SendMessage));
|
||||
|
||||
let mut query = DatabasePermissionQuery::new(&db, &member1).channel(&channel);
|
||||
assert!(calculate_channel_permissions(&mut query)
|
||||
.await
|
||||
.has_channel_permission(ChannelPermission::SendMessage));
|
||||
|
||||
let mut query = DatabasePermissionQuery::new(&db, &member2).channel(&channel);
|
||||
assert!(!calculate_channel_permissions(&mut query)
|
||||
.await
|
||||
.has_channel_permission(ChannelPermission::SendMessage));
|
||||
});
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn permissions_text_channel() {
|
||||
database_test!(|db| async move {
|
||||
|
||||
@@ -341,11 +341,7 @@ impl From<crate::Message> for Message {
|
||||
embeds: value.embeds,
|
||||
mentions: value.mentions,
|
||||
replies: value.replies,
|
||||
reactions: value
|
||||
.reactions
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.into_iter().collect()))
|
||||
.collect(),
|
||||
reactions: value.reactions,
|
||||
interactions: value.interactions.into(),
|
||||
masquerade: value.masquerade.map(|masq| masq.into()),
|
||||
}
|
||||
@@ -369,12 +365,7 @@ impl From<crate::PartialMessage> for PartialMessage {
|
||||
embeds: value.embeds,
|
||||
mentions: value.mentions,
|
||||
replies: value.replies,
|
||||
reactions: value.reactions.map(|reactions| {
|
||||
reactions
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.into_iter().collect()))
|
||||
.collect()
|
||||
}),
|
||||
reactions: value.reactions,
|
||||
interactions: value.interactions.map(|interactions| interactions.into()),
|
||||
masquerade: value.masquerade.map(|masq| masq.into()),
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||
|
||||
use revolt_permissions::{
|
||||
calculate_user_permissions, ChannelType, Override, PermissionQuery, PermissionValue,
|
||||
RelationshipStatus,
|
||||
RelationshipStatus, DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
||||
};
|
||||
|
||||
use crate::{Channel, Database, Member, Server, User};
|
||||
@@ -209,7 +209,7 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
|
||||
match channel {
|
||||
Cow::Borrowed(Channel::Group { permissions, .. })
|
||||
| Cow::Owned(Channel::Group { permissions, .. }) => Override {
|
||||
allow: permissions.unwrap_or_default() as u64,
|
||||
allow: permissions.unwrap_or(*DEFAULT_PERMISSION_DIRECT_MESSAGE as i64) as u64,
|
||||
deny: 0,
|
||||
},
|
||||
Cow::Borrowed(Channel::TextChannel {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-models"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -18,8 +18,8 @@ default = ["serde", "partials"]
|
||||
|
||||
[dependencies]
|
||||
# Core
|
||||
revolt-config = { version = "0.6.11", path = "../config" }
|
||||
revolt-permissions = { version = "0.6.11", path = "../permissions" }
|
||||
revolt-config = { version = "0.6.13", path = "../config" }
|
||||
revolt-permissions = { version = "0.6.13", path = "../permissions" }
|
||||
|
||||
# Utility
|
||||
regex = "1"
|
||||
@@ -32,7 +32,7 @@ serde = { version = "1", features = ["derive"], optional = true }
|
||||
iso8601-timestamp = { version = "0.2.11", features = ["schema", "bson"] }
|
||||
|
||||
# Spec Generation
|
||||
schemars = { version = "0.8.8", optional = true }
|
||||
schemars = { version = "0.8.8", optional = true, features = ["indexmap1"] }
|
||||
|
||||
# Validation
|
||||
validator = { version = "0.16.0", optional = true, features = ["derive"] }
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
time::SystemTime,
|
||||
};
|
||||
use std::time::SystemTime;
|
||||
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use revolt_config::config;
|
||||
@@ -55,8 +53,8 @@ auto_derived_partial!(
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub replies: Option<Vec<String>>,
|
||||
/// Hashmap of emoji IDs to array of user IDs
|
||||
#[serde(skip_serializing_if = "HashMap::is_empty", default)]
|
||||
pub reactions: HashMap<String, HashSet<String>>,
|
||||
#[serde(skip_serializing_if = "IndexMap::is_empty", default)]
|
||||
pub reactions: IndexMap<String, IndexSet<String>>,
|
||||
/// Information about how this message should be interacted with
|
||||
#[serde(skip_serializing_if = "Interactions::is_default", default)]
|
||||
pub interactions: Interactions,
|
||||
@@ -119,7 +117,7 @@ auto_derived!(
|
||||
pub struct Interactions {
|
||||
/// Reactions which should always appear and be distinct
|
||||
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||
pub reactions: Option<HashSet<String>>,
|
||||
pub reactions: Option<IndexSet<String>>,
|
||||
/// Whether reactions should be restricted to the given list
|
||||
///
|
||||
/// Can only be set to true if reactions list is of at least length 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-permissions"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -21,7 +21,7 @@ async-std = { version = "1.8.0", features = ["attributes"] }
|
||||
|
||||
[dependencies]
|
||||
# Core
|
||||
revolt-result = { version = "0.6.5", path = "../result" }
|
||||
revolt-result = { version = "0.6.13", path = "../result" }
|
||||
|
||||
# Utility
|
||||
auto_ops = "0.3.0"
|
||||
|
||||
@@ -111,7 +111,7 @@ pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) ->
|
||||
query.set_server_from_channel().await;
|
||||
|
||||
if query.are_we_server_owner().await {
|
||||
return ChannelPermission::GrantAllSafe.into();
|
||||
ChannelPermission::GrantAllSafe.into()
|
||||
} else if query.are_we_a_member().await {
|
||||
let mut permissions = calculate_server_permissions(query).await;
|
||||
permissions.apply(query.get_default_channel_permissions().await);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-presence"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-result"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-delta"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <paulmakles@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -65,13 +65,8 @@ pub async fn message_send(
|
||||
// Disallow mentions for new users (TRUST-0: <12 hours age) in public servers
|
||||
let allow_mentions = if let Some(server) = query.server_ref() {
|
||||
if server.discoverable {
|
||||
if (Utc::now() - ulid::Ulid::from_string(&user.id).unwrap().datetime())
|
||||
< Duration::hours(12)
|
||||
{
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
(Utc::now() - ulid::Ulid::from_string(&user.id).unwrap().datetime())
|
||||
>= Duration::hours(12)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ impl Ratelimiter {
|
||||
pub fn from(
|
||||
identifier: &str,
|
||||
(bucket, resource): (&str, Option<&str>),
|
||||
) -> Result<Ratelimiter, u128> {
|
||||
) -> Result<Ratelimiter, Ratelimiter> {
|
||||
let mut key = DefaultHasher::new();
|
||||
key.write(identifier.as_bytes());
|
||||
key.write(bucket.as_bytes());
|
||||
@@ -194,27 +194,29 @@ impl Ratelimiter {
|
||||
let mut entry = Entry::from(key);
|
||||
|
||||
let remaining = entry.get_remaining(limit);
|
||||
if remaining > 0 {
|
||||
entry.deduct();
|
||||
|
||||
let reset = entry.left_until_reset();
|
||||
entry.save(key);
|
||||
|
||||
Ok(Ratelimiter {
|
||||
key,
|
||||
limit,
|
||||
remaining: remaining - 1,
|
||||
reset,
|
||||
})
|
||||
} else {
|
||||
Err(entry.left_until_reset())
|
||||
let reset = entry.left_until_reset();
|
||||
let mut ratelimiter = Ratelimiter {
|
||||
key,
|
||||
limit,
|
||||
remaining,
|
||||
reset,
|
||||
};
|
||||
if remaining == 0 {
|
||||
return Err(ratelimiter);
|
||||
}
|
||||
|
||||
entry.deduct();
|
||||
entry.save(key);
|
||||
ratelimiter.remaining -= 1;
|
||||
ratelimiter.reset = entry.left_until_reset();
|
||||
|
||||
Ok(ratelimiter)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'r> FromRequest<'r> for Ratelimiter {
|
||||
type Error = u128;
|
||||
type Error = Ratelimiter;
|
||||
|
||||
async fn from_request(request: &'r rocket::Request<'_>) -> Outcome<Self, Self::Error> {
|
||||
let ratelimiter = request
|
||||
@@ -233,7 +235,7 @@ impl<'r> FromRequest<'r> for Ratelimiter {
|
||||
|
||||
match ratelimiter {
|
||||
Ok(ratelimiter) => Outcome::Success(*ratelimiter),
|
||||
Err(retry_after) => Outcome::Failure((Status::TooManyRequests, *retry_after)),
|
||||
Err(ratelimiter) => Outcome::Failure((Status::TooManyRequests, *ratelimiter)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,23 +277,24 @@ impl Fairing for RatelimitFairing {
|
||||
}
|
||||
|
||||
async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
|
||||
use rocket::outcome::Outcome;
|
||||
match request.guard::<Ratelimiter>().await {
|
||||
Outcome::Success(ratelimiter) => {
|
||||
let Ratelimiter {
|
||||
key,
|
||||
limit,
|
||||
remaining,
|
||||
reset,
|
||||
} = ratelimiter;
|
||||
let guard = request.guard::<Ratelimiter>().await;
|
||||
let (Outcome::Success(ratelimiter) | Outcome::Failure((_, ratelimiter))) = guard else {
|
||||
unreachable!()
|
||||
};
|
||||
let Ratelimiter {
|
||||
key,
|
||||
limit,
|
||||
remaining,
|
||||
reset,
|
||||
} = ratelimiter;
|
||||
|
||||
response.set_raw_header("X-RateLimit-Limit", limit.to_string());
|
||||
response.set_raw_header("X-RateLimit-Bucket", key.to_string());
|
||||
response.set_raw_header("X-RateLimit-Remaining", remaining.to_string());
|
||||
response.set_raw_header("X-RateLimit-Reset-After", reset.to_string());
|
||||
}
|
||||
Outcome::Failure(_) => response.set_status(Status::TooManyRequests),
|
||||
Outcome::Forward(_) => unreachable!(),
|
||||
response.set_raw_header("X-RateLimit-Limit", limit.to_string());
|
||||
response.set_raw_header("X-RateLimit-Bucket", key.to_string());
|
||||
response.set_raw_header("X-RateLimit-Remaining", remaining.to_string());
|
||||
response.set_raw_header("X-RateLimit-Reset-After", reset.to_string());
|
||||
|
||||
if guard.is_failure() {
|
||||
response.set_status(Status::TooManyRequests);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,11 +311,14 @@ impl<'r> FromRequest<'r> for RatelimitInformation {
|
||||
type Error = u128;
|
||||
|
||||
async fn from_request(request: &'r rocket::Request<'_>) -> Outcome<Self, Self::Error> {
|
||||
Outcome::Success(match request.guard::<Ratelimiter>().await {
|
||||
let info = match request.guard::<Ratelimiter>().await {
|
||||
Outcome::Success(ratelimiter) => RatelimitInformation::Success(ratelimiter),
|
||||
Outcome::Failure((_, retry_after)) => RatelimitInformation::Failure { retry_after },
|
||||
Outcome::Failure((_, ratelimiter)) => RatelimitInformation::Failure {
|
||||
retry_after: ratelimiter.reset,
|
||||
},
|
||||
_ => unreachable!(),
|
||||
})
|
||||
};
|
||||
Outcome::Success(info)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+100
-100
@@ -1,100 +1,100 @@
|
||||
[package]
|
||||
name = "revolt-quark"
|
||||
version = "0.6.11"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
mongo = ["mongodb"]
|
||||
rocket_impl = [
|
||||
"rocket",
|
||||
"rocket_empty",
|
||||
"rocket_cors",
|
||||
|
||||
"lru",
|
||||
"dashmap",
|
||||
|
||||
"authifier/database-mongodb",
|
||||
"authifier/rocket_impl",
|
||||
"authifier/okapi_impl",
|
||||
]
|
||||
|
||||
test = ["async-std", "mongo", "mongodb/async-std-runtime", "rocket_impl"]
|
||||
default = ["test"]
|
||||
|
||||
[dependencies]
|
||||
# Serialisation
|
||||
revolt_optional_struct = "0.2.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
validator = { version = "0.16", features = ["derive"] }
|
||||
iso8601-timestamp = { version = "0.1.8", features = ["schema", "bson"] }
|
||||
|
||||
# Formats
|
||||
bincode = "1.3.3"
|
||||
serde_json = "1.0.78"
|
||||
bson = { version = "2.1.0", features = ["chrono-0_4"] }
|
||||
|
||||
# Spec Generation
|
||||
schemars = "0.8.8"
|
||||
revolt_okapi = "0.9.1"
|
||||
revolt_rocket_okapi = { version = "0.9.1", features = ["swagger"] }
|
||||
|
||||
# Databases
|
||||
redis-kiss = { version = "0.1.4" }
|
||||
mongodb = { optional = true, version = "2.1.0", default-features = false }
|
||||
|
||||
# Async
|
||||
futures = "0.3.19"
|
||||
deadqueue = "0.2.1"
|
||||
async-trait = "0.1.51"
|
||||
async-recursion = "1.0.0"
|
||||
async-std = { version = "1.8.0", features = ["attributes"], optional = true }
|
||||
|
||||
# Logging
|
||||
log = "0.4.14"
|
||||
pretty_env_logger = "0.4.0"
|
||||
|
||||
# Util
|
||||
rand = "0.8.5"
|
||||
ulid = "0.5.0"
|
||||
regex = "1.5.5"
|
||||
nanoid = "0.4.0"
|
||||
linkify = "0.8.1"
|
||||
dotenv = "0.15.0"
|
||||
indexmap = "1.9.1"
|
||||
decancer = "1.6.2"
|
||||
impl_ops = "0.1.1"
|
||||
num_enum = "0.5.6"
|
||||
reqwest = "0.11.10"
|
||||
bitfield = "0.13.2"
|
||||
once_cell = "1.17.1"
|
||||
async-lock = "2.6.0"
|
||||
|
||||
lru = { version = "0.7.6", optional = true }
|
||||
dashmap = { version = "5.2.0", optional = true }
|
||||
|
||||
# Web Push
|
||||
base64 = "0.13.0"
|
||||
web-push = "0.7.2"
|
||||
|
||||
# Implementations
|
||||
rocket_http = { optional = true, version = "0.5.0-rc.2" }
|
||||
rocket = { optional = true, version = "0.5.0-rc.2", default-features = false, features = [
|
||||
"json",
|
||||
] }
|
||||
rocket_empty = { version = "0.1.1", optional = true, features = ["schema"] }
|
||||
rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
|
||||
|
||||
# Authifier
|
||||
authifier = { version = "1.0.8", features = ["async-std-runtime"] }
|
||||
|
||||
# Sentry
|
||||
sentry = "0.31.5"
|
||||
|
||||
# Core
|
||||
revolt-result = { path = "../core/result", features = ["serde", "schemas"] }
|
||||
revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] }
|
||||
revolt-database = { path = "../core/database" }
|
||||
revolt-models = { path = "../core/models" }
|
||||
[package]
|
||||
name = "revolt-quark"
|
||||
version = "0.6.13"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
mongo = ["mongodb"]
|
||||
rocket_impl = [
|
||||
"rocket",
|
||||
"rocket_empty",
|
||||
"rocket_cors",
|
||||
|
||||
"lru",
|
||||
"dashmap",
|
||||
|
||||
"authifier/database-mongodb",
|
||||
"authifier/rocket_impl",
|
||||
"authifier/okapi_impl",
|
||||
]
|
||||
|
||||
test = ["async-std", "mongo", "mongodb/async-std-runtime", "rocket_impl"]
|
||||
default = ["test"]
|
||||
|
||||
[dependencies]
|
||||
# Serialisation
|
||||
revolt_optional_struct = "0.2.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
validator = { version = "0.16", features = ["derive"] }
|
||||
iso8601-timestamp = { version = "0.1.8", features = ["schema", "bson"] }
|
||||
|
||||
# Formats
|
||||
bincode = "1.3.3"
|
||||
serde_json = "1.0.78"
|
||||
bson = { version = "2.1.0", features = ["chrono-0_4"] }
|
||||
|
||||
# Spec Generation
|
||||
schemars = "0.8.8"
|
||||
revolt_okapi = "0.9.1"
|
||||
revolt_rocket_okapi = { version = "0.9.1", features = ["swagger"] }
|
||||
|
||||
# Databases
|
||||
redis-kiss = { version = "0.1.4" }
|
||||
mongodb = { optional = true, version = "2.1.0", default-features = false }
|
||||
|
||||
# Async
|
||||
futures = "0.3.19"
|
||||
deadqueue = "0.2.1"
|
||||
async-trait = "0.1.51"
|
||||
async-recursion = "1.0.0"
|
||||
async-std = { version = "1.8.0", features = ["attributes"], optional = true }
|
||||
|
||||
# Logging
|
||||
log = "0.4.14"
|
||||
pretty_env_logger = "0.4.0"
|
||||
|
||||
# Util
|
||||
rand = "0.8.5"
|
||||
ulid = "0.5.0"
|
||||
regex = "1.5.5"
|
||||
nanoid = "0.4.0"
|
||||
linkify = "0.8.1"
|
||||
dotenv = "0.15.0"
|
||||
indexmap = "1.9.1"
|
||||
decancer = "1.6.2"
|
||||
impl_ops = "0.1.1"
|
||||
num_enum = "0.5.6"
|
||||
reqwest = "0.11.10"
|
||||
bitfield = "0.13.2"
|
||||
once_cell = "1.17.1"
|
||||
async-lock = "2.6.0"
|
||||
|
||||
lru = { version = "0.7.6", optional = true }
|
||||
dashmap = { version = "5.2.0", optional = true }
|
||||
|
||||
# Web Push
|
||||
base64 = "0.13.0"
|
||||
web-push = "0.7.2"
|
||||
|
||||
# Implementations
|
||||
rocket_http = { optional = true, version = "0.5.0-rc.2" }
|
||||
rocket = { optional = true, version = "0.5.0-rc.2", default-features = false, features = [
|
||||
"json",
|
||||
] }
|
||||
rocket_empty = { version = "0.1.1", optional = true, features = ["schema"] }
|
||||
rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
|
||||
|
||||
# Authifier
|
||||
authifier = { version = "1.0.8", features = ["async-std-runtime"] }
|
||||
|
||||
# Sentry
|
||||
sentry = "0.31.5"
|
||||
|
||||
# Core
|
||||
revolt-result = { path = "../core/result", features = ["serde", "schemas"] }
|
||||
revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] }
|
||||
revolt-database = { path = "../core/database" }
|
||||
revolt-models = { path = "../core/models" }
|
||||
|
||||
@@ -5,7 +5,6 @@ use iso8601_timestamp::Timestamp;
|
||||
use crate::{
|
||||
events::client::EventV1,
|
||||
models::{
|
||||
server::Role,
|
||||
server_member::{FieldsMember, MemberCompositeKey, MemberWithRoles, PartialMember},
|
||||
Member, Server,
|
||||
},
|
||||
@@ -84,30 +83,13 @@ impl Member {
|
||||
FieldsMember::Timeout => self.timeout = None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_roles(&self, roles: HashMap<String, Role>) -> MemberWithRoles {
|
||||
MemberWithRoles {
|
||||
id: self.id.clone(),
|
||||
joined_at: self.joined_at,
|
||||
nickname: self.nickname.clone(),
|
||||
avatar: self.avatar.clone(),
|
||||
roles,
|
||||
timeout: self.timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MemberWithRoles {
|
||||
pub fn new(server_id: String, user_id: String) -> Self {
|
||||
Self {
|
||||
id: MemberCompositeKey {
|
||||
server: server_id,
|
||||
user: user_id,
|
||||
},
|
||||
joined_at: Timestamp::now_utc(),
|
||||
nickname: None,
|
||||
avatar: None,
|
||||
member: Member::new(server_id, user_id),
|
||||
roles: HashMap::new(),
|
||||
timeout: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,14 @@ impl AbstractServerMember for MongoDb {
|
||||
}
|
||||
|
||||
async fn fetch_member_with_roles(&self, server: &str, user: &str) -> Result<MemberWithRoles> {
|
||||
Ok(self
|
||||
.fetch_member(server, user)
|
||||
.await?
|
||||
.with_roles(self.fetch_server(server).await?.roles))
|
||||
let member = self.fetch_member(server, user).await?;
|
||||
let server_roles = self.fetch_server(server).await?.roles;
|
||||
let roles = member
|
||||
.roles
|
||||
.iter()
|
||||
.filter_map(|id| server_roles.get(id).map(|r| (id.clone(), r.clone())))
|
||||
.collect();
|
||||
Ok(MemberWithRoles { member, roles })
|
||||
}
|
||||
|
||||
async fn insert_member(&self, member: &Member) -> Result<()> {
|
||||
|
||||
@@ -47,47 +47,27 @@ pub struct Member {
|
||||
}
|
||||
|
||||
/// Representation of a member of a server on Revolt With Role Data
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, OptionalStruct)]
|
||||
#[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]
|
||||
#[opt_skip_serializing_none]
|
||||
#[opt_some_priority]
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
pub struct MemberWithRoles {
|
||||
/// Unique member id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: MemberCompositeKey,
|
||||
|
||||
/// Time at which this user joined the server
|
||||
pub joined_at: Timestamp,
|
||||
|
||||
/// Member's nickname
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub nickname: Option<String>,
|
||||
/// Avatar attachment
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub avatar: Option<File>,
|
||||
|
||||
/// Member's roles
|
||||
#[serde(skip_serializing_if = "HashMap::is_empty", default)]
|
||||
pub member: Member,
|
||||
pub roles: HashMap<String, Role>,
|
||||
/// Timestamp this member is timed out until
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timeout: Option<Timestamp>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||
#[serde(untagged)]
|
||||
pub enum MemberResponse {
|
||||
Members(Member),
|
||||
MembersWithRoles(MemberWithRoles),
|
||||
Member(Member),
|
||||
MemberWithRoles(MemberWithRoles),
|
||||
}
|
||||
|
||||
impl From<Member> for MemberResponse {
|
||||
fn from(value: Member) -> Self {
|
||||
Self::Members(value)
|
||||
Self::Member(value)
|
||||
}
|
||||
}
|
||||
impl From<MemberWithRoles> for MemberResponse {
|
||||
fn from(value: MemberWithRoles) -> Self {
|
||||
Self::MembersWithRoles(value)
|
||||
Self::MemberWithRoles(value)
|
||||
}
|
||||
}
|
||||
/// Optional fields on server member object
|
||||
|
||||
@@ -5,3 +5,15 @@ publish:
|
||||
cargo publish --package revolt-models
|
||||
cargo publish --package revolt-presence
|
||||
cargo publish --package revolt-database
|
||||
|
||||
patch:
|
||||
cargo release version patch --execute
|
||||
|
||||
minor:
|
||||
cargo release version minor --execute
|
||||
|
||||
major:
|
||||
cargo release version major --execute
|
||||
|
||||
release:
|
||||
scripts/try-tag-and-release.sh
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
date=$(date +'%Y%m%d')
|
||||
incr=1
|
||||
|
||||
while [ $(git tag -l "$date-$incr") ]; do
|
||||
incr=$((incr+1))
|
||||
done
|
||||
|
||||
tag=$date-$incr
|
||||
echo About to tag and push $tag in 3 seconds...
|
||||
sleep 3s
|
||||
|
||||
git tag $tag
|
||||
git push --atomic origin $(git rev-parse --abbrev-ref HEAD) $tag
|
||||
Reference in New Issue
Block a user