Update to mongo 1.1.0-beta, start reset + migrations

This commit is contained in:
Paul Makles
2020-08-04 10:04:08 +02:00
parent 6a1912c27b
commit 17c9148556
18 changed files with 1367 additions and 1125 deletions

2387
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,13 @@
[package] [package]
name = "revolt" name = "revolt"
version = "0.2.2" version = "0.2.3"
authors = ["Paul Makles <paulmakles@gmail.com>"] authors = ["Paul Makles <paulmakles@gmail.com>"]
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
mongodb = "0.9.2" mongodb = { version = "1.1.0-beta", default-features = false, features = ["sync"] } # FIXME: rewrite database with async API
bson = "0.14.1"
rocket = { version = "0.4.4", default-features = false } rocket = { version = "0.4.4", default-features = false }
once_cell = "1.3.1" once_cell = "1.3.1"
dotenv = "0.15.0" dotenv = "0.15.0"

View File

@@ -3,7 +3,7 @@ use super::get_collection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use rocket::request::FromParam; use rocket::request::FromParam;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use bson::{doc, from_bson}; use mongodb::bson::{Bson, doc, from_bson};
use rocket::http::RawStr; use rocket::http::RawStr;
use lru::LruCache; use lru::LruCache;
@@ -60,7 +60,7 @@ pub fn fetch_channel(id: &str) -> Result<Option<Channel>, String> {
let col = get_collection("channels"); let col = get_collection("channels");
if let Ok(result) = col.find_one(doc! { "_id": id }, None) { if let Ok(result) = col.find_one(doc! { "_id": id }, None) {
if let Some(doc) = result { if let Some(doc) = result {
if let Ok(channel) = from_bson(bson::Bson::Document(doc)) as Result<Channel, _> { if let Ok(channel) = from_bson(Bson::Document(doc)) as Result<Channel, _> {
let mut cache = CACHE.lock().unwrap(); let mut cache = CACHE.lock().unwrap();
cache.put(id.to_string(), channel.clone()); cache.put(id.to_string(), channel.clone());
@@ -105,7 +105,7 @@ pub fn fetch_channels(ids: &Vec<String>) -> Result<Option<Vec<Channel>>, String>
for item in result { for item in result {
let mut cache = CACHE.lock().unwrap(); let mut cache = CACHE.lock().unwrap();
if let Ok(doc) = item { if let Ok(doc) = item {
if let Ok(channel) = from_bson(bson::Bson::Document(doc)) as Result<Channel, _> { if let Ok(channel) = from_bson(Bson::Document(doc)) as Result<Channel, _> {
cache.put(channel.id.clone(), channel.clone()); cache.put(channel.id.clone(), channel.clone());
channels.push(channel); channels.push(channel);
} else { } else {

View File

@@ -3,7 +3,7 @@ use super::get_collection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use rocket::request::FromParam; use rocket::request::FromParam;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use bson::{doc, from_bson}; use mongodb::bson::{Bson, doc, from_bson};
use rocket::http::RawStr; use rocket::http::RawStr;
use lru::LruCache; use lru::LruCache;
@@ -68,7 +68,7 @@ pub fn fetch_guild(id: &str) -> Result<Option<Guild>, String> {
let col = get_collection("guilds"); let col = get_collection("guilds");
if let Ok(result) = col.find_one(doc! { "_id": id }, None) { if let Ok(result) = col.find_one(doc! { "_id": id }, None) {
if let Some(doc) = result { if let Some(doc) = result {
if let Ok(guild) = from_bson(bson::Bson::Document(doc)) as Result<Guild, _> { if let Ok(guild) = from_bson(Bson::Document(doc)) as Result<Guild, _> {
let mut cache = CACHE.lock().unwrap(); let mut cache = CACHE.lock().unwrap();
cache.put(id.to_string(), guild.clone()); cache.put(id.to_string(), guild.clone());
@@ -109,7 +109,7 @@ pub fn get_member(guild_id: &String, member: &String) -> Option<Member> {
None, None,
) { ) {
if let Some(doc) = result { if let Some(doc) = result {
Some(from_bson(bson::Bson::Document(doc)).expect("Failed to unwrap member.")) Some(from_bson(Bson::Document(doc)).expect("Failed to unwrap member."))
} else { } else {
None None
} }
@@ -166,7 +166,7 @@ pub fn get_invite<U: Into<Option<String>>>(
Some(( Some((
doc.get_str("_id").unwrap().to_string(), doc.get_str("_id").unwrap().to_string(),
doc.get_str("name").unwrap().to_string(), doc.get_str("name").unwrap().to_string(),
from_bson(bson::Bson::Document(invite.clone())).unwrap(), from_bson(Bson::Document(invite.clone())).unwrap(),
)) ))
} else { } else {
None None

View File

@@ -5,16 +5,16 @@ use crate::database::channel::Channel;
use super::get_collection; use super::get_collection;
use crate::notifications; use crate::notifications;
use bson::{doc, to_bson, UtcDateTime}; use mongodb::bson::{doc, to_bson, Bson, DateTime};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use rocket::request::FromParam; use rocket::request::FromParam;
use bson::from_bson; use mongodb::bson::from_bson;
use rocket::http::RawStr; use rocket::http::RawStr;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct PreviousEntry { pub struct PreviousEntry {
pub content: String, pub content: String,
pub time: UtcDateTime, pub time: DateTime,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@@ -26,7 +26,7 @@ pub struct Message {
pub author: String, pub author: String,
pub content: String, pub content: String,
pub edited: Option<UtcDateTime>, pub edited: Option<DateTime>,
pub previous_content: Vec<PreviousEntry>, pub previous_content: Vec<PreviousEntry>,
} }
@@ -101,7 +101,7 @@ impl<'r> FromParam<'r> for Message {
.unwrap(); .unwrap();
if let Some(message) = result { if let Some(message) = result {
Ok(from_bson(bson::Bson::Document(message)).expect("Failed to unwrap message.")) Ok(from_bson(Bson::Document(message)).expect("Failed to unwrap message."))
} else { } else {
Err(param) Err(param)
} }

View File

@@ -1,4 +1,5 @@
use mongodb::{Client, Collection, Database}; use mongodb::sync::{Client, Collection, Database};
use mongodb::bson::doc;
use std::env; use std::env;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@@ -9,6 +10,8 @@ pub fn connect() {
Client::with_uri_str(&env::var("DB_URI").expect("DB_URI not in environment variables!")) Client::with_uri_str(&env::var("DB_URI").expect("DB_URI not in environment variables!"))
.expect("Failed to init db connection."); .expect("Failed to init db connection.");
client.database("revolt").collection("migrations").find(doc! { }, None).expect("Failed to get migration data from database.");
DBCONN.set(client).unwrap(); DBCONN.set(client).unwrap();
} }

View File

@@ -1,6 +1,6 @@
use super::{get_collection, MemberPermissions}; use super::{get_collection, MemberPermissions};
use bson::doc; use mongodb::bson::doc;
use mongodb::options::FindOptions; use mongodb::options::FindOptions;
pub fn find_mutual_guilds(user_id: &str, target_id: &str) -> Vec<String> { pub fn find_mutual_guilds(user_id: &str, target_id: &str) -> Vec<String> {

View File

@@ -1,12 +1,12 @@
use bson::UtcDateTime; use mongodb::bson::DateTime;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UserEmailVerification { pub struct UserEmailVerification {
pub verified: bool, pub verified: bool,
pub target: Option<String>, pub target: Option<String>,
pub expiry: Option<UtcDateTime>, pub expiry: Option<DateTime>,
pub rate_limit: Option<UtcDateTime>, pub rate_limit: Option<DateTime>,
pub code: Option<String>, pub code: Option<String>,
} }

View File

@@ -35,6 +35,17 @@ pub fn send_verification_email(email: String, code: String) -> bool {
.is_ok() .is_ok()
} }
pub fn send_password_reset(email: String, code: String) -> bool {
let url = format!("{}/api/account/reset/{}", public_uri(), code);
send_email(
email,
"Reset your password.".to_string(),
format!("Reset your password here: {}", url),
format!("<a href=\"{}\">Click to reset your password!</a>", url),
)
.is_ok()
}
pub fn send_welcome_email(email: String, username: String) -> bool { pub fn send_welcome_email(email: String, username: String) -> bool {
send_email( send_email(
email, email,

View File

@@ -1,4 +1,4 @@
use bson::{doc, from_bson, Document}; use mongodb::bson::{Bson, doc, from_bson, Document};
use mongodb::options::FindOneOptions; use mongodb::options::FindOneOptions;
use rocket::http::{RawStr, Status}; use rocket::http::{RawStr, Status};
use rocket::request::{self, FromParam, FromRequest, Request}; use rocket::request::{self, FromParam, FromRequest, Request};
@@ -143,7 +143,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for User {
if let Some(user) = result { if let Some(user) = result {
Outcome::Success( Outcome::Success(
from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."), from_bson(Bson::Document(user)).expect("Failed to unwrap user."),
) )
} else { } else {
Outcome::Failure((Status::Forbidden, AuthError::Invalid)) Outcome::Failure((Status::Forbidden, AuthError::Invalid))

View File

@@ -1,4 +1,4 @@
use bson::{doc, from_bson, Bson, Document}; use mongodb::bson::{doc, from_bson, Bson, Document};
use mongodb::options::FindOneOptions; use mongodb::options::FindOneOptions;
use rocket::http::RawStr; use rocket::http::RawStr;
use rocket::request::FromParam; use rocket::request::FromParam;
@@ -36,7 +36,7 @@ impl GuildRef {
) { ) {
Ok(result) => match result { Ok(result) => match result {
Some(doc) => { Some(doc) => {
Some(from_bson(bson::Bson::Document(doc)).expect("Failed to unwrap guild.")) Some(from_bson(mongodb::bson::mongodb::bson::Document(doc)).expect("Failed to unwrap guild."))
} }
None => None, None => None,
}, },
@@ -85,7 +85,7 @@ pub fn get_member(guild_id: &String, member: &String) -> Option<Member> {
None, None,
) { ) {
if let Some(doc) = result { if let Some(doc) = result {
Some(from_bson(Bson::Document(doc)).expect("Failed to unwrap member.")) Some(from_bson(mongodb::bson::Document(doc)).expect("Failed to unwrap member."))
} else { } else {
None None
} }
@@ -142,7 +142,7 @@ pub fn get_invite<U: Into<Option<String>>>(
Some(( Some((
doc.get_str("_id").unwrap().to_string(), doc.get_str("_id").unwrap().to_string(),
doc.get_str("name").unwrap().to_string(), doc.get_str("name").unwrap().to_string(),
from_bson(Bson::Document(invite.clone())).unwrap(), from_bson(mongodb::bson::Document(invite.clone())).unwrap(),
)) ))
} else { } else {
None None

View File

@@ -1,7 +1,7 @@
use super::events::Notification; use super::events::Notification;
use crate::database::get_collection; use crate::database::get_collection;
use bson::{doc, from_bson, to_bson, Bson}; use mongodb::bson::{doc, from_bson, to_bson, Bson};
use mongodb::options::{CursorType, FindOneOptions, FindOptions}; use mongodb::options::{CursorType, FindOneOptions, FindOptions};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;

View File

@@ -1,7 +1,7 @@
use crate::database; use crate::database;
use crate::util::vec_to_set; use crate::util::vec_to_set;
use bson::doc; use mongodb::bson::doc;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use mongodb::options::FindOneOptions; use mongodb::options::FindOneOptions;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;

View File

@@ -4,7 +4,7 @@ use crate::email;
use crate::util::gen_token; use crate::util::gen_token;
use bcrypt::{hash, verify}; use bcrypt::{hash, verify};
use bson::{doc, from_bson, Bson::UtcDatetime}; use mongodb::bson::{doc, from_bson, Bson};
use chrono::prelude::*; use chrono::prelude::*;
use database::user::User; use database::user::User;
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
@@ -75,8 +75,8 @@ pub fn create(info: Json<Create>) -> Response {
"email_verification": { "email_verification": {
"verified": false, "verified": false,
"target": info.email.clone(), "target": info.email.clone(),
"expiry": UtcDatetime(Utc::now() + chrono::Duration::days(1)), "expiry": Bson::DateTime(Utc::now() + chrono::Duration::days(1)),
"rate_limit": UtcDatetime(Utc::now() + chrono::Duration::minutes(1)), "rate_limit": Bson::DateTime(Utc::now() + chrono::Duration::minutes(1)),
"code": code.clone(), "code": code.clone(),
} }
}, },
@@ -110,7 +110,7 @@ pub fn verify_email(code: String) -> Response {
.find_one(doc! { "email_verification.code": code.clone() }, None) .find_one(doc! { "email_verification.code": code.clone() }, None)
.expect("Failed user lookup") .expect("Failed user lookup")
{ {
let user: User = from_bson(bson::Bson::Document(u)).expect("Failed to unwrap user."); let user: User = from_bson(Bson::Document(u)).expect("Failed to unwrap user.");
let ev = user.email_verification; let ev = user.email_verification;
if Utc::now() > *ev.expiry.unwrap() { if Utc::now() > *ev.expiry.unwrap() {
@@ -169,7 +169,7 @@ pub fn resend_email(info: Json<Resend>) -> Response {
) )
.expect("Failed user lookup.") .expect("Failed user lookup.")
{ {
let user: User = from_bson(bson::Bson::Document(u)).expect("Failed to unwrap user."); let user: User = from_bson(Bson::Document(u)).expect("Failed to unwrap user.");
let ev = user.email_verification; let ev = user.email_verification;
let expiry = ev.expiry.unwrap(); let expiry = ev.expiry.unwrap();
@@ -180,7 +180,7 @@ pub fn resend_email(info: Json<Resend>) -> Response {
json!({ "error": "You are being rate limited, please try again in a while." }), json!({ "error": "You are being rate limited, please try again in a while." }),
) )
} else { } else {
let mut new_expiry = UtcDatetime(Utc::now() + chrono::Duration::days(1)); let mut new_expiry = Bson::DateTime(Utc::now() + chrono::Duration::days(1));
if info.email.clone() != user.email { if info.email.clone() != user.email {
if Utc::now() > *expiry { if Utc::now() > *expiry {
return Response::Gone( return Response::Gone(
@@ -188,7 +188,7 @@ pub fn resend_email(info: Json<Resend>) -> Response {
); );
} }
new_expiry = UtcDatetime(*expiry); new_expiry = Bson::DateTime(*expiry);
} }
let code = gen_token(48); let code = gen_token(48);
@@ -198,7 +198,7 @@ pub fn resend_email(info: Json<Resend>) -> Response {
"$set": { "$set": {
"email_verification.code": code.clone(), "email_verification.code": code.clone(),
"email_verification.expiry": new_expiry, "email_verification.expiry": new_expiry,
"email_verification.rate_limit": UtcDatetime(Utc::now() + chrono::Duration::minutes(1)), "email_verification.rate_limit": Bson::DateTime(Utc::now() + chrono::Duration::minutes(1)),
}, },
}, },
None, None,
@@ -234,7 +234,7 @@ pub fn login(info: Json<Login>) -> Response {
.find_one(doc! { "email": info.email.clone() }, None) .find_one(doc! { "email": info.email.clone() }, None)
.expect("Failed user lookup") .expect("Failed user lookup")
{ {
let user: User = from_bson(bson::Bson::Document(u)).expect("Failed to unwrap user."); let user: User = from_bson(Bson::Document(u)).expect("Failed to unwrap user.");
match verify(info.password.clone(), &user.password) match verify(info.password.clone(), &user.password)
.expect("Failed to check hash of password.") .expect("Failed to check hash of password.")

View File

@@ -10,7 +10,7 @@ use crate::notifications::{
}; };
use crate::util::vec_to_set; use crate::util::vec_to_set;
use bson::{doc, from_bson, Bson, Bson::UtcDatetime}; use mongodb::bson::{doc, from_bson, Bson};
use chrono::prelude::*; use chrono::prelude::*;
use mongodb::options::FindOptions; use mongodb::options::FindOptions;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
@@ -531,7 +531,7 @@ pub fn messages(
let mut messages = Vec::new(); let mut messages = Vec::new();
for item in result { for item in result {
let message: Message = let message: Message =
from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap message."); from_bson(Bson::Document(item.unwrap())).expect("Failed to unwrap message.");
messages.push(json!({ messages.push(json!({
"id": message.id, "id": message.id,
"author": message.author, "author": message.author,
@@ -667,7 +667,7 @@ pub fn edit_message(
doc! { doc! {
"$set": { "$set": {
"content": &edit.content, "content": &edit.content,
"edited": UtcDatetime(edited) "edited": Bson::DateTime(edited)
}, },
"$push": { "$push": {
"previous_content": { "previous_content": {

View File

@@ -9,7 +9,7 @@ use crate::notifications::{
}; };
use crate::util::gen_token; use crate::util::gen_token;
use bson::{doc, from_bson, Bson}; use mongodb::bson::{doc, from_bson, Bson};
use mongodb::options::{FindOneOptions, FindOptions}; use mongodb::options::{FindOneOptions, FindOptions};
use rocket::request::Form; use rocket::request::Form;
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
@@ -107,7 +107,7 @@ pub fn guild(user: UserRef, target: Guild) -> Option<Response> {
for item in results { for item in results {
if let Ok(entry) = item { if let Ok(entry) = item {
if let Ok(channel) = if let Ok(channel) =
from_bson(bson::Bson::Document(entry)) as Result<Channel, _> from_bson(Bson::Document(entry)) as Result<Channel, _>
{ {
channels.push(json!({ channels.push(json!({
"id": channel.id, "id": channel.id,

View File

@@ -1,12 +1,12 @@
use super::Response; use super::Response;
use bson::doc; use mongodb::bson::doc;
/// root /// root
#[get("/")] #[get("/")]
pub fn root() -> Response { pub fn root() -> Response {
Response::Success(json!({ Response::Success(json!({
"revolt": "0.2.2" "revolt": "0.2.3"
})) }))
} }

View File

@@ -7,7 +7,7 @@ use crate::notifications::{
}; };
use crate::routes::channel; use crate::routes::channel;
use bson::doc; use mongodb::bson::doc;
use mongodb::options::{Collation, FindOptions, FindOneOptions}; use mongodb::options::{Collation, FindOptions, FindOneOptions};
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -148,6 +148,7 @@ pub fn dms(user: UserRef) -> Response {
for item in results { for item in results {
if let Ok(doc) = item { if let Ok(doc) = item {
let id = doc.get_str("_id").unwrap(); let id = doc.get_str("_id").unwrap();
let last_message = doc.get_document("last_message").unwrap();
let recipients = doc.get_array("recipients").unwrap(); let recipients = doc.get_array("recipients").unwrap();
match doc.get_i32("type").unwrap() { match doc.get_i32("type").unwrap() {
@@ -155,6 +156,7 @@ pub fn dms(user: UserRef) -> Response {
channels.push(json!({ channels.push(json!({
"id": id, "id": id,
"type": 0, "type": 0,
"last_message": last_message,
"recipients": recipients, "recipients": recipients,
})); }));
} }