Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
use crate::database::*;
use crate::util::result::{Error, Result};
use mongodb::bson::doc;
use mongodb::options::FindOneOptions;
use rocket_contrib::json::{Json, JsonValue};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct Options {
keys: Vec<String>,
}
#[post("/settings/fetch", data = "<options>")]
pub async fn req(user: User, options: Json<Options>) -> Result<JsonValue> {
let options = options.into_inner();
let mut projection = doc! {
"_id": 0,
};
for key in options.keys {
projection.insert(key, 1);
}
if let Some(doc) = get_collection("user_settings")
.find_one(
doc! {
"_id": user.id
},
FindOneOptions::builder().projection(projection).build(),
)
.await
.map_err(|_| Error::DatabaseError {
operation: "find_one",
with: "user_settings",
})?
{
Ok(json!(doc))
} else {
Ok(json!({}))
}
}
use crate::database::*;
use crate::util::result::Result;
use mongodb::bson::doc;
use rocket_contrib::json::JsonValue;
#[get("/unreads")]
pub async fn req(user: User) -> Result<JsonValue> {
Ok(json!(User::fetch_unreads(&user.id).await?))
}
use rocket::Route; use rocket::Route;
mod get_settings;
mod get_unreads;
mod set_settings;
pub fn routes() -> Vec<Route> { pub fn routes() -> Vec<Route> {
routes![] routes![get_settings::req, set_settings::req, get_unreads::req]
} }
use crate::database::*;
use crate::notifications::events::ClientboundNotification;
use crate::util::result::{Error, Result};
use chrono::prelude::*;
use mongodb::bson::{doc, to_bson};
use mongodb::options::UpdateOptions;
use rocket::request::Form;
use rocket_contrib::json::Json;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
type Data = HashMap<String, String>;
#[derive(Serialize, Deserialize, FromForm)]
pub struct Options {
timestamp: Option<i64>,
}
#[post("/settings/set?<options..>", data = "<data>")]
pub async fn req(user: User, data: Json<Data>, options: Form<Options>) -> Result<()> {
let data = data.into_inner();
let current_time = Utc::now().timestamp_millis();
let timestamp = if let Some(timestamp) = options.timestamp {
if timestamp > current_time {
current_time
} else {
timestamp
}
} else {
current_time
};
let mut set = doc! {};
for (key, data) in &data {
set.insert(
key.clone(),
vec![
to_bson(&timestamp).unwrap(),
to_bson(&data.clone()).unwrap(),
],
);
}
if set.len() > 0 {
get_collection("user_settings")
.update_one(
doc! {
"_id": &user.id
},
doc! {
"$set": &set
},
UpdateOptions::builder().upsert(true).build(),
)
.await
.map_err(|_| Error::DatabaseError {
operation: "update_one",
with: "user_settings",
})?;
}
ClientboundNotification::UserSettingsUpdate {
id: user.id.clone(),
update: json!(set),
}
.publish(user.id);
Ok(())
}
...@@ -74,21 +74,19 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> { ...@@ -74,21 +74,19 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> {
.from_override(&target_user, RelationshipStatus::Friend) .from_override(&target_user, RelationshipStatus::Friend)
.await?; .await?;
try_join!( ClientboundNotification::UserRelationship {
ClientboundNotification::UserRelationship { id: user.id.clone(),
id: user.id.clone(), user: target_user,
user: target_user, status: RelationshipStatus::Friend,
status: RelationshipStatus::Friend }
} .publish(user.id.clone());
.publish(user.id.clone()),
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.to_string(), id: target_id.to_string(),
user, user,
status: RelationshipStatus::Friend status: RelationshipStatus::Friend,
} }
.publish(target_id.to_string()) .publish(target_id.to_string());
)
.ok();
Ok(json!({ "status": "Friend" })) Ok(json!({ "status": "Friend" }))
} }
...@@ -136,21 +134,20 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> { ...@@ -136,21 +134,20 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> {
let user = user let user = user
.from_override(&target_user, RelationshipStatus::Incoming) .from_override(&target_user, RelationshipStatus::Incoming)
.await?; .await?;
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target_user, user: target_user,
status: RelationshipStatus::Outgoing status: RelationshipStatus::Outgoing,
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship {
id: target_id.to_string(), ClientboundNotification::UserRelationship {
user, id: target_id.to_string(),
status: RelationshipStatus::Incoming user,
} status: RelationshipStatus::Incoming,
.publish(target_id.to_string()) }
) .publish(target_id.to_string());
.ok();
Ok(json!({ "status": "Outgoing" })) Ok(json!({ "status": "Outgoing" }))
} }
......
...@@ -38,9 +38,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -38,9 +38,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
user: target, user: target,
status: RelationshipStatus::Blocked, status: RelationshipStatus::Blocked,
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
Ok(json!({ "status": "Blocked" })) Ok(json!({ "status": "Blocked" }))
} }
...@@ -77,28 +75,26 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -77,28 +75,26 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
) { ) {
Ok(_) => { Ok(_) => {
let target = target let target = target
.from_override(&user, RelationshipStatus::Friend) .from_override(&user, RelationshipStatus::Blocked)
.await?; .await?;
let user = user let user = user
.from_override(&target, RelationshipStatus::Friend) .from_override(&target, RelationshipStatus::BlockedOther)
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!( ClientboundNotification::UserRelationship {
ClientboundNotification::UserRelationship { id: user.id.clone(),
id: user.id.clone(), user: target,
user: target, status: RelationshipStatus::Blocked,
status: RelationshipStatus::Blocked }
} .publish(user.id.clone());
.publish(user.id.clone()),
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user, user,
status: RelationshipStatus::BlockedOther status: RelationshipStatus::BlockedOther,
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "Blocked" })) Ok(json!({ "status": "Blocked" }))
} }
...@@ -146,21 +142,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -146,21 +142,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!( ClientboundNotification::UserRelationship {
ClientboundNotification::UserRelationship { id: user.id.clone(),
id: user.id.clone(), user: target,
user: target, status: RelationshipStatus::Blocked,
status: RelationshipStatus::Blocked }
} .publish(user.id.clone());
.publish(user.id.clone()),
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user, user,
status: RelationshipStatus::BlockedOther status: RelationshipStatus::BlockedOther,
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "Blocked" })) Ok(json!({ "status": "Blocked" }))
} }
......
...@@ -57,12 +57,12 @@ pub async fn req( ...@@ -57,12 +57,12 @@ pub async fn req(
ClientboundNotification::UserUpdate { ClientboundNotification::UserUpdate {
id: user.id.clone(), id: user.id.clone(),
data: json!(data.0), data: json!({
clear: None "username": data.username
}),
clear: None,
} }
.publish(user.id.clone()) .publish_as_user(user.id.clone());
.await
.ok();
Ok(()) Ok(())
} }
use crate::{database::*, notifications::events::RemoveUserField};
use crate::notifications::events::ClientboundNotification; use crate::notifications::events::ClientboundNotification;
use crate::util::result::{Error, Result}; use crate::util::result::{Error, Result};
use crate::{database::*, notifications::events::RemoveUserField};
use mongodb::bson::{doc, to_document}; use mongodb::bson::{doc, to_document};
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
...@@ -25,7 +25,7 @@ pub struct Data { ...@@ -25,7 +25,7 @@ pub struct Data {
profile: Option<UserProfileData>, profile: Option<UserProfileData>,
#[validate(length(min = 1, max = 128))] #[validate(length(min = 1, max = 128))]
avatar: Option<String>, avatar: Option<String>,
remove: Option<RemoveUserField> remove: Option<RemoveUserField>,
} }
#[patch("/<_ignore_id>", data = "<data>")] #[patch("/<_ignore_id>", data = "<data>")]
...@@ -35,6 +35,14 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> ...@@ -35,6 +35,14 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
data.validate() data.validate()
.map_err(|error| Error::FailedValidation { error })?; .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(());
}
let mut unset = doc! {}; let mut unset = doc! {};
let mut set = doc! {}; let mut set = doc! {};
...@@ -45,14 +53,14 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> ...@@ -45,14 +53,14 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
match remove { match remove {
RemoveUserField::ProfileContent => { RemoveUserField::ProfileContent => {
unset.insert("profile.content", 1); unset.insert("profile.content", 1);
}, }
RemoveUserField::ProfileBackground => { RemoveUserField::ProfileBackground => {
unset.insert("profile.background", 1); unset.insert("profile.background", 1);
remove_background = true; remove_background = true;
} }
RemoveUserField::StatusText => { RemoveUserField::StatusText => {
unset.insert("status.text", 1); unset.insert("status.text", 1);
}, }
RemoveUserField::Avatar => { RemoveUserField::Avatar => {
unset.insert("avatar", 1); unset.insert("avatar", 1);
remove_avatar = true; remove_avatar = true;
...@@ -76,7 +84,8 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> ...@@ -76,7 +84,8 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
} }
if let Some(attachment_id) = profile.background { if let Some(attachment_id) = profile.background {
let attachment = File::find_and_use(&attachment_id, "backgrounds", "user", &user.id).await?; let attachment =
File::find_and_use(&attachment_id, "backgrounds", "user", &user.id).await?;
set.insert( set.insert(
"profile.background", "profile.background",
to_document(&attachment).map_err(|_| Error::DatabaseError { to_document(&attachment).map_err(|_| Error::DatabaseError {
...@@ -90,7 +99,7 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> ...@@ -90,7 +99,7 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
} }
let avatar = std::mem::replace(&mut data.avatar, None); let avatar = std::mem::replace(&mut data.avatar, None);
let attachment = if let Some(attachment_id) = avatar { if let Some(attachment_id) = avatar {
let attachment = File::find_and_use(&attachment_id, "avatars", "user", &user.id).await?; let attachment = File::find_and_use(&attachment_id, "avatars", "user", &user.id).await?;
set.insert( set.insert(
"avatar", "avatar",
...@@ -101,60 +110,33 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()> ...@@ -101,60 +110,33 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
); );
remove_avatar = true; remove_avatar = true;
Some(attachment) }
} else {
None
};
let mut operations = doc! {}; let mut operations = doc! {};
if set.len() > 0 { if set.len() > 0 {
operations.insert("$set", set); operations.insert("$set", &set);
} }
if unset.len() > 0 { if unset.len() > 0 {
operations.insert("$unset", unset); operations.insert("$unset", unset);
} }
get_collection("users") if operations.len() > 0 {
.update_one(doc! { "_id": &user.id }, operations, None) get_collection("users")
.await .update_one(doc! { "_id": &user.id }, operations, None)
.map_err(|_| Error::DatabaseError { .await
operation: "update_one", .map_err(|_| Error::DatabaseError {
with: "user", operation: "update_one",
})?; with: "user",
})?;
if let Some(status) = &data.status {
ClientboundNotification::UserUpdate {
id: user.id.clone(),
data: json!({ "status": status }),
clear: None
}
.publish(user.id.clone())
.await
.ok();
} }
if let Some(avatar) = attachment { ClientboundNotification::UserUpdate {
ClientboundNotification::UserUpdate { id: user.id.clone(),
id: user.id.clone(), data: json!(set),
data: json!({ "avatar": avatar }), clear: data.remove,
clear: None
}
.publish(user.id.clone())
.await
.ok();
}
if let Some(clear) = data.remove {
ClientboundNotification::UserUpdate {
id: user.id.clone(),
data: json!({}),
clear: Some(clear)
}
.publish(user.id.clone())
.await
.ok();
} }
.publish_as_user(user.id.clone());
if remove_avatar { if remove_avatar {
if let Some(old_avatar) = user.avatar { if let Some(old_avatar) = user.avatar {
......
...@@ -12,8 +12,8 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -12,8 +12,8 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.find( .find(
doc! { doc! {
"$and": [ "$and": [
{ "relations._id": &user.id, "relations.status": "Friend" }, { "relations": { "$elemMatch": { "_id": &user.id, "status": "Friend" } } },
{ "relations._id": &target.id, "relations.status": "Friend" } { "relations": { "$elemMatch": { "_id": &target.id, "status": "Friend" } } }
] ]
}, },
FindOptions::builder().projection(doc! { "_id": 1 }).build(), FindOptions::builder().projection(doc! { "_id": 1 }).build(),
......
use rocket::response::NamedFile; use rocket::{Request, Response};
use rocket::response::{self, NamedFile, Responder};
use std::path::Path; use std::path::Path;
use crate::database::Ref; use crate::database::Ref;
pub struct CachedFile(NamedFile);
pub static CACHE_CONTROL: &'static str = "public, max-age=31536000, immutable";
impl<'r> Responder<'r, 'static> for CachedFile {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
Response::build_from(self.0.respond_to(req)?)
.raw_header("Cache-control", CACHE_CONTROL)
.ok()
}
}
#[get("/<target>/default_avatar")] #[get("/<target>/default_avatar")]
pub async fn req(target: Ref) -> Option<NamedFile> { pub async fn req(target: Ref) -> Option<CachedFile> {
match target.id.chars().nth(25).unwrap() { match target.id.chars().nth(25).unwrap() {
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => {
NamedFile::open(Path::new("assets/user_red.png")).await.ok() NamedFile::open(Path::new("assets/user_red.png")).await.ok().map(|n| CachedFile(n))
} }
'8' | '9' | 'A' | 'C' | 'B' | 'D' | 'E' | 'F' => { '8' | '9' | 'A' | 'C' | 'B' | 'D' | 'E' | 'F' => {
NamedFile::open(Path::new("assets/user_green.png")) NamedFile::open(Path::new("assets/user_green.png"))
.await .await
.ok() .ok().map(|n| CachedFile(n))
} }
'G' | 'H' | 'J' | 'K' | 'M' | 'N' | 'P' | 'Q' => { 'G' | 'H' | 'J' | 'K' | 'M' | 'N' | 'P' | 'Q' => {
NamedFile::open(Path::new("assets/user_blue.png")) NamedFile::open(Path::new("assets/user_blue.png"))
.await .await
.ok() .ok().map(|n| CachedFile(n))
} }
'R' | 'S' | 'T' | 'V' | 'W' | 'X' | 'Y' | 'Z' => { 'R' | 'S' | 'T' | 'V' | 'W' | 'X' | 'Y' | 'Z' => {
NamedFile::open(Path::new("assets/user_yellow.png")) NamedFile::open(Path::new("assets/user_yellow.png"))
.await .await
.ok() .ok().map(|n| CachedFile(n))
} }
_ => unreachable!(), _ => unreachable!(),
} }
......
...@@ -53,21 +53,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -53,21 +53,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!( ClientboundNotification::UserRelationship {
ClientboundNotification::UserRelationship { id: user.id.clone(),
id: user.id.clone(), user: target,
user: target, status: RelationshipStatus::None,
status: RelationshipStatus::None }
} .publish(user.id.clone());
.publish(user.id.clone()),
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user, user,
status: RelationshipStatus::None status: RelationshipStatus::None,
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "None" })) Ok(json!({ "status": "None" }))
} }
......
...@@ -40,9 +40,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -40,9 +40,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
user: target, user: target,
status: RelationshipStatus::BlockedOther, status: RelationshipStatus::BlockedOther,
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
Ok(json!({ "status": "BlockedOther" })) Ok(json!({ "status": "BlockedOther" }))
} }
...@@ -84,21 +82,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ...@@ -84,21 +82,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!( ClientboundNotification::UserRelationship {
ClientboundNotification::UserRelationship { id: user.id.clone(),
id: user.id.clone(), user: target,
user: target, status: RelationshipStatus::None,
status: RelationshipStatus::None }
} .publish(user.id.clone());
.publish(user.id.clone()),
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user: user, user: user,
status: RelationshipStatus::None status: RelationshipStatus::None,
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "None" })) Ok(json!({ "status": "None" }))
} }
......
...@@ -3,77 +3,63 @@ use rocket::http::{ContentType, Status}; ...@@ -3,77 +3,63 @@ use rocket::http::{ContentType, Status};
use rocket::request::Request; use rocket::request::Request;
use rocket::response::{self, Responder, Response}; use rocket::response::{self, Responder, Response};
use serde::Serialize; use serde::Serialize;
use snafu::Snafu;
use std::io::Cursor; use std::io::Cursor;
use validator::ValidationErrors; use validator::ValidationErrors;
#[derive(Serialize, Debug, Snafu)] #[derive(Serialize, Debug)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Error { pub enum Error {
#[snafu(display("This error has not been labelled."))]
LabelMe, LabelMe,
// ? Onboarding related errors. // ? Onboarding related errors.
#[snafu(display("Already finished onboarding."))]
AlreadyOnboarded, AlreadyOnboarded,
// ? User related errors. // ? User related errors.
#[snafu(display("Username has already been taken."))]
UsernameTaken, UsernameTaken,
#[snafu(display("This user does not exist!"))]
UnknownUser, UnknownUser,
#[snafu(display("Already friends with this user."))]
AlreadyFriends, AlreadyFriends,
#[snafu(display("Already sent a request to this user."))]
AlreadySentRequest, AlreadySentRequest,
#[snafu(display("You have blocked this user."))]
Blocked, Blocked,
#[snafu(display("You have been blocked by this user."))]
BlockedByOther, BlockedByOther,
#[snafu(display("Not friends with target user."))]
NotFriends, NotFriends,
// ? Channel related errors. // ? Channel related errors.
#[snafu(display("This channel does not exist!"))]
UnknownChannel, UnknownChannel,
#[snafu(display("Attachment does not exist!"))]
UnknownAttachment, UnknownAttachment,
#[snafu(display("Cannot edit someone else's message."))] UnknownMessage,
CannotEditMessage, CannotEditMessage,
#[snafu(display("Cannot send empty message."))] CannotJoinCall,
TooManyAttachments,
TooManyReplies,
EmptyMessage, EmptyMessage,
#[snafu(display("Cannot remove yourself from a group, use delete channel instead."))]
CannotRemoveYourself, CannotRemoveYourself,
#[snafu(display("Group size is too large."))] GroupTooLarge {
GroupTooLarge { max: usize }, max: usize,
#[snafu(display("User already part of group."))] },
AlreadyInGroup, AlreadyInGroup,
#[snafu(display("User is not part of the group."))]
NotInGroup, NotInGroup,
// ? Server related errors.
UnknownServer,
InvalidRole,
Banned,
// ? General errors. // ? General errors.
#[snafu(display("Trying to fetch too much data."))]
TooManyIds, TooManyIds,
#[snafu(display("Failed to validate fields."))] FailedValidation {
FailedValidation { error: ValidationErrors }, error: ValidationErrors,
#[snafu(display("Encountered a database error."))] },
DatabaseError { DatabaseError {
operation: &'static str, operation: &'static str,
with: &'static str, with: &'static str,
}, },
#[snafu(display("Internal server error."))]
InternalError, InternalError,
#[snafu(display("Missing permission."))]
MissingPermission, MissingPermission,
#[snafu(display("Operation cannot be performed on this object."))]
InvalidOperation, InvalidOperation,
#[snafu(display("Email or password is incorrect."))]
InvalidCredentials, InvalidCredentials,
#[snafu(display("Already created an object with this nonce."))]
DuplicateNonce, DuplicateNonce,
#[snafu(display("Voso is not enabled on this instance."))]
VosoUnavailable, VosoUnavailable,
#[snafu(display("This request had no effect."))] NotFound,
NoEffect, NoEffect,
} }
...@@ -96,14 +82,22 @@ impl<'r> Responder<'r, 'static> for Error { ...@@ -96,14 +82,22 @@ impl<'r> Responder<'r, 'static> for Error {
Error::NotFriends => Status::Forbidden, Error::NotFriends => Status::Forbidden,
Error::UnknownChannel => Status::NotFound, Error::UnknownChannel => Status::NotFound,
Error::UnknownMessage => Status::NotFound,
Error::UnknownAttachment => Status::BadRequest, Error::UnknownAttachment => Status::BadRequest,
Error::CannotEditMessage => Status::Forbidden, Error::CannotEditMessage => Status::Forbidden,
Error::CannotJoinCall => Status::BadRequest,
Error::TooManyAttachments => Status::BadRequest,
Error::TooManyReplies => Status::BadRequest,
Error::EmptyMessage => Status::UnprocessableEntity, Error::EmptyMessage => Status::UnprocessableEntity,
Error::CannotRemoveYourself => Status::BadRequest, Error::CannotRemoveYourself => Status::BadRequest,
Error::GroupTooLarge { .. } => Status::Forbidden, Error::GroupTooLarge { .. } => Status::Forbidden,
Error::AlreadyInGroup => Status::Conflict, Error::AlreadyInGroup => Status::Conflict,
Error::NotInGroup => Status::NotFound, Error::NotInGroup => Status::NotFound,
Error::UnknownServer => Status::NotFound,
Error::InvalidRole => Status::NotFound,
Error::Banned => Status::Forbidden,
Error::FailedValidation { .. } => Status::UnprocessableEntity, Error::FailedValidation { .. } => Status::UnprocessableEntity,
Error::DatabaseError { .. } => Status::InternalServerError, Error::DatabaseError { .. } => Status::InternalServerError,
Error::InternalError => Status::InternalServerError, Error::InternalError => Status::InternalServerError,
...@@ -113,6 +107,7 @@ impl<'r> Responder<'r, 'static> for Error { ...@@ -113,6 +107,7 @@ impl<'r> Responder<'r, 'static> for Error {
Error::InvalidCredentials => Status::Forbidden, Error::InvalidCredentials => Status::Forbidden,
Error::DuplicateNonce => Status::Conflict, Error::DuplicateNonce => Status::Conflict,
Error::VosoUnavailable => Status::BadRequest, Error::VosoUnavailable => Status::BadRequest,
Error::NotFound => Status::NotFound,
Error::NoEffect => Status::Ok, Error::NoEffect => Status::Ok,
}; };
......
...@@ -18,6 +18,8 @@ lazy_static! { ...@@ -18,6 +18,8 @@ lazy_static! {
pub static ref AUTUMN_URL: String = pub static ref AUTUMN_URL: String =
env::var("AUTUMN_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("AUTUMN_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref JANUARY_URL: String =
env::var("JANUARY_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref VOSO_URL: String = pub static ref VOSO_URL: String =
env::var("VOSO_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("VOSO_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref VOSO_WS_HOST: String = pub static ref VOSO_WS_HOST: String =
...@@ -35,7 +37,6 @@ lazy_static! { ...@@ -35,7 +37,6 @@ lazy_static! {
env::var("REVOLT_VAPID_PUBLIC_KEY").expect("Missing REVOLT_VAPID_PUBLIC_KEY environment variable."); env::var("REVOLT_VAPID_PUBLIC_KEY").expect("Missing REVOLT_VAPID_PUBLIC_KEY environment variable.");
// Application Flags // Application Flags
pub static ref DISABLE_REGISTRATION: bool = env::var("REVOLT_DISABLE_REGISTRATION").map_or(false, |v| v == "1");
pub static ref INVITE_ONLY: bool = env::var("REVOLT_INVITE_ONLY").map_or(false, |v| v == "1"); pub static ref INVITE_ONLY: bool = env::var("REVOLT_INVITE_ONLY").map_or(false, |v| v == "1");
pub static ref USE_EMAIL: bool = env::var("REVOLT_USE_EMAIL_VERIFICATION").map_or( pub static ref USE_EMAIL: bool = env::var("REVOLT_USE_EMAIL_VERIFICATION").map_or(
env::var("REVOLT_SMTP_HOST").is_ok() env::var("REVOLT_SMTP_HOST").is_ok()
...@@ -47,6 +48,7 @@ lazy_static! { ...@@ -47,6 +48,7 @@ lazy_static! {
pub static ref USE_HCAPTCHA: bool = env::var("REVOLT_HCAPTCHA_KEY").is_ok(); pub static ref USE_HCAPTCHA: bool = env::var("REVOLT_HCAPTCHA_KEY").is_ok();
pub static ref USE_PROMETHEUS: bool = env::var("REVOLT_ENABLE_PROMETHEUS").map_or(false, |v| v == "1"); pub static ref USE_PROMETHEUS: bool = env::var("REVOLT_ENABLE_PROMETHEUS").map_or(false, |v| v == "1");
pub static ref USE_AUTUMN: bool = env::var("AUTUMN_PUBLIC_URL").is_ok(); pub static ref USE_AUTUMN: bool = env::var("AUTUMN_PUBLIC_URL").is_ok();
pub static ref USE_JANUARY: bool = env::var("JANUARY_PUBLIC_URL").is_ok();
pub static ref USE_VOSO: bool = env::var("VOSO_PUBLIC_URL").is_ok() && env::var("VOSO_MANAGE_TOKEN").is_ok(); pub static ref USE_VOSO: bool = env::var("VOSO_PUBLIC_URL").is_ok() && env::var("VOSO_MANAGE_TOKEN").is_ok();
// SMTP Settings // SMTP Settings
...@@ -61,6 +63,8 @@ lazy_static! { ...@@ -61,6 +63,8 @@ lazy_static! {
// Application Logic Settings // Application Logic Settings
pub static ref MAX_GROUP_SIZE: usize = pub static ref MAX_GROUP_SIZE: usize =
env::var("REVOLT_MAX_GROUP_SIZE").unwrap_or_else(|_| "50".to_string()).parse().unwrap(); env::var("REVOLT_MAX_GROUP_SIZE").unwrap_or_else(|_| "50".to_string()).parse().unwrap();
pub static ref EARLY_ADOPTER_BADGE: i64 =
env::var("REVOLT_EARLY_ADOPTER_BADGE").unwrap_or_else(|_| "0".to_string()).parse().unwrap();
} }
pub fn preflight_checks() { pub fn preflight_checks() {
......
pub const VERSION: &str = "0.4.1-alpha.6"; pub const VERSION: &str = "0.5.1-alpha.21";