Skip to content
Snippets Groups Projects
Verified Commit 20c82dde authored by insert's avatar insert
Browse files

Add all friend routes.

parent 92f20d7b
Branches
Tags
No related merge requests found
use rocket::Outcome;
use rocket::http::Status;
use rocket::request::{self, Request, FromRequest};
use rocket::http::{ Status, RawStr };
use rocket::request::{ self, Request, FromRequest, FromParam };
use bson::{ bson, doc, ordered::OrderedDocument };
use ulid::Ulid;
......@@ -45,4 +45,23 @@ impl<'a, 'r> FromRequest<'a, 'r> for User {
_ => Outcome::Failure((Status::BadRequest, AuthError::BadCount)),
}
}
}
\ No newline at end of file
}
impl<'r> FromParam<'r> for User {
type Error = &'r RawStr;
fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
let col = database::get_db().collection("users");
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(),
user
))
} else {
Err(param)
}
}
}
use mongodb::{ Client, Database };
use mongodb::{ Client, Collection, Database };
use std::env;
use once_cell::sync::OnceCell;
......@@ -19,3 +19,7 @@ pub fn get_connection() -> &'static Client {
pub fn get_db() -> Database {
get_connection().database("revolt")
}
pub fn get_collection(collection: &str) -> Collection {
get_db().collection(collection)
}
......@@ -33,7 +33,7 @@ pub struct Create {
/// (3) add user and send email verification
#[post("/create", data = "<info>")]
pub fn create(info: Json<Create>) -> JsonValue {
let col = database::get_db().collection("users");
let col = database::get_collection("users");
if info.username.len() < 2 || info.username.len() > 32 {
return json!({
......@@ -108,7 +108,7 @@ pub fn create(info: Json<Create>) -> JsonValue {
/// (3) set account as verified
#[get("/verify/<code>")]
pub fn verify_email(code: String) -> JsonValue {
let col = database::get_db().collection("users");
let col = database::get_collection("users");
if let Some(u) =
col.find_one(doc! { "email_verification.code": code.clone() }, None).expect("Failed user lookup") {
......@@ -166,8 +166,8 @@ pub struct Resend {
/// (2) check for rate limit
/// (3) resend the email
#[post("/resend", data = "<info>")]
pub fn resend_email(info: Json<Resend>) -> JsonValue {
let col = database::get_db().collection("users");
pub fn resend_email(info: Json<Resend>) -> JsonValue {
let col = database::get_collection("users");
if let Some(u) =
col.find_one(doc! { "email_verification.target": info.email.clone() }, None).expect("Failed user lookup") {
......@@ -239,7 +239,7 @@ pub struct Login {
/// (3) return access token
#[post("/login", data = "<info>")]
pub fn login(info: Json<Login>) -> JsonValue {
let col = database::get_db().collection("users");
let col = database::get_collection("users");
if let Some(u) =
col.find_one(doc! { "email": info.email.clone() }, None).expect("Failed user lookup") {
......
......@@ -6,5 +6,5 @@ mod user;
pub fn mount(rocket: Rocket) -> Rocket {
rocket
.mount("/api/account", routes![ account::create, account::verify_email, account::resend_email, account::login ])
.mount("/api/users", routes![ user::me, user::dms, user::lookup ])
.mount("/api/users", routes![ user::me, user::user, user::lookup, user::dms, user::dm, user::get_friends, user::get_friend, user::add_friend, user::remove_friend ])
}
......@@ -22,8 +22,8 @@ pub fn me(user: User) -> JsonValue {
}
/// retrieve another user's information
#[get("/<id>")]
pub fn user(user: User, id: String) -> JsonValue {
#[get("/<target>")]
pub fn user(user: User, target: User) -> JsonValue {
json!([])
}
......@@ -36,7 +36,7 @@ pub struct Query {
/// currently only supports exact username searches
#[post("/lookup", data = "<query>")]
pub fn lookup(_user: User, query: Json<Query>) -> JsonValue {
let col = database::get_db().collection("users");
let col = database::get_collection("users");
let users = col.find(
doc! { "username": query.username.clone() },
......@@ -64,31 +64,245 @@ pub fn dms(user: User) -> JsonValue {
}
/// open a DM with a user
#[get("/<id>/dm")]
pub fn dm(user: User, id: String) -> JsonValue {
#[get("/<target>/dm")]
pub fn dm(user: User, target: User) -> JsonValue {
json!([])
}
enum Relationship {
FRIEND = 0,
OUTGOING = 1,
INCOMING = 2,
BLOCKED = 3,
BLOCKED_OTHER = 4,
NONE = 5,
SELF = 6,
}
fn get_relationship(a: &User, b: &User) -> Relationship {
if a.0.to_string() == b.0.to_string() {
return Relationship::SELF
}
if let Ok(arr) = b.2.get_array("relations") {
let id = a.0.to_string();
for entry in arr {
let relation = entry.as_document().expect("Expected document in relations array.");
if relation.get_str("id").expect("DB[id]") == id {
match relation.get_i32("status").expect("DB[status]") {
0 => {
return Relationship::FRIEND
},
1 => {
return Relationship::INCOMING
},
2 => {
return Relationship::OUTGOING
},
3 => {
return Relationship::BLOCKED_OTHER
}
_ => {
return Relationship::NONE
}
}
}
}
}
Relationship::NONE
}
/// retrieve all of your friends
#[get("/@me/friend")]
pub fn get_friends(user: User) -> JsonValue {
json!([])
let mut results = Vec::new();
if let Ok(arr) = user.2.get_array("relations") {
for item in arr {
let doc = item.as_document().expect("Expected document in relations array.");
results.push(
json!({
"id": doc.get_str("id").expect("DB[id]"),
"status": doc.get_i32("status").expect("DB[status]")
})
)
}
}
json!(results)
}
/// retrieve friend status with user
#[get("/<id>/friend")]
pub fn get_friend(user: User, id: String) -> JsonValue {
json!([])
#[get("/<target>/friend")]
pub fn get_friend(user: User, target: User) -> JsonValue {
let relationship = get_relationship(&user, &target);
json!({
"id": target.0.to_string(),
"status": relationship as u8
})
}
/// create or accept a friend request
#[put("/<id>/friend")]
pub fn add_friend(user: User, id: String) -> JsonValue {
json!([])
#[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 =>
json!({
"success": false,
"error": "Already friends."
}),
Relationship::OUTGOING =>
json!({
"success": false,
"error": "Already sent a friend request."
}),
Relationship::INCOMING => {
col.update_one(
doc! {
"_id": id.to_string(),
"relations.id": tid.to_string()
},
doc! {
"$set": {
"relations.$.status": Relationship::FRIEND as i32
}
},
None
).expect("Failed update query.");
col.update_one(
doc! {
"_id": tid.to_string(),
"relations.id": id.to_string()
},
doc! {
"$set": {
"relations.$.status": Relationship::FRIEND as i32
}
},
None
).expect("Failed update query.");
json!({
"success": true
})
},
Relationship::BLOCKED =>
json!({
"success": false,
"error": "You have blocked this person."
}),
Relationship::BLOCKED_OTHER =>
json!({
"success": false,
"error": "You have been blocked by this person."
}),
Relationship::NONE => {
col.update_one(
doc! {
"_id": id.to_string()
},
doc! {
"$push": {
"relations": {
"id": tid.to_string(),
"status": Relationship::OUTGOING as i32
}
}
},
None
).expect("Failed update query.");
col.update_one(
doc! {
"_id": tid.to_string()
},
doc! {
"$push": {
"relations": {
"id": id.to_string(),
"status": Relationship::INCOMING as i32
}
}
},
None
).expect("Failed update query.");
json!({
"success": true
})
},
Relationship::SELF =>
json!({
"success": false,
"error": "Cannot add yourself as a friend."
})
}
}
/// remove a friend or deny a request
#[delete("/<id>/friend")]
pub fn remove_friend(user: User, id: String) -> JsonValue {
json!([])
#[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 |
Relationship::OUTGOING |
Relationship::INCOMING => {
col.update_one(
doc! {
"_id": id.to_string()
},
doc! {
"$pull": {
"relations": {
"id": tid.to_string()
}
}
},
None
).expect("Failed update query.");
col.update_one(
doc! {
"_id": tid.to_string()
},
doc! {
"$pull": {
"relations": {
"id": id.to_string()
}
}
},
None
).expect("Failed update query.");
json!({
"success": true
})
},
Relationship::BLOCKED |
Relationship::BLOCKED_OTHER |
Relationship::NONE |
Relationship::SELF =>
json!({
"success": false,
"error": "This has no effect."
})
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment