forked from jmug/stoatchat
Re-do guards, streamline requests.
This commit is contained in:
12
src/database/channel.rs
Normal file
12
src/database/channel.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
use serde::{ Deserialize, Serialize };
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Channel {
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
pub id: String,
|
||||||
|
pub channel_type: u8,
|
||||||
|
|
||||||
|
// for Direct Messages
|
||||||
|
pub recipients: Option<Vec<String>>,
|
||||||
|
pub active: Option<bool>,
|
||||||
|
}
|
||||||
8
src/database/message.rs
Normal file
8
src/database/message.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
use serde::{ Deserialize, Serialize };
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Message {
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
@@ -24,4 +24,6 @@ pub fn get_collection(collection: &str) -> Collection {
|
|||||||
get_db().collection(collection)
|
get_db().collection(collection)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
pub mod channel;
|
||||||
|
pub mod message;
|
||||||
|
|||||||
@@ -3,15 +3,9 @@ use rocket::http::{ Status, RawStr };
|
|||||||
use rocket::request::{ self, Request, FromRequest, FromParam };
|
use rocket::request::{ self, Request, FromRequest, FromParam };
|
||||||
|
|
||||||
use bson::{ bson, doc, from_bson };
|
use bson::{ bson, doc, from_bson };
|
||||||
use ulid::Ulid;
|
|
||||||
|
|
||||||
use crate::database;
|
use crate::database;
|
||||||
|
use database::user::User;
|
||||||
pub struct User(
|
|
||||||
pub Ulid,
|
|
||||||
pub String,
|
|
||||||
pub database::user::User,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AuthError {
|
pub enum AuthError {
|
||||||
@@ -33,11 +27,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for User {
|
|||||||
let result = col.find_one(doc! { "access_token": key }, None).unwrap();
|
let result = col.find_one(doc! { "access_token": key }, None).unwrap();
|
||||||
|
|
||||||
if let Some(user) = result {
|
if let Some(user) = result {
|
||||||
Outcome::Success(User (
|
Outcome::Success(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
|
||||||
Ulid::from_string(user.get_str("_id").unwrap()).unwrap(),
|
|
||||||
user.get_str("username").unwrap().to_string(),
|
|
||||||
from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.")
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Outcome::Failure((Status::Forbidden, AuthError::Invalid))
|
Outcome::Failure((Status::Forbidden, AuthError::Invalid))
|
||||||
}
|
}
|
||||||
@@ -55,11 +45,7 @@ impl<'r> FromParam<'r> for User {
|
|||||||
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
||||||
|
|
||||||
if let Some(user) = result {
|
if let Some(user) = result {
|
||||||
Ok(User (
|
Ok(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
|
||||||
Ulid::from_string(user.get_str("_id").unwrap()).unwrap(),
|
|
||||||
user.get_str("username").unwrap().to_string(),
|
|
||||||
from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.")
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(param)
|
Err(param)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,11 @@
|
|||||||
use rocket::Outcome;
|
use rocket::http::{ RawStr };
|
||||||
use rocket::http::{ Status, RawStr };
|
use rocket::request::{ FromParam };
|
||||||
use rocket::request::{ self, Request, FromRequest, FromParam };
|
use bson::{ bson, doc, from_bson };
|
||||||
|
|
||||||
use bson::{ bson, doc, ordered::OrderedDocument };
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
use ulid::Ulid;
|
|
||||||
|
|
||||||
use crate::database;
|
use crate::database;
|
||||||
use crate::routes::channel::ChannelType;
|
|
||||||
|
|
||||||
pub struct Channel (
|
use database::channel::Channel;
|
||||||
pub Ulid,
|
use database::message::Message;
|
||||||
pub ChannelType,
|
|
||||||
pub OrderedDocument,
|
|
||||||
);
|
|
||||||
|
|
||||||
pub struct Message (
|
|
||||||
pub Ulid,
|
|
||||||
pub OrderedDocument,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<'r> FromParam<'r> for Channel {
|
impl<'r> FromParam<'r> for Channel {
|
||||||
type Error = &'r RawStr;
|
type Error = &'r RawStr;
|
||||||
@@ -28,11 +15,7 @@ impl<'r> FromParam<'r> for Channel {
|
|||||||
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
||||||
|
|
||||||
if let Some(channel) = result {
|
if let Some(channel) = result {
|
||||||
Ok(Channel (
|
Ok(from_bson(bson::Bson::Document(channel)).expect("Failed to unwrap channel."))
|
||||||
Ulid::from_string(channel.get_str("_id").unwrap()).unwrap(),
|
|
||||||
ChannelType::try_from(channel.get_i32("type").unwrap() as usize).unwrap(),
|
|
||||||
channel
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(param)
|
Err(param)
|
||||||
}
|
}
|
||||||
@@ -47,10 +30,7 @@ impl<'r> FromParam<'r> for Message {
|
|||||||
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
||||||
|
|
||||||
if let Some(message) = result {
|
if let Some(message) = result {
|
||||||
Ok(Message (
|
Ok(from_bson(bson::Bson::Document(message)).expect("Failed to unwrap message."))
|
||||||
Ulid::from_string(message.get_str("_id").unwrap()).unwrap(),
|
|
||||||
message
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(param)
|
Err(param)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
use crate::guards::{ auth::User, channel::Channel };
|
use crate::database::{ user::User, channel::Channel };
|
||||||
use crate::database;
|
|
||||||
|
|
||||||
use rocket_contrib::json::{ Json, JsonValue };
|
use rocket_contrib::json::{ JsonValue };
|
||||||
use serde::{ Serialize, Deserialize };
|
|
||||||
use mongodb::options::FindOptions;
|
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
use bson::{ bson, doc };
|
use bson::{ doc };
|
||||||
use ulid::Ulid;
|
|
||||||
|
|
||||||
#[derive(Debug, TryFromPrimitive)]
|
#[derive(Debug, TryFromPrimitive)]
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
@@ -17,19 +13,21 @@ pub enum ChannelType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn has_permission(user: &User, target: &Channel) -> bool {
|
fn has_permission(user: &User, target: &Channel) -> bool {
|
||||||
let id = user.0.to_string();
|
match target.channel_type {
|
||||||
match target.1 {
|
0..=1 => {
|
||||||
ChannelType::DM |
|
if let Some(arr) = &target.recipients {
|
||||||
ChannelType::GROUP_DM => {
|
for item in arr {
|
||||||
for user in target.2.get_array("recipients").expect("DB[recipients]") {
|
if item == &user.id {
|
||||||
if user.as_str().expect("Expected string id.") == id {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
ChannelType::GUILD_CHANNEL =>
|
2 =>
|
||||||
|
false,
|
||||||
|
_ =>
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,12 +39,10 @@ pub fn channel(user: User, target: Channel) -> Option<JsonValue> {
|
|||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
let Channel ( id, channel_type, doc ) = target;
|
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
json!({
|
json!({
|
||||||
"id": id.to_string(),
|
"id": target.id,
|
||||||
"type": channel_type as u8
|
"type": target.channel_type
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::guards::auth::User;
|
use crate::database::{ self, user::User, channel::Channel };
|
||||||
use crate::database;
|
|
||||||
use crate::routes::channel;
|
use crate::routes::channel;
|
||||||
|
|
||||||
use rocket_contrib::json::{ Json, JsonValue };
|
use rocket_contrib::json::{ Json, JsonValue };
|
||||||
@@ -11,14 +10,12 @@ use ulid::Ulid;
|
|||||||
/// retrieve your user information
|
/// retrieve your user information
|
||||||
#[get("/@me")]
|
#[get("/@me")]
|
||||||
pub fn me(user: User) -> JsonValue {
|
pub fn me(user: User) -> JsonValue {
|
||||||
let User ( id, username, doc ) = user;
|
|
||||||
|
|
||||||
json!({
|
json!({
|
||||||
"id": id.to_string(),
|
"id": user.id,
|
||||||
"username": username,
|
"username": user.username,
|
||||||
"email": doc.email,
|
"email": user.email,
|
||||||
"verified": doc.email_verification.verified,
|
"verified": user.email_verification.verified,
|
||||||
"created_timestamp": id.datetime().timestamp(),
|
"created_timestamp": Ulid::from_string(&user.id).unwrap().datetime().timestamp(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +43,7 @@ pub fn lookup(_user: User, query: Json<Query>) -> JsonValue {
|
|||||||
|
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
for user in users {
|
for user in users {
|
||||||
let u: database::user::User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user.");
|
let u: User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user.");
|
||||||
results.push(
|
results.push(
|
||||||
json!({
|
json!({
|
||||||
"id": u.id,
|
"id": u.id,
|
||||||
@@ -73,35 +70,21 @@ pub fn dms(user: User) -> JsonValue {
|
|||||||
"type": channel::ChannelType::GROUP_DM as i32
|
"type": channel::ChannelType::GROUP_DM as i32
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"recipients": user.0.to_string()
|
"recipients": user.id
|
||||||
},
|
},
|
||||||
None
|
None
|
||||||
).expect("Failed channel lookup");
|
).expect("Failed channel lookup");
|
||||||
|
|
||||||
let mut channels = Vec::new();
|
let mut channels = Vec::new();
|
||||||
for res in results {
|
for item in results {
|
||||||
let doc = res.expect("Failed to unwrap document");
|
let channel: Channel = from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap channel.");
|
||||||
|
|
||||||
let mut recipients = Vec::new();
|
|
||||||
for user in doc.get_array("recipients").expect("DB[recipients]") {
|
|
||||||
recipients.push(
|
|
||||||
user.as_str()
|
|
||||||
.expect("Should be a string.")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let active =
|
|
||||||
match doc.get_bool("active") {
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(_) => true
|
|
||||||
};
|
|
||||||
|
|
||||||
channels.push(
|
channels.push(
|
||||||
json!({
|
json!({
|
||||||
"id": doc.get_str("_id").expect("DB[id]"),
|
"id": channel.id,
|
||||||
"type": doc.get_i32("type").expect("DB[type]"),
|
"type": channel.channel_type,
|
||||||
"recipients": recipients,
|
"recipients": channel.recipients,
|
||||||
"active": active
|
"active": channel.active.unwrap()
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -115,12 +98,12 @@ pub fn dm(user: User, target: User) -> JsonValue {
|
|||||||
let col = database::get_collection("channels");
|
let col = database::get_collection("channels");
|
||||||
|
|
||||||
match col.find_one(
|
match col.find_one(
|
||||||
doc! { "type": channel::ChannelType::DM as i32, "recipients": [ user.0.to_string(), target.0.to_string() ] },
|
doc! { "type": channel::ChannelType::DM as i32, "recipients": [ user.id.clone(), target.id.clone() ] },
|
||||||
None
|
None
|
||||||
).expect("Failed channel lookup") {
|
).expect("Failed channel lookup") {
|
||||||
Some(channel) =>
|
Some(channel) =>
|
||||||
json!({
|
json!({
|
||||||
"id": channel.get_str("_id").expect("DB[id]")
|
"id": channel.get_str("_id").unwrap()
|
||||||
}),
|
}),
|
||||||
None => {
|
None => {
|
||||||
let id = Ulid::new();
|
let id = Ulid::new();
|
||||||
@@ -129,7 +112,7 @@ pub fn dm(user: User, target: User) -> JsonValue {
|
|||||||
doc! {
|
doc! {
|
||||||
"_id": id.to_string(),
|
"_id": id.to_string(),
|
||||||
"type": channel::ChannelType::DM as i32,
|
"type": channel::ChannelType::DM as i32,
|
||||||
"recipients": [ user.0.to_string(), target.0.to_string() ],
|
"recipients": [ user.id, target.id ],
|
||||||
"active": false
|
"active": false
|
||||||
},
|
},
|
||||||
None
|
None
|
||||||
@@ -153,15 +136,13 @@ enum Relationship {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_relationship(a: &User, b: &User) -> Relationship {
|
fn get_relationship(a: &User, b: &User) -> Relationship {
|
||||||
if a.0.to_string() == b.0.to_string() {
|
if a.id == b.id {
|
||||||
return Relationship::SELF
|
return Relationship::SELF
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(arr) = &b.2.relations {
|
if let Some(arr) = &b.relations {
|
||||||
let id = a.0.to_string();
|
|
||||||
|
|
||||||
for entry in arr {
|
for entry in arr {
|
||||||
if entry.id == id {
|
if entry.id == a.id {
|
||||||
match entry.status {
|
match entry.status {
|
||||||
0 => {
|
0 => {
|
||||||
return Relationship::FRIEND
|
return Relationship::FRIEND
|
||||||
@@ -190,7 +171,7 @@ fn get_relationship(a: &User, b: &User) -> Relationship {
|
|||||||
#[get("/@me/friend")]
|
#[get("/@me/friend")]
|
||||||
pub fn get_friends(user: User) -> JsonValue {
|
pub fn get_friends(user: User) -> JsonValue {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
if let Some(arr) = user.2.relations {
|
if let Some(arr) = user.relations {
|
||||||
for item in arr {
|
for item in arr {
|
||||||
results.push(
|
results.push(
|
||||||
json!({
|
json!({
|
||||||
@@ -210,7 +191,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue {
|
|||||||
let relationship = get_relationship(&user, &target);
|
let relationship = get_relationship(&user, &target);
|
||||||
|
|
||||||
json!({
|
json!({
|
||||||
"id": target.0.to_string(),
|
"id": target.id,
|
||||||
"status": relationship as u8
|
"status": relationship as u8
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -219,10 +200,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue {
|
|||||||
#[put("/<target>/friend")]
|
#[put("/<target>/friend")]
|
||||||
pub fn add_friend(user: User, target: User) -> JsonValue {
|
pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||||
let col = database::get_collection("users");
|
let col = database::get_collection("users");
|
||||||
|
|
||||||
let relationship = get_relationship(&user, &target);
|
let relationship = get_relationship(&user, &target);
|
||||||
let User ( id, _, _ ) = user;
|
|
||||||
let User ( tid, _, _ ) = target;
|
|
||||||
|
|
||||||
match relationship {
|
match relationship {
|
||||||
Relationship::FRIEND =>
|
Relationship::FRIEND =>
|
||||||
@@ -238,8 +216,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
|||||||
Relationship::INCOMING => {
|
Relationship::INCOMING => {
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": id.to_string(),
|
"_id": user.id.clone(),
|
||||||
"relations.id": tid.to_string()
|
"relations.id": target.id.clone()
|
||||||
},
|
},
|
||||||
doc! {
|
doc! {
|
||||||
"$set": {
|
"$set": {
|
||||||
@@ -251,8 +229,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
|||||||
|
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": tid.to_string(),
|
"_id": target.id,
|
||||||
"relations.id": id.to_string()
|
"relations.id": user.id
|
||||||
},
|
},
|
||||||
doc! {
|
doc! {
|
||||||
"$set": {
|
"$set": {
|
||||||
@@ -279,12 +257,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
|||||||
Relationship::NONE => {
|
Relationship::NONE => {
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": id.to_string()
|
"_id": user.id.clone()
|
||||||
},
|
},
|
||||||
doc! {
|
doc! {
|
||||||
"$push": {
|
"$push": {
|
||||||
"relations": {
|
"relations": {
|
||||||
"id": tid.to_string(),
|
"id": target.id.clone(),
|
||||||
"status": Relationship::OUTGOING as i32
|
"status": Relationship::OUTGOING as i32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,12 +272,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
|||||||
|
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": tid.to_string()
|
"_id": target.id
|
||||||
},
|
},
|
||||||
doc! {
|
doc! {
|
||||||
"$push": {
|
"$push": {
|
||||||
"relations": {
|
"relations": {
|
||||||
"id": id.to_string(),
|
"id": user.id,
|
||||||
"status": Relationship::INCOMING as i32
|
"status": Relationship::INCOMING as i32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,10 +301,7 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
|||||||
#[delete("/<target>/friend")]
|
#[delete("/<target>/friend")]
|
||||||
pub fn remove_friend(user: User, target: User) -> JsonValue {
|
pub fn remove_friend(user: User, target: User) -> JsonValue {
|
||||||
let col = database::get_collection("users");
|
let col = database::get_collection("users");
|
||||||
|
|
||||||
let relationship = get_relationship(&user, &target);
|
let relationship = get_relationship(&user, &target);
|
||||||
let User ( id, _, _ ) = user;
|
|
||||||
let User ( tid, _, _ ) = target;
|
|
||||||
|
|
||||||
match relationship {
|
match relationship {
|
||||||
Relationship::FRIEND |
|
Relationship::FRIEND |
|
||||||
@@ -334,12 +309,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue {
|
|||||||
Relationship::INCOMING => {
|
Relationship::INCOMING => {
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": id.to_string()
|
"_id": user.id.clone()
|
||||||
},
|
},
|
||||||
doc! {
|
doc! {
|
||||||
"$pull": {
|
"$pull": {
|
||||||
"relations": {
|
"relations": {
|
||||||
"id": tid.to_string()
|
"id": target.id.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -348,12 +323,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue {
|
|||||||
|
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": tid.to_string()
|
"_id": target.id
|
||||||
},
|
},
|
||||||
doc! {
|
doc! {
|
||||||
"$pull": {
|
"$pull": {
|
||||||
"relations": {
|
"relations": {
|
||||||
"id": id.to_string()
|
"id": user.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user