feat: implement channel invites, perms, group create, members fetch

chore: when you accidentally run fmt
This commit is contained in:
Paul Makles
2022-02-04 21:50:30 +00:00
parent b58755dbeb
commit 88f811761b
59 changed files with 536 additions and 195 deletions

View File

@@ -30,8 +30,8 @@ use rauth::{
logic::Auth,
};
use revolt_quark::DatabaseInfo;
use std::str::FromStr;
use rocket_cors::AllowedOrigins;
use std::str::FromStr;
/*use util::variables::{
APP_URL, HCAPTCHA_KEY, INVITE_ONLY, SMTP_FROM, SMTP_HOST, SMTP_PASSWORD, SMTP_USERNAME,
USE_EMAIL, USE_HCAPTCHA,

View File

@@ -1,7 +1,7 @@
use revolt_quark::Result;
use rauth::util::EmptyResponse;
use revolt_quark::Result;
#[delete("/<target>")]
pub async fn delete_bot(/*user: UserRef, target: Ref*/ target: String) -> Result<EmptyResponse> {
pub async fn delete_bot(/*user: UserRef, target: Ref*/ target: String,) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,6 +1,6 @@
use crate::util::regex::RE_USERNAME;
use revolt_quark::{Result, models::bot::FieldsBot, EmptyResponse};
use revolt_quark::{models::bot::FieldsBot, EmptyResponse, Result};
use mongodb::bson::doc;
use rocket::serde::json::Json;
@@ -19,6 +19,9 @@ pub struct Data {
}
#[patch("/<target>", data = "<data>")]
pub async fn edit_bot(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn edit_bot(
/*user: UserRef, target: Ref,*/ target: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -5,22 +5,25 @@ use serde::Deserialize;
#[derive(Deserialize)]
pub struct ServerId {
server: String
server: String,
}
#[derive(Deserialize)]
pub struct GroupId {
group: String
group: String,
}
#[derive(Deserialize)]
#[serde(untagged)]
pub enum Destination {
Server(ServerId),
Group(GroupId)
Group(GroupId),
}
#[post("/<target>/invite", data = "<dest>")]
pub async fn invite_bot(/*user: UserRef, target: Ref,*/ target: String, dest: Json<Destination>) -> Result<EmptyResponse> {
pub async fn invite_bot(
/*user: UserRef, target: Ref,*/ target: String,
dest: Json<Destination>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,12 +1,12 @@
use rocket::Route;
mod create;
mod invite;
mod fetch_public;
mod delete;
mod edit;
mod fetch;
mod fetch_owned;
mod edit;
mod delete;
mod fetch_public;
mod invite;
pub fn routes() -> Vec<Route> {
routes![

View File

@@ -1,6 +1,9 @@
use revolt_quark::{EmptyResponse, Result};
#[put("/<target>/ack/<message>")]
pub async fn req(/*user: UserRef, target: Ref, message: Ref*/ target: String, message: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref, message: Ref*/ target: String,
message: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,4 +1,7 @@
use revolt_quark::{Error, EmptyResponse, Result, models::{User, Channel, channel::PartialChannel}, Ref, Db, perms, ChannelPermission};
use revolt_quark::{
models::{channel::PartialChannel, Channel, User},
perms, ChannelPermission, Db, EmptyResponse, Error, Ref, Result,
};
use mongodb::bson::doc;
@@ -8,16 +11,21 @@ pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
let perm = perms(&user).channel(&channel).calc_channel(db).await;
if !perm.get_view() {
return Err(Error::NotFound)
return Err(Error::NotFound);
}
match channel {
Channel::SavedMessages { .. } => Err(Error::NoEffect),
Channel::DirectMessage { id, .. } => {
db.update_channel(&id, &PartialChannel {
active: Some(false),
..Default::default()
}, vec![]).await?;
db.update_channel(
&id,
&PartialChannel {
active: Some(false),
..Default::default()
},
vec![],
)
.await?;
Ok(EmptyResponse)
}
@@ -29,10 +37,15 @@ pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
} => {
if user.id == owner {
if let Some(new_owner) = recipients.iter().find(|x| *x != &user.id) {
db.update_channel(&id, &PartialChannel {
owner: Some(new_owner.into()),
..Default::default()
}, vec![]).await?;
db.update_channel(
&id,
&PartialChannel {
owner: Some(new_owner.into()),
..Default::default()
},
vec![],
)
.await?;
} else {
db.delete_channel(&id).await?;
return Ok(EmptyResponse);
@@ -54,13 +67,14 @@ pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
Ok(EmptyResponse)
}
Channel::TextChannel { id, .. } |
Channel::VoiceChannel { id, .. } => {
Channel::TextChannel { id, .. } | Channel::VoiceChannel { id, .. } => {
if perm.get_manage_channel() {
db.delete_channel(&id).await?;
Ok(EmptyResponse)
} else {
Err(Error::MissingPermission { permission: ChannelPermission::ManageChannel as i32 })
Err(Error::MissingPermission {
permission: ChannelPermission::ManageChannel as i32,
})
}
}
}

View File

@@ -1,4 +1,10 @@
use revolt_quark::{Error, Result, models::{channel::{FieldsChannel, PartialChannel, Channel}, User, File}, Ref, Database, perms, ChannelPermission};
use revolt_quark::{
models::{
channel::{Channel, FieldsChannel, PartialChannel},
File, User,
},
perms, ChannelPermission, Database, Error, Ref, Result,
};
use mongodb::bson::doc;
use rocket::{serde::json::Json, State};
@@ -22,24 +28,63 @@ pub struct Data {
}
#[patch("/<target>", data = "<data>")]
pub async fn req(db: &State<Database>, user: User, target: Ref, data: Json<Data>) -> Result<Json<Channel>> {
pub async fn req(
db: &State<Database>,
user: User,
target: Ref,
data: Json<Data>,
) -> Result<Json<Channel>> {
let data = data.into_inner();
data.validate().map_err(|error| Error::FailedValidation { error })?;
data.validate()
.map_err(|error| Error::FailedValidation { error })?;
let mut channel = target.as_channel(db).await?;
if !perms(&user).channel(&channel).calc_channel(db).await.get_manage_channel() {
return Err(Error::MissingPermission { permission: ChannelPermission::ManageChannel as i32 })
if !perms(&user)
.channel(&channel)
.calc_channel(db)
.await
.get_manage_channel()
{
return Err(Error::MissingPermission {
permission: ChannelPermission::ManageChannel as i32,
});
}
if data.name.is_none() && data.description.is_none() && data.icon.is_none() && data.nsfw.is_none() && data.remove.is_none() {
return Ok(Json(channel))
if data.name.is_none()
&& data.description.is_none()
&& data.icon.is_none()
&& data.nsfw.is_none()
&& data.remove.is_none()
{
return Ok(Json(channel));
}
let mut partial: PartialChannel = Default::default();
match &mut channel {
Channel::Group { id, name, description, icon, nsfw, .. }
| Channel::TextChannel { id, name, description, icon, nsfw, .. }
| Channel::VoiceChannel { id, name, description, icon, nsfw, .. } => {
Channel::Group {
id,
name,
description,
icon,
nsfw,
..
}
| Channel::TextChannel {
id,
name,
description,
icon,
nsfw,
..
}
| Channel::VoiceChannel {
id,
name,
description,
icon,
nsfw,
..
} => {
if let Some(fields) = &data.remove {
if fields.contains(&FieldsChannel::Icon) {
if let Some(icon) = &icon {
@@ -51,10 +96,10 @@ pub async fn req(db: &State<Database>, user: User, target: Ref, data: Json<Data>
match field {
FieldsChannel::Description => {
description.take();
},
}
FieldsChannel::Icon => {
icon.take();
},
}
_ => {}
}
}
@@ -80,9 +125,10 @@ pub async fn req(db: &State<Database>, user: User, target: Ref, data: Json<Data>
partial.nsfw = Some(new_nsfw);
}
db.update_channel(id, &partial, data.remove.unwrap_or_default()).await?;
},
_ => return Err(Error::InvalidOperation)
db.update_channel(id, &partial, data.remove.unwrap_or_default())
.await?;
}
_ => return Err(Error::InvalidOperation),
};
Ok(Json(channel))

View File

@@ -1,4 +1,7 @@
use revolt_quark::{Error, Result, models::{User, Channel}, Ref, Database, perms, ChannelPermission};
use revolt_quark::{
models::{Channel, User},
perms, ChannelPermission, Database, Error, Ref, Result,
};
use rocket::{serde::json::Json, State};
@@ -6,9 +9,16 @@ use rocket::{serde::json::Json, State};
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<Channel>> {
let target = target.as_channel(db).await?;
if perms(&user).channel(&target).calc_channel(db).await.get_view() {
if perms(&user)
.channel(&target)
.calc_channel(db)
.await
.get_view()
{
Ok(Json(target))
} else {
Err(Error::MissingPermission { permission: ChannelPermission::View as i32 })
Err(Error::MissingPermission {
permission: ChannelPermission::View as i32,
})
}
}

View File

@@ -3,6 +3,9 @@ use revolt_quark::{EmptyResponse, Result};
use mongodb::bson::doc;
#[put("/<target>/recipients/<member>")]
pub async fn req(/*user: UserRef, target: Ref, member: Ref*/ target: String, member: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref, member: Ref*/ target: String,
member: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,8 +1,15 @@
use revolt_quark::Result;
use std::{collections::HashSet, iter::FromIterator};
use revolt_quark::{
get_relationship,
models::{user::RelationshipStatus, Channel, User},
Db, Error, Result,
};
use mongodb::bson::doc;
use rocket::serde::json::{Json, Value};
use rocket::serde::json::Json;
use serde::{Deserialize, Serialize};
use ulid::Ulid;
use validator::Validate;
#[derive(Validate, Serialize, Deserialize)]
@@ -13,10 +20,48 @@ pub struct Data {
description: Option<String>,
users: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
nsfw: Option<bool>
nsfw: Option<bool>,
}
#[post("/create", data = "<info>")]
pub async fn req(/*_idempotency: IdempotencyKey, user: User,*/ info: Json<Data>) -> Result<Value> {
todo!();
pub async fn req(db: &Db, user: User, info: Json<Data>) -> Result<Json<Channel>> {
let info = info.into_inner();
info.validate()
.map_err(|error| Error::FailedValidation { error })?;
let mut set: HashSet<String> = HashSet::from_iter(info.users.into_iter());
set.insert(user.id.clone());
// ! FIXME: un hard code this
if set.len() > 50 {
return Err(Error::GroupTooLarge { max: 50 });
}
for target in &set {
match get_relationship(&user, target) {
RelationshipStatus::Friend | RelationshipStatus::User => {}
_ => {
return Err(Error::NotFriends);
}
}
}
let group = Channel::Group {
id: Ulid::new().to_string(),
name: info.name,
owner: user.id,
description: info.description,
recipients: set.into_iter().collect::<Vec<String>>(),
icon: None,
last_message_id: None,
permissions: None,
nsfw: info.nsfw.unwrap_or(false),
};
db.insert_channel(&group).await?;
Ok(Json(group))
}

View File

@@ -3,6 +3,9 @@ use revolt_quark::{EmptyResponse, Result};
use mongodb::bson::doc;
#[delete("/<target>/recipients/<member>")]
pub async fn req(/*user: UserRef, target: Ref, member: Ref*/ target: String, member: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref, member: Ref*/ target: String,
member: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,17 +1,25 @@
use revolt_quark::Result;
use revolt_quark::{
models::{Invite, User},
perms, ChannelPermission, Db, Error, Ref, Result,
};
use mongodb::bson::doc;
use rocket::serde::json::Value;
lazy_static! {
static ref ALPHABET: [char; 54] = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'
];
}
use rocket::serde::json::Json;
#[post("/<target>/invites")]
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
todo!()
pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Invite>> {
let channel = target.as_channel(db).await?;
if !perms(&user)
.channel(&channel)
.calc_channel(db)
.await
.get_invite_others()
{
return Err(Error::MissingPermission {
permission: ChannelPermission::InviteOthers as i32,
});
}
Invite::create(db, &user, &channel).await.map(Json)
}

View File

@@ -1,8 +1,31 @@
use revolt_quark::Result;
use revolt_quark::{
models::{Channel, User},
perms, Db, Error, Ref, Result,
};
use rocket::serde::json::Value;
use rocket::serde::json::Json;
#[get("/<target>/members")]
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
todo!()
pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Vec<User>>> {
let channel = target.as_channel(db).await?;
if !perms(&user)
.channel(&channel)
.calc_channel(db)
.await
.get_view()
{
return Err(Error::NotFound);
}
if let Channel::Group { recipients, .. } = channel {
Ok(Json(
db.fetch_users(&recipients)
.await?
.into_iter()
.map(|x| x.with_relationship(&user))
.collect::<Vec<User>>(),
))
} else {
Err(Error::InvalidOperation)
}
}

View File

@@ -3,6 +3,9 @@ use revolt_quark::{EmptyResponse, Result};
use mongodb::bson::doc;
#[delete("/<target>/messages/<msg>")]
pub async fn req(/*user: UserRef, target: Ref, msg: Ref*/ target: String, msg: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref, msg: Ref*/ target: String,
msg: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,7 +1,7 @@
use revolt_quark::{EmptyResponse, Result};
use chrono::Utc;
use mongodb::bson::{Bson, Document, doc, to_document};
use mongodb::bson::{doc, to_document, Bson, Document};
use rocket::serde::json::Json;
use serde::{Deserialize, Serialize};
use validator::Validate;
@@ -15,6 +15,10 @@ pub struct Data {
}
#[patch("/<target>/messages/<msg>", data = "<edit>")]
pub async fn req(/*user: UserRef, target: Ref, msg: Ref,*/ target: String, msg: String, edit: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref, msg: Ref,*/ target: String,
msg: String,
edit: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -3,6 +3,9 @@ use revolt_quark::Result;
use rocket::serde::json::Value;
#[get("/<target>/messages/<msg>")]
pub async fn req(/*user: UserRef, target: Ref, msg: Ref*/ target: String, msg: String) -> Result<Value> {
pub async fn req(
/*user: UserRef, target: Ref, msg: Ref*/ target: String,
msg: String,
) -> Result<Value> {
todo!()
}

View File

@@ -2,7 +2,7 @@ use std::collections::HashSet;
use revolt_quark::{Error, Result};
use futures::{StreamExt, try_join};
use futures::{try_join, StreamExt};
use mongodb::{
bson::{doc, from_document},
options::FindOptions,
@@ -35,6 +35,9 @@ pub struct Options {
}
#[get("/<target>/messages?<options..>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, options: Options) -> Result<Value> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
options: Options,
) -> Result<Value> {
todo!()
}

View File

@@ -11,6 +11,9 @@ pub struct Options {
}
#[post("/<target>/messages/stale", data = "<data>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Options>) -> Result<Value> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
data: Json<Options>,
) -> Result<Value> {
todo!()
}

View File

@@ -39,6 +39,9 @@ pub struct Options {
}
#[post("/<target>/search", data = "<options>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, options: Json<Options>) -> Result<Value> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
options: Json<Options>,
) -> Result<Value> {
todo!()
}

View File

@@ -1,4 +1,4 @@
use revolt_quark::{Result, models::message::Masquerade};
use revolt_quark::{models::message::Masquerade, Result};
use mongodb::bson::doc;
use regex::Regex;
@@ -9,7 +9,7 @@ use validator::Validate;
#[derive(Serialize, Deserialize)]
pub struct Reply {
id: String,
mention: bool
mention: bool,
}
#[derive(Validate, Serialize, Deserialize, Clone, Debug)]
@@ -21,7 +21,7 @@ pub struct SendableEmbed {
#[validate(length(min = 1, max = 2000))]
description: Option<String>,
media: Option<String>,
colour: Option<String>,
colour: Option<String>,
}
#[derive(Validate, Serialize, Deserialize)]
pub struct Data {
@@ -34,7 +34,7 @@ pub struct Data {
//#[validate]
masquerade: Option<Masquerade>,
#[validate(length(min = 1, max = 10))]
embeds: Option<Vec<SendableEmbed>>
embeds: Option<Vec<SendableEmbed>>,
}
lazy_static! {
@@ -43,6 +43,10 @@ lazy_static! {
}
#[post("/<target>/messages", data = "<message>")]
pub async fn message_send(/*user: UserRef, _r: Ratelimiter, mut idempotency: IdempotencyKey, target: Ref,*/ target: String, message: Json<Data>) -> /*Result<RatelimitResponse<Value>>*/ Result<Value> {
pub async fn message_send(
/*user: UserRef, _r: Ratelimiter, mut idempotency: IdempotencyKey, target: Ref,*/
target: String,
message: Json<Data>,
) -> Result<Value> {
todo!()
}

View File

@@ -4,21 +4,21 @@ mod channel_ack;
mod channel_delete;
mod channel_edit;
mod channel_fetch;
mod members_fetch;
mod group_add_member;
mod group_create;
mod group_remove_member;
mod invite_create;
mod voice_join;
mod members_fetch;
mod message_delete;
mod message_edit;
mod message_fetch;
mod message_query;
mod message_search;
mod message_query_stale;
mod message_search;
mod message_send;
mod permissions_set;
mod permissions_set_default;
mod voice_join;
pub fn routes() -> Vec<Route> {
routes![

View File

@@ -1,16 +1,44 @@
use mongodb::bson::doc;
use rocket::serde::json::Json;
use serde::{Serialize, Deserialize};
use validator::Contains;
use serde::{Deserialize, Serialize};
use revolt_quark::{EmptyResponse, Result};
use revolt_quark::{
models::{Channel, User},
perms, ChannelPermission, Db, EmptyResponse, Error, Ref, Result,
};
#[derive(Serialize, Deserialize)]
pub struct Data {
permissions: u32
permissions: u32,
}
#[put("/<target>/permissions/<role>", data = "<data>", rank = 2)]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role: String, data: Json<Data>) -> Result<EmptyResponse> {
todo!()
pub async fn req(
db: &Db,
user: User,
target: Ref,
role: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
let channel = target.as_channel(db).await?;
if !perms(&user)
.channel(&channel)
.calc_channel(db)
.await
.get_manage_channel()
{
return Err(Error::MissingPermission {
permission: ChannelPermission::ManageChannel as i32,
});
}
match channel {
Channel::TextChannel { id, .. } | Channel::VoiceChannel { id, .. } => {
db.set_channel_role_permission(&id, &role, data.permissions)
.await?;
}
_ => return Err(Error::InvalidOperation),
}
Ok(EmptyResponse)
}

View File

@@ -1,15 +1,56 @@
use mongodb::bson::doc;
use rocket::serde::json::Json;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use revolt_quark::{EmptyResponse, Result};
use revolt_quark::{
models::{channel::PartialChannel, Channel, User},
perms, ChannelPermission, Db, EmptyResponse, Error, Ref, Result,
};
#[derive(Serialize, Deserialize)]
pub struct Data {
permissions: u32
permissions: u32,
}
#[put("/<target>/permissions/default", data = "<data>", rank = 1)]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
todo!()
pub async fn req(db: &Db, user: User, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
let channel = target.as_channel(db).await?;
if !perms(&user)
.channel(&channel)
.calc_channel(db)
.await
.get_manage_channel()
{
return Err(Error::MissingPermission {
permission: ChannelPermission::ManageChannel as i32,
});
}
match channel {
Channel::Group { id, .. } => {
db.update_channel(
&id,
&PartialChannel {
permissions: Some(data.permissions as i32),
..Default::default()
},
vec![],
)
.await?;
}
Channel::TextChannel { id, .. } | Channel::VoiceChannel { id, .. } => {
db.update_channel(
&id,
&PartialChannel {
default_permissions: Some(data.permissions as i32),
..Default::default()
},
vec![],
)
.await?;
}
_ => return Err(Error::InvalidOperation),
}
Ok(EmptyResponse)
}

View File

@@ -1,5 +1,5 @@
use revolt_quark::Result;
use revolt_quark::models::File;
use revolt_quark::Result;
use rocket::serde::json::Value;
use serde::Serialize;

View File

@@ -1,5 +1,5 @@
use revolt_quark::{EmptyResponse, Error, Result, models::User, Database};
use crate::util::regex::RE_USERNAME;
use revolt_quark::{models::User, Database, EmptyResponse, Error, Result};
use mongodb::bson::doc;
use rauth::entities::Session;
@@ -14,9 +14,14 @@ pub struct Data {
}
#[post("/complete", data = "<data>")]
pub async fn req(db: &State<Database>, session: Session, user: Option<User>, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
db: &State<Database>,
session: Session,
user: Option<User>,
data: Json<Data>,
) -> Result<EmptyResponse> {
if user.is_some() {
return Err(Error::AlreadyOnboarded)
return Err(Error::AlreadyOnboarded);
}
let data = data.into_inner();
@@ -33,7 +38,5 @@ pub async fn req(db: &State<Database>, session: Session, user: Option<User>, dat
..Default::default()
};
db.insert_user(&user)
.await
.map(|_| EmptyResponse)
db.insert_user(&user).await.map(|_| EmptyResponse)
}

View File

@@ -5,6 +5,7 @@ use rauth::entities::{Model, Session, WebPushSubscription};
use rocket::serde::json::Json;
#[post("/subscribe"/*, data = "<data>"*/)]
pub async fn req(/*mut session: Session, data: Json<WebPushSubscription>*/) -> Result<EmptyResponse> {
pub async fn req(/*mut session: Session, data: Json<WebPushSubscription>*/) -> Result<EmptyResponse>
{
todo!()
}

View File

@@ -12,6 +12,10 @@ pub struct Data {
}
#[put("/<server>/bans/<target>", data = "<data>")]
pub async fn req(/*user: UserRef, server: Ref, target: Ref,*/ server: String, target: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, server: Ref, target: Ref,*/ server: String,
target: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,17 +1,17 @@
use revolt_quark::{Error, Result};
use revolt_quark::models::File;
use revolt_quark::{Error, Result};
use futures::StreamExt;
use mongodb::options::FindOptions;
use serde::{Serialize, Deserialize};
use rocket::serde::json::Value;
use mongodb::bson::{doc, from_document};
use mongodb::options::FindOptions;
use rocket::serde::json::Value;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct BannedUser {
_id: String,
username: String,
avatar: Option<File>
avatar: Option<File>,
}
#[get("/<target>/bans")]

View File

@@ -3,6 +3,9 @@ use revolt_quark::{EmptyResponse, Result};
use mongodb::bson::doc;
#[delete("/<server>/bans/<target>")]
pub async fn req(/*user: UserRef, server: Ref, target: Ref*/ server: String, target: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, server: Ref, target: Ref*/ server: String,
target: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -11,7 +11,7 @@ use validator::Validate;
#[derive(Serialize, Deserialize)]
enum ChannelType {
Text,
Voice
Voice,
}
impl Default for ChannelType {
@@ -33,6 +33,9 @@ pub struct Data {
}
#[post("/<target>/channels", data = "<info>")]
pub async fn req(/*_idempotency: IdempotencyKey, user: User, target: Ref,*/ target: String, info: Json<Data>) -> Result<Value> {
pub async fn req(
/*_idempotency: IdempotencyKey, user: User, target: Ref,*/ target: String,
info: Json<Data>,
) -> Result<Value> {
todo!()
}

View File

@@ -1,4 +1,4 @@
use revolt_quark::{EmptyResponse, Result, models::server_member::FieldsMember};
use revolt_quark::{models::server_member::FieldsMember, EmptyResponse, Result};
use rocket::serde::json::Json;
use serde::{Deserialize, Serialize};
@@ -14,6 +14,10 @@ pub struct Data {
}
#[patch("/<server>/members/<target>", data = "<data>")]
pub async fn req(/*user: UserRef, server: Ref,*/ server: String, target: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, server: Ref,*/ server: String,
target: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -4,6 +4,9 @@ use mongodb::bson::doc;
use rocket::serde::json::Value;
#[get("/<target>/members/<member>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, member: String) -> Result<Value> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
member: String,
) -> Result<Value> {
todo!()
}

View File

@@ -3,6 +3,9 @@ use revolt_quark::{EmptyResponse, Result};
use mongodb::bson::doc;
#[delete("/<target>/members/<member>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, member: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
member: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,10 +1,10 @@
use rocket::Route;
mod server_ack;
mod server_create;
mod server_delete;
mod server_edit;
mod server_fetch;
mod server_ack;
mod channel_create;
@@ -19,11 +19,11 @@ mod ban_remove;
mod invites_fetch;
mod roles_create;
mod roles_edit;
mod roles_delete;
mod permissions_set;
mod permissions_set_default;
mod roles_create;
mod roles_delete;
mod roles_edit;
pub fn routes() -> Vec<Route> {
routes![

View File

@@ -1,21 +1,25 @@
use mongodb::bson::doc;
use rocket::serde::json::Json;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use revolt_quark::{EmptyResponse, Result};
#[derive(Serialize, Deserialize)]
pub struct Values {
server: u32,
channel: u32
channel: u32,
}
#[derive(Serialize, Deserialize)]
pub struct Data {
permissions: Values
permissions: Values,
}
#[put("/<target>/permissions/<role_id>", data = "<data>", rank = 2)]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role_id: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
role_id: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,21 +1,24 @@
use mongodb::bson::doc;
use rocket::serde::json::Json;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use revolt_quark::{EmptyResponse, Result};
#[derive(Serialize, Deserialize)]
pub struct Values {
server: u32,
channel: u32
channel: u32,
}
#[derive(Serialize, Deserialize)]
pub struct Data {
permissions: Values
permissions: Values,
}
#[put("/<target>/permissions/default", data = "<data>", rank = 1)]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,18 +1,21 @@
use revolt_quark::{Error, Result};
use ulid::Ulid;
use mongodb::bson::doc;
use validator::Validate;
use serde::{Serialize, Deserialize};
use rocket::serde::json::{Json, Value};
use serde::{Deserialize, Serialize};
use ulid::Ulid;
use validator::Validate;
#[derive(Validate, Serialize, Deserialize)]
pub struct Data {
#[validate(length(min = 1, max = 32))]
name: String
name: String,
}
#[post("/<target>/roles", data = "<data>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<Value> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
data: Json<Data>,
) -> Result<Value> {
todo!()
}

View File

@@ -1,6 +1,9 @@
use revolt_quark::{EmptyResponse, Result};
#[delete("/<target>/roles/<role_id>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role_id: String) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
role_id: String,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -17,6 +17,10 @@ pub struct Data {
}
#[patch("/<target>/roles/<role_id>", data = "<data>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, role_id: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
role_id: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -15,10 +15,10 @@ pub struct Data {
#[validate(length(min = 0, max = 1024))]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
nsfw: Option<bool>
nsfw: Option<bool>,
}
#[post("/create", data = "<info>")]
pub async fn req(/*_idempotency: IdempotencyKey, user: User,*/ info: Json<Data>) -> Result<Value> {
pub async fn req(/*_idempotency: IdempotencyKey, user: User,*/ info: Json<Data>,) -> Result<Value> {
todo!()
}

View File

@@ -1,4 +1,7 @@
use revolt_quark::{EmptyResponse, Result, models::server::{FieldsServer, SystemMessageChannels, Category}};
use revolt_quark::{
models::server::{Category, FieldsServer, SystemMessageChannels},
EmptyResponse, Result,
};
use rocket::serde::json::Json;
use serde::{Deserialize, Serialize};
@@ -20,6 +23,9 @@ pub struct Data {
}
#[patch("/<target>", data = "<data>")]
pub async fn req(/*user: UserRef, target: Ref,*/ target: String, data: Json<Data>) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef, target: Ref,*/ target: String,
data: Json<Data>,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -16,6 +16,9 @@ pub struct Options {
}
#[post("/settings/set?<options..>", data = "<data>")]
pub async fn req(/*user: UserRef,*/ data: Json<Data>, options: Options) -> Result<EmptyResponse> {
pub async fn req(
/*user: UserRef,*/ data: Json<Data>,
options: Options,
) -> Result<EmptyResponse> {
todo!()
}

View File

@@ -1,9 +1,9 @@
use revolt_quark::models::User;
use revolt_quark::{Result, Database};
use revolt_quark::{Database, Result};
use mongodb::bson::doc;
use rocket::State;
use rocket::serde::json::Json;
use rocket::State;
#[put("/<username>/friend")]
pub async fn req(db: &State<Database>, user: User, username: String) -> Result<Json<User>> {

View File

@@ -1,9 +1,9 @@
use revolt_quark::models::User;
use revolt_quark::{Result, Database};
use revolt_quark::{Database, Result};
use mongodb::bson::doc;
use rocket::State;
use rocket::serde::json::Json;
use rocket::State;
#[put("/<username>/block")]
pub async fn req(db: &State<Database>, user: User, username: String) -> Result<Json<User>> {

View File

@@ -1,7 +1,7 @@
use revolt_quark::{Error, EmptyResponse, Result, models::User, Database};
use crate::util::regex::RE_USERNAME;
use mongodb::bson::doc;
use rauth::entities::Account;
use revolt_quark::{models::User, Database, EmptyResponse, Error, Result};
use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize};
use validator::Validate;
@@ -22,6 +22,10 @@ pub async fn req(
data: Json<Data>,
) -> Result<EmptyResponse> {
let data = data.into_inner();
account.verify_password(&data.password).map_err(|_| Error::InvalidCredentials)?;
user.update_username(db, data.username).await.map(|_| EmptyResponse)
account
.verify_password(&data.password)
.map_err(|_| Error::InvalidCredentials)?;
user.update_username(db, data.username)
.await
.map(|_| EmptyResponse)
}

View File

@@ -1,13 +1,13 @@
//! Edit currently authenticated user.
use revolt_quark::models::user::{FieldsUser, PartialUser, User};
use revolt_quark::models::File;
use revolt_quark::{Error, Result, Database};
use revolt_quark::models::user::{FieldsUser, User, PartialUser};
use revolt_quark::{Database, Error, Result};
use mongodb::bson::doc;
use revolt_quark::models::user::UserStatus;
use rocket::State;
use rocket::serde::json::Json;
use rocket::State;
use serde::{Deserialize, Serialize};
use validator::Validate;
@@ -36,10 +36,15 @@ pub struct Data {
#[patch("/@me", data = "<data>")]
pub async fn req(db: &State<Database>, mut user: User, data: Json<Data>) -> Result<Json<User>> {
let data = data.into_inner();
data.validate().map_err(|error| Error::FailedValidation { error })?;
data.validate()
.map_err(|error| Error::FailedValidation { error })?;
if data.status.is_none() && data.profile.is_none() && data.avatar.is_none() && data.remove.is_none() {
return Ok(Json(user))
if data.status.is_none()
&& data.profile.is_none()
&& data.avatar.is_none()
&& data.remove.is_none()
{
return Ok(Json(user));
}
if let Some(fields) = &data.remove {
@@ -97,6 +102,7 @@ pub async fn req(db: &State<Database>, mut user: User, data: Json<Data>) -> Resu
user.profile = partial.profile.clone();
}
db.update_user(&user.id, &partial, data.remove.unwrap_or_default()).await?;
db.update_user(&user.id, &partial, data.remove.unwrap_or_default())
.await?;
Ok(Json(user.foreign()))
}

View File

@@ -1,8 +1,11 @@
//! Fetch direct messages that the current user is involved in
//!
//!
//! This includes group DMs and "active" 1:1 DMs.
use revolt_quark::{Result, models::{Channel, User}, Database};
use revolt_quark::{
models::{Channel, User},
Database, Result,
};
use mongodb::bson::doc;
use rocket::{serde::json::Json, State};

View File

@@ -1,9 +1,12 @@
//! Fetch another user's profile
//!
//!
//! Will fail if the authenticated user does not
//! have permission to access the other user's profile.
use revolt_quark::{Ref, Result, Error, models::{User, user::UserProfile}, perms, Database};
use revolt_quark::{
models::{user::UserProfile, User},
perms, Database, Error, Ref, Result,
};
use rocket::{serde::json::Json, State};
@@ -11,7 +14,12 @@ use rocket::{serde::json::Json, State};
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<UserProfile>> {
let target = target.as_user(db).await?;
if perms(&user).user(&target).calc_user(db).await.get_view_profile() {
if perms(&user)
.user(&target)
.calc_user(db)
.await
.get_view_profile()
{
Ok(Json(target.profile.unwrap_or_default()))
} else {
Err(Error::NotFound)

View File

@@ -1,11 +1,11 @@
//! Fetch the currently authenticated session's user account
use revolt_quark::Result;
use revolt_quark::models::User;
use rocket::serde::json::Json;
#[get("/@me")]
pub async fn req(user: User) -> Result<Json<User>> {
Ok(Json(user.foreign()))
}
//! Fetch the currently authenticated session's user account
use revolt_quark::models::User;
use revolt_quark::Result;
use rocket::serde::json::Json;
#[get("/@me")]
pub async fn req(user: User) -> Result<Json<User>> {
Ok(Json(user.foreign()))
}

View File

@@ -1,16 +1,16 @@
//! Fetch another user
//!
//!
//! Will fail if the authenticated user does not
//! have permission to access the other user.
use revolt_quark::{Ref, Result, Error, models::User, perms, Database};
use revolt_quark::{models::User, perms, Database, Error, Ref, Result};
use rocket::{serde::json::Json, State};
#[get("/<target>")]
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<User>> {
let target = target.as_user(db).await?;
let permissions = perms(&user).user(&target).calc_user(db).await;
if permissions.get_access() {
Ok(Json(target.with_perspective(&user, &permissions)))

View File

@@ -2,16 +2,21 @@
//! authenticated user and the target user
use revolt_quark::models::User;
use revolt_quark::{Error, Result, perms, Database, Ref};
use revolt_quark::{perms, Database, Error, Ref, Result};
use rocket::State;
use rocket::serde::json::Value;
use rocket::State;
#[get("/<target>/mutual")]
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Value> {
let target = target.as_user(db).await?;
if perms(&user).user(&target).calc_user(db).await.get_view_profile() {
if perms(&user)
.user(&target)
.calc_user(db)
.await
.get_view_profile()
{
Ok(json!({
"users": db.fetch_mutual_user_ids(&user.id, &target.id).await?,
"servers": db.fetch_mutual_server_ids(&user.id, &target.id).await?

View File

@@ -1,6 +1,6 @@
use rocket::{Request, Response};
use rocket::response::{self, Responder};
use rocket::fs::NamedFile;
use rocket::response::{self, Responder};
use rocket::{Request, Response};
use std::path::Path;
pub struct CachedFile(NamedFile);
@@ -19,22 +19,28 @@ impl<'r> Responder<'r, 'static> for CachedFile {
pub async fn req(target: String) -> Option<CachedFile> {
match target.chars().nth(25).unwrap() {
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => {
NamedFile::open(Path::new("assets/user_red.png")).await.ok().map(CachedFile)
NamedFile::open(Path::new("assets/user_red.png"))
.await
.ok()
.map(CachedFile)
}
'8' | '9' | 'A' | 'C' | 'B' | 'D' | 'E' | 'F' => {
NamedFile::open(Path::new("assets/user_green.png"))
.await
.ok().map(CachedFile)
.ok()
.map(CachedFile)
}
'G' | 'H' | 'J' | 'K' | 'M' | 'N' | 'P' | 'Q' => {
NamedFile::open(Path::new("assets/user_blue.png"))
.await
.ok().map(CachedFile)
.ok()
.map(CachedFile)
}
'R' | 'S' | 'T' | 'V' | 'W' | 'X' | 'Y' | 'Z' => {
NamedFile::open(Path::new("assets/user_yellow.png"))
.await
.ok().map(CachedFile)
.ok()
.map(CachedFile)
}
_ => unreachable!(),
}

View File

@@ -6,13 +6,13 @@ mod change_username;
mod edit_user;
mod fetch_dms;
mod fetch_profile;
mod fetch_self;
mod fetch_user;
mod find_mutual;
mod get_default_avatar;
mod open_dm;
mod remove_friend;
mod unblock_user;
mod fetch_self;
pub fn routes() -> Vec<Route> {
routes![

View File

@@ -1,9 +1,12 @@
//! Open a direct message with another user
use revolt_quark::{Error, Result, Ref, models::{User, Channel}, Database, perms, UserPermission};
use revolt_quark::{
models::{Channel, User},
perms, Database, Error, Ref, Result, UserPermission,
};
use mongodb::bson::doc;
use rocket::{State, serde::json::Json};
use rocket::{serde::json::Json, State};
use ulid::Ulid;
#[get("/<target>/dm")]
@@ -12,14 +15,16 @@ pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<C
if let Ok(channel) = db.find_direct_message_channel(&user.id, &target.id).await {
Ok(Json(channel))
} else if perms(&user).user(&target).calc_user(db).await.get_send_message() {
} else if perms(&user)
.user(&target)
.calc_user(db)
.await
.get_send_message()
{
let new_channel = Channel::DirectMessage {
id: Ulid::new().to_string(),
active: false,
recipients: vec! [
user.id.clone(),
target.id.clone()
],
recipients: vec![user.id.clone(), target.id.clone()],
last_message_id: None,
};

View File

@@ -1,9 +1,9 @@
use revolt_quark::models::User;
use revolt_quark::{Result, Database};
use revolt_quark::{Database, Result};
use mongodb::bson::doc;
use rocket::State;
use rocket::serde::json::Json;
use rocket::State;
#[delete("/<username>/friend")]
pub async fn req(db: &State<Database>, user: User, username: String) -> Result<Json<User>> {

View File

@@ -1,9 +1,9 @@
use revolt_quark::models::User;
use revolt_quark::{Result, Database};
use revolt_quark::{Database, Result};
use mongodb::bson::doc;
use rocket::State;
use rocket::serde::json::Json;
use rocket::State;
#[delete("/<username>/block")]
pub async fn req(db: &State<Database>, user: User, username: String) -> Result<Json<User>> {

View File

@@ -2,4 +2,4 @@
// pub mod variables;
// pub mod ratelimit;
pub mod regex;
// pub mod idempotency;
// pub mod idempotency;