chore(thanos): strip down codebase to just API routes
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::Json;
|
||||
@@ -13,50 +12,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[put("/<server>/bans/<target>", data = "<data>")]
|
||||
pub async fn req(user: User, server: Ref, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let data = data.into_inner();
|
||||
data.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let server = server.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&server)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_ban_members() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let target = target.fetch_user().await?;
|
||||
if target.id == user.id {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
|
||||
if target.id == server.owner {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let mut document = doc! {
|
||||
"_id": {
|
||||
"server": &server.id,
|
||||
"user": &target.id
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(reason) = data.reason {
|
||||
document.insert("reason", reason);
|
||||
}
|
||||
|
||||
get_collection("server_bans")
|
||||
.insert_one(document, None)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "insert_one",
|
||||
with: "server_ban",
|
||||
})?;
|
||||
|
||||
server.remove_member(&target.id, RemoveMember::Ban).await?;
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, server: Ref, target: Ref,*/ server: String, target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
use revolt_quark::models::File;
|
||||
|
||||
use futures::StreamExt;
|
||||
use mongodb::options::FindOptions;
|
||||
@@ -15,73 +15,6 @@ struct BannedUser {
|
||||
}
|
||||
|
||||
#[get("/<target>/bans")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_ban_members() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let mut cursor = get_collection("server_bans")
|
||||
.find(
|
||||
doc! {
|
||||
"_id.server": target.id
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "server_bans",
|
||||
})?;
|
||||
|
||||
let mut bans = vec![];
|
||||
let mut user_ids = vec![];
|
||||
while let Some(result) = cursor.next().await {
|
||||
if let Ok(doc) = result {
|
||||
if let Ok(ban) = from_document::<Ban>(doc) {
|
||||
user_ids.push(ban.id.user.clone());
|
||||
bans.push(ban);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut cursor = get_collection("users")
|
||||
.find(
|
||||
doc! {
|
||||
"_id": {
|
||||
"$in": user_ids
|
||||
}
|
||||
},
|
||||
FindOptions::builder()
|
||||
.projection(doc! {
|
||||
"username": 1,
|
||||
"avatar": 1
|
||||
})
|
||||
.build(),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "users",
|
||||
})?;
|
||||
|
||||
let mut users = vec![];
|
||||
while let Some(result) = cursor.next().await {
|
||||
if let Ok(doc) = result {
|
||||
if let Ok(user) = from_document::<BannedUser>(doc) {
|
||||
users.push(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(json!({
|
||||
"users": users,
|
||||
"bans": bans
|
||||
}))
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,43 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[delete("/<server>/bans/<target>")]
|
||||
pub async fn req(user: User, server: Ref, target: Ref) -> Result<EmptyResponse> {
|
||||
let server = server.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&server)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_ban_members() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
if target.id == user.id {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
|
||||
if target.id == server.owner {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let target = target.fetch_ban(&server.id).await?;
|
||||
get_collection("server_bans")
|
||||
.delete_one(
|
||||
doc! {
|
||||
"_id.server": &server.id,
|
||||
"_id.user": &target.id.user
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "delete_one",
|
||||
with: "server_ban",
|
||||
})?;
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, server: Ref, target: Ref*/ server: String, target: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::database::*;
|
||||
use crate::util::idempotency::IdempotencyKey;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::{Json, Value};
|
||||
@@ -35,70 +33,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[post("/<target>/channels", data = "<info>")]
|
||||
pub async fn req(_idempotency: IdempotencyKey, user: User, target: Ref, info: Json<Data>) -> Result<Value> {
|
||||
let info = info.into_inner();
|
||||
info.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let target = target.fetch_server().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_channels() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let id = Ulid::new().to_string();
|
||||
let channel = match info.channel_type {
|
||||
ChannelType::Text => Channel::TextChannel {
|
||||
id: id.clone(),
|
||||
server: target.id.clone(),
|
||||
|
||||
name: info.name,
|
||||
description: info.description,
|
||||
icon: None,
|
||||
last_message_id: None,
|
||||
|
||||
default_permissions: None,
|
||||
role_permissions: HashMap::new(),
|
||||
|
||||
nsfw: info.nsfw.unwrap_or_default(),
|
||||
},
|
||||
ChannelType::Voice => Channel::VoiceChannel {
|
||||
id: id.clone(),
|
||||
server: target.id.clone(),
|
||||
|
||||
name: info.name,
|
||||
description: info.description,
|
||||
icon: None,
|
||||
|
||||
default_permissions: None,
|
||||
role_permissions: HashMap::new(),
|
||||
|
||||
nsfw: info.nsfw.unwrap_or_default()
|
||||
}
|
||||
};
|
||||
|
||||
channel.clone().publish().await?;
|
||||
get_collection("servers")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": target.id
|
||||
},
|
||||
doc! {
|
||||
"$addToSet": {
|
||||
"channels": id
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "server",
|
||||
})?;
|
||||
|
||||
Ok(json!(channel))
|
||||
pub async fn req(/*_idempotency: IdempotencyKey, user: User, target: Ref,*/ target: String, info: Json<Data>) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use futures::StreamExt;
|
||||
use mongodb::bson::{doc, from_document};
|
||||
@@ -15,39 +14,6 @@ pub struct ServerInvite {
|
||||
}
|
||||
|
||||
#[get("/<target>/invites")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_server() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let mut cursor = get_collection("channel_invites")
|
||||
.find(
|
||||
doc! {
|
||||
"server": target.id
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "channel_invites",
|
||||
})?;
|
||||
|
||||
let mut invites = vec![];
|
||||
while let Some(result) = cursor.next().await {
|
||||
if let Ok(doc) = result {
|
||||
if let Ok(invite) = from_document::<Invite>(doc) {
|
||||
invites.push(invite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(json!(invites))
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
use std::collections::HashSet;
|
||||
use revolt_quark::{EmptyResponse, Result, models::server_member::FieldsMember};
|
||||
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::{database::*, notifications::events::RemoveMemberField};
|
||||
|
||||
use mongodb::bson::{doc, to_document};
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
@@ -15,144 +10,10 @@ pub struct Data {
|
||||
nickname: Option<String>,
|
||||
avatar: Option<String>,
|
||||
roles: Option<Vec<String>>,
|
||||
remove: Option<RemoveMemberField>,
|
||||
remove: Option<FieldsMember>,
|
||||
}
|
||||
|
||||
#[patch("/<server>/members/<target>", data = "<data>")]
|
||||
pub async fn req(user: User, server: Ref, target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let data = data.into_inner();
|
||||
data.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
if data.nickname.is_none() && data.avatar.is_none() && data.roles.is_none() && data.remove.is_none() {
|
||||
return Ok(EmptyResponse {});
|
||||
}
|
||||
|
||||
let server = server.fetch_server().await?;
|
||||
let target = Ref::from(target)?.fetch_member(&server.id).await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&server)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if data.roles.is_some() && !perm.get_manage_roles() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
if target.id.user == user.id {
|
||||
if (data.nickname.is_some() && !perm.get_change_nickname())
|
||||
|| (data.avatar.is_some() && !perm.get_change_avatar())
|
||||
{
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
if let Some(remove) = &data.remove {
|
||||
if match remove {
|
||||
RemoveMemberField::Avatar => !perm.get_change_avatar(),
|
||||
RemoveMemberField::Nickname => !perm.get_change_nickname(),
|
||||
} {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if data.avatar.is_some() || (data.nickname.is_some() && !perm.get_manage_nicknames()) {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
if let Some(remove) = &data.remove {
|
||||
if match remove {
|
||||
RemoveMemberField::Avatar => !perm.get_remove_avatars(),
|
||||
RemoveMemberField::Nickname => !perm.get_manage_nicknames(),
|
||||
} {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut set = doc! {};
|
||||
let mut unset = doc! {};
|
||||
|
||||
let mut remove_avatar = false;
|
||||
if let Some(remove) = &data.remove {
|
||||
match remove {
|
||||
RemoveMemberField::Avatar => {
|
||||
unset.insert("avatar", 1);
|
||||
remove_avatar = true;
|
||||
}
|
||||
RemoveMemberField::Nickname => {
|
||||
unset.insert("nickname", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(name) = &data.nickname {
|
||||
set.insert("nickname", name);
|
||||
}
|
||||
|
||||
if let Some(attachment_id) = &data.avatar {
|
||||
let attachment =
|
||||
File::find_and_use(&attachment_id, "avatars", "user", &target.id.user).await?;
|
||||
set.insert(
|
||||
"avatar",
|
||||
to_document(&attachment).map_err(|_| Error::DatabaseError {
|
||||
operation: "to_document",
|
||||
with: "attachment",
|
||||
})?,
|
||||
);
|
||||
|
||||
remove_avatar = true;
|
||||
}
|
||||
|
||||
if let Some(role_ids) = &data.roles {
|
||||
let mut ids = HashSet::new();
|
||||
|
||||
for role in role_ids {
|
||||
if server.roles.contains_key(role) {
|
||||
ids.insert(role.clone());
|
||||
}
|
||||
}
|
||||
|
||||
set.insert("roles", ids.into_iter().collect::<Vec<String>>());
|
||||
}
|
||||
|
||||
let mut operations = doc! {};
|
||||
if set.len() > 0 {
|
||||
operations.insert("$set", &set);
|
||||
}
|
||||
|
||||
if unset.len() > 0 {
|
||||
operations.insert("$unset", unset);
|
||||
}
|
||||
|
||||
if operations.len() > 0 {
|
||||
get_collection("server_members")
|
||||
.update_one(
|
||||
doc! { "_id.server": &server.id, "_id.user": &target.id.user },
|
||||
operations,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "server_member",
|
||||
})?;
|
||||
}
|
||||
|
||||
ClientboundNotification::ServerMemberUpdate {
|
||||
id: target.id.clone(),
|
||||
data: json!(set),
|
||||
clear: data.remove,
|
||||
}
|
||||
.publish(server.id.clone());
|
||||
|
||||
let Member { avatar, .. } = target;
|
||||
|
||||
if remove_avatar {
|
||||
if let Some(old_avatar) = avatar {
|
||||
old_avatar.delete().await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, server: Ref,*/ server: String, target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
#[get("/<target>/members/<member>")]
|
||||
pub async fn req(user: User, target: Ref, member: String) -> Result<Value> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
Ok(json!(Ref::from(member)?.fetch_member(&target.id).await?))
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, member: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,51 +1,9 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use futures::StreamExt;
|
||||
use mongodb::bson::{doc, from_document, Document};
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
// ! FIXME: this is a temporary route while permissions are being worked on.
|
||||
|
||||
#[get("/<target>/members")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let members = get_collection("server_members")
|
||||
.find(
|
||||
doc! {
|
||||
"_id.server": target.id
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "find",
|
||||
with: "server_members",
|
||||
})?
|
||||
.filter_map(async move |s| s.ok())
|
||||
.collect::<Vec<Document>>()
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|x| from_document(x).ok())
|
||||
.collect::<Vec<Member>>();
|
||||
|
||||
let member_ids = members
|
||||
.iter()
|
||||
.map(|m| m.id.user.clone())
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
Ok(json!({
|
||||
"members": members,
|
||||
"users": user.fetch_multiple_users(&member_ids).await?
|
||||
}))
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,33 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[delete("/<target>/members/<member>")]
|
||||
pub async fn req(user: User, target: Ref, member: String) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_kick_members() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let member = Ref::from(member)?.fetch_member(&target.id).await?;
|
||||
if member.id.user == user.id {
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
|
||||
if member.id.user == target.owner {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
target
|
||||
.remove_member(&member.id.user, RemoveMember::Kick)
|
||||
.await?;
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, member: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ use mongodb::bson::doc;
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::database::*;
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Values {
|
||||
@@ -18,56 +16,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[put("/<target>/permissions/<role_id>", data = "<data>", rank = 2)]
|
||||
pub async fn req(user: User, target: Ref, role_id: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
if !target.roles.contains_key(&role_id) {
|
||||
return Err(Error::NotFound);
|
||||
}
|
||||
|
||||
let server_permissions: u32 = data.permissions.server;
|
||||
let channel_permissions: u32 = data.permissions.channel;
|
||||
|
||||
get_collection("servers")
|
||||
.update_one(
|
||||
doc! { "_id": &target.id },
|
||||
doc! {
|
||||
"$set": {
|
||||
"roles.".to_owned() + &role_id + &".permissions": [
|
||||
server_permissions as i32,
|
||||
channel_permissions as i32
|
||||
]
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "server"
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ServerRoleUpdate {
|
||||
id: target.id.clone(),
|
||||
role_id,
|
||||
data: json!({
|
||||
"permissions": [
|
||||
server_permissions as i32,
|
||||
channel_permissions as i32
|
||||
]
|
||||
}),
|
||||
clear: None
|
||||
}
|
||||
.publish(target.id);
|
||||
|
||||
Ok(EmptyResponse)
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role_id: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ use mongodb::bson::doc;
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::database::*;
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Values {
|
||||
@@ -18,51 +16,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[put("/<target>/permissions/default", data = "<data>", rank = 1)]
|
||||
pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
let server_permissions: u32 = data.permissions.server;
|
||||
let channel_permissions: u32 = data.permissions.channel;
|
||||
|
||||
get_collection("servers")
|
||||
.update_one(
|
||||
doc! { "_id": &target.id },
|
||||
doc! {
|
||||
"$set": {
|
||||
"default_permissions": [
|
||||
server_permissions as i32,
|
||||
channel_permissions as i32
|
||||
]
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "server"
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ServerUpdate {
|
||||
id: target.id.clone(),
|
||||
data: json!({
|
||||
"default_permissions": [
|
||||
server_permissions as i32,
|
||||
channel_permissions as i32
|
||||
]
|
||||
}),
|
||||
clear: None
|
||||
}
|
||||
.publish(target.id);
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::database::*;
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use ulid::Ulid;
|
||||
use mongodb::bson::doc;
|
||||
@@ -15,62 +13,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[post("/<target>/roles", data = "<data>")]
|
||||
pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<Value> {
|
||||
let data = data.into_inner();
|
||||
data.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let id = Ulid::new().to_string();
|
||||
let perm_tuple = (
|
||||
*permissions::server::DEFAULT_PERMISSION as i32,
|
||||
*permissions::channel::DEFAULT_PERMISSION_SERVER as i32
|
||||
);
|
||||
|
||||
get_collection("servers")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"roles.".to_owned() + &id: {
|
||||
"name": &data.name,
|
||||
"permissions": [
|
||||
&perm_tuple.0,
|
||||
&perm_tuple.1
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "servers"
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ServerRoleUpdate {
|
||||
id: target.id.clone(),
|
||||
role_id: id.clone(),
|
||||
data: json!({
|
||||
"name": data.name,
|
||||
"permissions": &perm_tuple
|
||||
}),
|
||||
clear: None
|
||||
}
|
||||
.publish(target.id);
|
||||
|
||||
Ok(json!({ "id": id, "permissions": perm_tuple }))
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,81 +1,6 @@
|
||||
use crate::database::*;
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[delete("/<target>/roles/<role_id>")]
|
||||
pub async fn req(user: User, target: Ref, role_id: String) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
get_collection("servers")
|
||||
.update_one(
|
||||
doc! {
|
||||
"_id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$unset": {
|
||||
"roles.".to_owned() + &role_id: 1
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "servers"
|
||||
})?;
|
||||
|
||||
get_collection("channels")
|
||||
.update_one(
|
||||
doc! {
|
||||
"server": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$unset": {
|
||||
"role_permissions.".to_owned() + &role_id: 1
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "channels"
|
||||
})?;
|
||||
|
||||
get_collection("server_members")
|
||||
.update_many(
|
||||
doc! {
|
||||
"_id.server": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"roles": &role_id
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_many",
|
||||
with: "server_members"
|
||||
})?;
|
||||
|
||||
ClientboundNotification::ServerRoleDelete {
|
||||
id: target.id.clone(),
|
||||
role_id
|
||||
}
|
||||
.publish(target.id);
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role_id: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::{database::*, notifications::events::RemoveRoleField};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::Json;
|
||||
@@ -15,96 +13,10 @@ pub struct Data {
|
||||
colour: Option<String>,
|
||||
hoist: Option<bool>,
|
||||
rank: Option<i64>,
|
||||
remove: Option<RemoveRoleField>,
|
||||
// remove: Option<FieldsRole>,
|
||||
}
|
||||
|
||||
#[patch("/<target>/roles/<role_id>", data = "<data>")]
|
||||
pub async fn req(user: User, target: Ref, role_id: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let data = data.into_inner();
|
||||
data.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
if data.name.is_none() && data.colour.is_none() && data.hoist.is_none() && data.rank.is_none() && data.remove.is_none()
|
||||
{
|
||||
return Ok(EmptyResponse {});
|
||||
}
|
||||
|
||||
let target = target.fetch_server().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_roles() {
|
||||
return Err(Error::MissingPermission)
|
||||
}
|
||||
|
||||
if !target.roles.contains_key(&role_id) {
|
||||
return Err(Error::InvalidRole)
|
||||
}
|
||||
|
||||
let mut set = doc! {};
|
||||
let mut unset = doc! {};
|
||||
|
||||
// ! FIXME: we should probably just require clients to support basic MQL incl. $set / $unset
|
||||
let mut set_update = doc! {};
|
||||
|
||||
let role_key = "roles.".to_owned() + &role_id;
|
||||
|
||||
if let Some(remove) = &data.remove {
|
||||
match remove {
|
||||
RemoveRoleField::Colour => {
|
||||
unset.insert(role_key.clone() + ".colour", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(name) = &data.name {
|
||||
set.insert(role_key.clone() + ".name", name);
|
||||
set_update.insert("name", name);
|
||||
}
|
||||
|
||||
if let Some(colour) = &data.colour {
|
||||
set.insert(role_key.clone() + ".colour", colour);
|
||||
set_update.insert("colour", colour);
|
||||
}
|
||||
|
||||
if let Some(hoist) = &data.hoist {
|
||||
set.insert(role_key.clone() + ".hoist", hoist);
|
||||
set_update.insert("hoist", hoist);
|
||||
}
|
||||
|
||||
if let Some(rank) = &data.rank {
|
||||
set.insert(role_key.clone() + ".rank", rank);
|
||||
set_update.insert("rank", rank);
|
||||
}
|
||||
|
||||
let mut operations = doc! {};
|
||||
if set.len() > 0 {
|
||||
operations.insert("$set", &set);
|
||||
}
|
||||
|
||||
if unset.len() > 0 {
|
||||
operations.insert("$unset", unset);
|
||||
}
|
||||
|
||||
if operations.len() > 0 {
|
||||
get_collection("servers")
|
||||
.update_one(doc! { "_id": &target.id }, operations, None)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "server",
|
||||
})?;
|
||||
}
|
||||
|
||||
ClientboundNotification::ServerRoleUpdate {
|
||||
id: target.id.clone(),
|
||||
role_id,
|
||||
data: json!(set_update),
|
||||
clear: data.remove,
|
||||
}
|
||||
.publish(target.id.clone());
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role_id: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
#[put("/<target>/ack")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<EmptyResponse> {
|
||||
if user.bot.is_some() {
|
||||
return Err(Error::IsBot)
|
||||
}
|
||||
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
target.mark_as_read(&user.id).await?;
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::database::*;
|
||||
use crate::util::idempotency::IdempotencyKey;
|
||||
use crate::util::result::{Error, Result};
|
||||
use crate::util::variables::MAX_SERVER_COUNT;
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use rocket::serde::json::{Json, Value};
|
||||
@@ -22,73 +19,6 @@ pub struct Data {
|
||||
}
|
||||
|
||||
#[post("/create", data = "<info>")]
|
||||
pub async fn req(_idempotency: IdempotencyKey, user: User, info: Json<Data>) -> Result<Value> {
|
||||
if user.bot.is_some() {
|
||||
return Err(Error::IsBot)
|
||||
}
|
||||
|
||||
if !User::can_acquire_server(&user.id).await? {
|
||||
Err(Error::TooManyServers {
|
||||
max: *MAX_SERVER_COUNT,
|
||||
})?
|
||||
}
|
||||
|
||||
let info = info.into_inner();
|
||||
info.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
let id = Ulid::new().to_string();
|
||||
let cid = Ulid::new().to_string();
|
||||
|
||||
let server = Server {
|
||||
id: id.clone(),
|
||||
owner: user.id.clone(),
|
||||
|
||||
name: info.name,
|
||||
description: info.description,
|
||||
|
||||
channels: vec![cid.clone()],
|
||||
categories: None,
|
||||
system_messages: Some(SystemMessageChannels {
|
||||
user_joined: Some(cid.clone()),
|
||||
user_left: Some(cid.clone()),
|
||||
user_kicked: Some(cid.clone()),
|
||||
user_banned: Some(cid.clone()),
|
||||
}),
|
||||
|
||||
roles: HashMap::new(),
|
||||
default_permissions: (
|
||||
*permissions::server::DEFAULT_PERMISSION as i32,
|
||||
*permissions::channel::DEFAULT_PERMISSION_SERVER as i32
|
||||
),
|
||||
|
||||
icon: None,
|
||||
banner: None,
|
||||
|
||||
flags: None,
|
||||
nsfw: info.nsfw.unwrap_or_default(),
|
||||
analytics: false,
|
||||
discoverable: false,
|
||||
};
|
||||
|
||||
Channel::TextChannel {
|
||||
id: cid,
|
||||
server: id,
|
||||
name: "general".to_string(),
|
||||
description: None,
|
||||
|
||||
icon: None,
|
||||
last_message_id: None,
|
||||
|
||||
default_permissions: None,
|
||||
role_permissions: HashMap::new(),
|
||||
nsfw: false
|
||||
}
|
||||
.publish()
|
||||
.await?;
|
||||
|
||||
server.clone().create().await?;
|
||||
server.join_member(&user.id).await?;
|
||||
|
||||
Ok(json!(server))
|
||||
pub async fn req(/*_idempotency: IdempotencyKey, user: User,*/ info: Json<Data>) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,25 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use revolt_quark::{EmptyResponse, Result};
|
||||
|
||||
use mongodb::bson::doc;
|
||||
|
||||
#[delete("/<target>")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<EmptyResponse> {
|
||||
let target = target.fetch_server().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
return Err(Error::MissingPermission);
|
||||
}
|
||||
|
||||
if user.id == target.owner {
|
||||
target.delete().await?;
|
||||
} else {
|
||||
target.remove_member(&user.id, RemoveMember::Leave).await?;
|
||||
}
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use crate::notifications::events::ClientboundNotification;
|
||||
use crate::util::result::{Error, Result, EmptyResponse};
|
||||
use crate::{database::*, notifications::events::RemoveServerField};
|
||||
use revolt_quark::{EmptyResponse, Result, models::server::{FieldsServer, SystemMessageChannels, Category}};
|
||||
|
||||
use mongodb::bson::{doc, to_bson, to_document};
|
||||
use rocket::serde::json::Json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
@@ -17,143 +14,12 @@ pub struct Data {
|
||||
banner: Option<String>,
|
||||
categories: Option<Vec<Category>>,
|
||||
system_messages: Option<SystemMessageChannels>,
|
||||
remove: Option<RemoveServerField>,
|
||||
remove: Option<FieldsServer>,
|
||||
nsfw: Option<bool>,
|
||||
analytics: Option<bool>,
|
||||
}
|
||||
|
||||
#[patch("/<target>", data = "<data>")]
|
||||
pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
let data = data.into_inner();
|
||||
data.validate()
|
||||
.map_err(|error| Error::FailedValidation { error })?;
|
||||
|
||||
if data.name.is_none() && data.description.is_none() && data.icon.is_none() && data.banner.is_none() && data.remove.is_none() && data.categories.is_none() && data.system_messages.is_none() && data.nsfw.is_none() && data.analytics.is_none()
|
||||
{
|
||||
return Ok(EmptyResponse {});
|
||||
}
|
||||
|
||||
let target = target.fetch_server().await?;
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_manage_server() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
let mut set = doc! {};
|
||||
let mut unset = doc! {};
|
||||
|
||||
let mut remove_icon = false;
|
||||
let mut remove_banner = false;
|
||||
if let Some(remove) = &data.remove {
|
||||
match remove {
|
||||
RemoveServerField::Icon => {
|
||||
unset.insert("icon", 1);
|
||||
remove_icon = true;
|
||||
}
|
||||
RemoveServerField::Banner => {
|
||||
unset.insert("banner", 1);
|
||||
remove_banner = true;
|
||||
}
|
||||
RemoveServerField::Description => {
|
||||
unset.insert("description", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(name) = &data.name {
|
||||
set.insert("name", name);
|
||||
}
|
||||
|
||||
if let Some(description) = &data.description {
|
||||
set.insert("description", description);
|
||||
}
|
||||
|
||||
if let Some(attachment_id) = &data.icon {
|
||||
let attachment = File::find_and_use(&attachment_id, "icons", "object", &target.id).await?;
|
||||
set.insert(
|
||||
"icon",
|
||||
to_document(&attachment).map_err(|_| Error::DatabaseError {
|
||||
operation: "to_document",
|
||||
with: "attachment",
|
||||
})?,
|
||||
);
|
||||
|
||||
remove_icon = true;
|
||||
}
|
||||
|
||||
if let Some(attachment_id) = &data.banner {
|
||||
let attachment =
|
||||
File::find_and_use(&attachment_id, "banners", "server", &target.id).await?;
|
||||
set.insert(
|
||||
"banner",
|
||||
to_document(&attachment).map_err(|_| Error::DatabaseError {
|
||||
operation: "to_document",
|
||||
with: "attachment",
|
||||
})?,
|
||||
);
|
||||
|
||||
remove_banner = true;
|
||||
}
|
||||
|
||||
if let Some(categories) = &data.categories {
|
||||
set.insert("categories", to_bson(&categories).map_err(|_| Error::DatabaseError { operation: "to_document", with: "categories" })?);
|
||||
}
|
||||
|
||||
if let Some(system_messages) = &data.system_messages {
|
||||
set.insert("system_messages", to_bson(&system_messages).map_err(|_| Error::DatabaseError { operation: "to_document", with: "system_messages" })?);
|
||||
}
|
||||
|
||||
if let Some(nsfw) = &data.nsfw {
|
||||
set.insert("nsfw", nsfw);
|
||||
}
|
||||
|
||||
if let Some(analytics) = &data.analytics {
|
||||
set.insert("analytics", analytics);
|
||||
}
|
||||
|
||||
let mut operations = doc! {};
|
||||
if set.len() > 0 {
|
||||
operations.insert("$set", &set);
|
||||
}
|
||||
|
||||
if unset.len() > 0 {
|
||||
operations.insert("$unset", unset);
|
||||
}
|
||||
|
||||
if operations.len() > 0 {
|
||||
get_collection("servers")
|
||||
.update_one(doc! { "_id": &target.id }, operations, None)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError {
|
||||
operation: "update_one",
|
||||
with: "server",
|
||||
})?;
|
||||
}
|
||||
|
||||
ClientboundNotification::ServerUpdate {
|
||||
id: target.id.clone(),
|
||||
data: json!(set),
|
||||
clear: data.remove,
|
||||
}
|
||||
.publish(target.id.clone());
|
||||
|
||||
let Server { icon, banner, .. } = target;
|
||||
|
||||
if remove_icon {
|
||||
if let Some(old_icon) = icon {
|
||||
old_icon.delete().await?;
|
||||
}
|
||||
}
|
||||
|
||||
if remove_banner {
|
||||
if let Some(old_banner) = banner {
|
||||
old_banner.delete().await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(EmptyResponse {})
|
||||
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
use crate::database::*;
|
||||
use crate::util::result::{Error, Result};
|
||||
use revolt_quark::{Error, Result};
|
||||
|
||||
use rocket::serde::json::Value;
|
||||
|
||||
#[get("/<target>")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
||||
let target = target.fetch_server().await?;
|
||||
|
||||
let perm = permissions::PermissionCalculator::new(&user)
|
||||
.with_server(&target)
|
||||
.for_server()
|
||||
.await?;
|
||||
|
||||
if !perm.get_view() {
|
||||
Err(Error::MissingPermission)?
|
||||
}
|
||||
|
||||
Ok(json!(target))
|
||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user