mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 05:26:59 +00:00
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)
|
||||
}
|
||||
|
||||
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 bson::{ bson, doc, from_bson };
|
||||
use ulid::Ulid;
|
||||
|
||||
use crate::database;
|
||||
|
||||
pub struct User(
|
||||
pub Ulid,
|
||||
pub String,
|
||||
pub database::user::User,
|
||||
);
|
||||
use database::user::User;
|
||||
|
||||
#[derive(Debug)]
|
||||
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();
|
||||
|
||||
if let Some(user) = result {
|
||||
Outcome::Success(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.")
|
||||
))
|
||||
Outcome::Success(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
|
||||
} else {
|
||||
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();
|
||||
|
||||
if let Some(user) = result {
|
||||
Ok(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.")
|
||||
))
|
||||
Ok(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
|
||||
} else {
|
||||
Err(param)
|
||||
}
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
use rocket::Outcome;
|
||||
use rocket::http::{ Status, RawStr };
|
||||
use rocket::request::{ self, Request, FromRequest, FromParam };
|
||||
|
||||
use bson::{ bson, doc, ordered::OrderedDocument };
|
||||
use std::convert::TryFrom;
|
||||
use ulid::Ulid;
|
||||
use rocket::http::{ RawStr };
|
||||
use rocket::request::{ FromParam };
|
||||
use bson::{ bson, doc, from_bson };
|
||||
|
||||
use crate::database;
|
||||
use crate::routes::channel::ChannelType;
|
||||
|
||||
pub struct Channel (
|
||||
pub Ulid,
|
||||
pub ChannelType,
|
||||
pub OrderedDocument,
|
||||
);
|
||||
|
||||
pub struct Message (
|
||||
pub Ulid,
|
||||
pub OrderedDocument,
|
||||
);
|
||||
use database::channel::Channel;
|
||||
use database::message::Message;
|
||||
|
||||
impl<'r> FromParam<'r> for Channel {
|
||||
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();
|
||||
|
||||
if let Some(channel) = result {
|
||||
Ok(Channel (
|
||||
Ulid::from_string(channel.get_str("_id").unwrap()).unwrap(),
|
||||
ChannelType::try_from(channel.get_i32("type").unwrap() as usize).unwrap(),
|
||||
channel
|
||||
))
|
||||
Ok(from_bson(bson::Bson::Document(channel)).expect("Failed to unwrap channel."))
|
||||
} else {
|
||||
Err(param)
|
||||
}
|
||||
@@ -47,10 +30,7 @@ impl<'r> FromParam<'r> for Message {
|
||||
let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
|
||||
|
||||
if let Some(message) = result {
|
||||
Ok(Message (
|
||||
Ulid::from_string(message.get_str("_id").unwrap()).unwrap(),
|
||||
message
|
||||
))
|
||||
Ok(from_bson(bson::Bson::Document(message)).expect("Failed to unwrap message."))
|
||||
} else {
|
||||
Err(param)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
use crate::guards::{ auth::User, channel::Channel };
|
||||
use crate::database;
|
||||
use crate::database::{ user::User, channel::Channel };
|
||||
|
||||
use rocket_contrib::json::{ Json, JsonValue };
|
||||
use serde::{ Serialize, Deserialize };
|
||||
use mongodb::options::FindOptions;
|
||||
use rocket_contrib::json::{ JsonValue };
|
||||
use num_enum::TryFromPrimitive;
|
||||
use bson::{ bson, doc };
|
||||
use ulid::Ulid;
|
||||
use bson::{ doc };
|
||||
|
||||
#[derive(Debug, TryFromPrimitive)]
|
||||
#[repr(usize)]
|
||||
@@ -17,19 +13,21 @@ pub enum ChannelType {
|
||||
}
|
||||
|
||||
fn has_permission(user: &User, target: &Channel) -> bool {
|
||||
let id = user.0.to_string();
|
||||
match target.1 {
|
||||
ChannelType::DM |
|
||||
ChannelType::GROUP_DM => {
|
||||
for user in target.2.get_array("recipients").expect("DB[recipients]") {
|
||||
if user.as_str().expect("Expected string id.") == id {
|
||||
return true;
|
||||
match target.channel_type {
|
||||
0..=1 => {
|
||||
if let Some(arr) = &target.recipients {
|
||||
for item in arr {
|
||||
if item == &user.id {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
},
|
||||
ChannelType::GUILD_CHANNEL =>
|
||||
2 =>
|
||||
false,
|
||||
_ =>
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -41,12 +39,10 @@ pub fn channel(user: User, target: Channel) -> Option<JsonValue> {
|
||||
return None
|
||||
}
|
||||
|
||||
let Channel ( id, channel_type, doc ) = target;
|
||||
|
||||
Some(
|
||||
json!({
|
||||
"id": id.to_string(),
|
||||
"type": channel_type as u8
|
||||
"id": target.id,
|
||||
"type": target.channel_type
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::guards::auth::User;
|
||||
use crate::database;
|
||||
use crate::database::{ self, user::User, channel::Channel };
|
||||
use crate::routes::channel;
|
||||
|
||||
use rocket_contrib::json::{ Json, JsonValue };
|
||||
@@ -11,14 +10,12 @@ use ulid::Ulid;
|
||||
/// retrieve your user information
|
||||
#[get("/@me")]
|
||||
pub fn me(user: User) -> JsonValue {
|
||||
let User ( id, username, doc ) = user;
|
||||
|
||||
json!({
|
||||
"id": id.to_string(),
|
||||
"username": username,
|
||||
"email": doc.email,
|
||||
"verified": doc.email_verification.verified,
|
||||
"created_timestamp": id.datetime().timestamp(),
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"email": user.email,
|
||||
"verified": user.email_verification.verified,
|
||||
"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();
|
||||
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(
|
||||
json!({
|
||||
"id": u.id,
|
||||
@@ -73,35 +70,21 @@ pub fn dms(user: User) -> JsonValue {
|
||||
"type": channel::ChannelType::GROUP_DM as i32
|
||||
}
|
||||
],
|
||||
"recipients": user.0.to_string()
|
||||
"recipients": user.id
|
||||
},
|
||||
None
|
||||
).expect("Failed channel lookup");
|
||||
|
||||
let mut channels = Vec::new();
|
||||
for res in results {
|
||||
let doc = res.expect("Failed to unwrap document");
|
||||
|
||||
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
|
||||
};
|
||||
for item in results {
|
||||
let channel: Channel = from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap channel.");
|
||||
|
||||
channels.push(
|
||||
json!({
|
||||
"id": doc.get_str("_id").expect("DB[id]"),
|
||||
"type": doc.get_i32("type").expect("DB[type]"),
|
||||
"recipients": recipients,
|
||||
"active": active
|
||||
"id": channel.id,
|
||||
"type": channel.channel_type,
|
||||
"recipients": channel.recipients,
|
||||
"active": channel.active.unwrap()
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -115,12 +98,12 @@ pub fn dm(user: User, target: User) -> JsonValue {
|
||||
let col = database::get_collection("channels");
|
||||
|
||||
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
|
||||
).expect("Failed channel lookup") {
|
||||
Some(channel) =>
|
||||
json!({
|
||||
"id": channel.get_str("_id").expect("DB[id]")
|
||||
"id": channel.get_str("_id").unwrap()
|
||||
}),
|
||||
None => {
|
||||
let id = Ulid::new();
|
||||
@@ -129,7 +112,7 @@ pub fn dm(user: User, target: User) -> JsonValue {
|
||||
doc! {
|
||||
"_id": id.to_string(),
|
||||
"type": channel::ChannelType::DM as i32,
|
||||
"recipients": [ user.0.to_string(), target.0.to_string() ],
|
||||
"recipients": [ user.id, target.id ],
|
||||
"active": false
|
||||
},
|
||||
None
|
||||
@@ -153,15 +136,13 @@ enum 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
|
||||
}
|
||||
|
||||
if let Some(arr) = &b.2.relations {
|
||||
let id = a.0.to_string();
|
||||
|
||||
if let Some(arr) = &b.relations {
|
||||
for entry in arr {
|
||||
if entry.id == id {
|
||||
if entry.id == a.id {
|
||||
match entry.status {
|
||||
0 => {
|
||||
return Relationship::FRIEND
|
||||
@@ -190,7 +171,7 @@ fn get_relationship(a: &User, b: &User) -> Relationship {
|
||||
#[get("/@me/friend")]
|
||||
pub fn get_friends(user: User) -> JsonValue {
|
||||
let mut results = Vec::new();
|
||||
if let Some(arr) = user.2.relations {
|
||||
if let Some(arr) = user.relations {
|
||||
for item in arr {
|
||||
results.push(
|
||||
json!({
|
||||
@@ -210,7 +191,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue {
|
||||
let relationship = get_relationship(&user, &target);
|
||||
|
||||
json!({
|
||||
"id": target.0.to_string(),
|
||||
"id": target.id,
|
||||
"status": relationship as u8
|
||||
})
|
||||
}
|
||||
@@ -219,10 +200,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue {
|
||||
#[put("/<target>/friend")]
|
||||
pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||
let col = database::get_collection("users");
|
||||
|
||||
let relationship = get_relationship(&user, &target);
|
||||
let User ( id, _, _ ) = user;
|
||||
let User ( tid, _, _ ) = target;
|
||||
|
||||
match relationship {
|
||||
Relationship::FRIEND =>
|
||||
@@ -238,8 +216,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||
Relationship::INCOMING => {
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": id.to_string(),
|
||||
"relations.id": tid.to_string()
|
||||
"_id": user.id.clone(),
|
||||
"relations.id": target.id.clone()
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
@@ -251,8 +229,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": tid.to_string(),
|
||||
"relations.id": id.to_string()
|
||||
"_id": target.id,
|
||||
"relations.id": user.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
@@ -279,12 +257,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||
Relationship::NONE => {
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": id.to_string()
|
||||
"_id": user.id.clone()
|
||||
},
|
||||
doc! {
|
||||
"$push": {
|
||||
"relations": {
|
||||
"id": tid.to_string(),
|
||||
"id": target.id.clone(),
|
||||
"status": Relationship::OUTGOING as i32
|
||||
}
|
||||
}
|
||||
@@ -294,12 +272,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": tid.to_string()
|
||||
"_id": target.id
|
||||
},
|
||||
doc! {
|
||||
"$push": {
|
||||
"relations": {
|
||||
"id": id.to_string(),
|
||||
"id": user.id,
|
||||
"status": Relationship::INCOMING as i32
|
||||
}
|
||||
}
|
||||
@@ -323,10 +301,7 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
|
||||
#[delete("/<target>/friend")]
|
||||
pub fn remove_friend(user: User, target: User) -> JsonValue {
|
||||
let col = database::get_collection("users");
|
||||
|
||||
let relationship = get_relationship(&user, &target);
|
||||
let User ( id, _, _ ) = user;
|
||||
let User ( tid, _, _ ) = target;
|
||||
|
||||
match relationship {
|
||||
Relationship::FRIEND |
|
||||
@@ -334,12 +309,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue {
|
||||
Relationship::INCOMING => {
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": id.to_string()
|
||||
"_id": user.id.clone()
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"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(
|
||||
doc! {
|
||||
"_id": tid.to_string()
|
||||
"_id": target.id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"relations": {
|
||||
"id": id.to_string()
|
||||
"id": user.id
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user