diff --git a/Cargo.lock b/Cargo.lock index 4ebb944621347818112c539781d2f7c88f9ba160..74e717033bf9feabad07745c1cf7069b27ce0bd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1564,6 +1564,7 @@ dependencies = [ "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket_cors 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1631,6 +1632,21 @@ dependencies = [ "serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rocket_cors" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase_serde 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rocket_http" version = "0.4.2" @@ -2313,6 +2329,15 @@ dependencies = [ "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicase_serde" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -2819,6 +2844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "42c1e9deb3ef4fa430d307bfccd4231434b707ca1328fae339c43ad1201cc6f7" "checksum rocket_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "79aa1366f9b2eccddc05971e17c5de7bb75a5431eb12c2b5c66545fd348647f4" "checksum rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e0fa5c1392135adc0f96a02ba150ac4c765e27c58dbfd32aa40678e948f6e56f" +"checksum rocket_cors 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "270a960cba5a0b7928ad74268db7773ce932da6b550478383cefebe9f46c4e13" "checksum rocket_http 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1391457ee4e80b40d4b57fa5765c0f2836b20d73bcbee4e3f35d93cf3b80817" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2889,6 +2915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ulid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66239d1f7f19c9af37383f4a28e112727f1a77f6b13dca86faf75c40038e6dd3" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +"checksum unicase_serde 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef53697679d874d69f3160af80bc28de12730a985d57bdf2b47456ccb8b11f1" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" diff --git a/Cargo.toml b/Cargo.toml index 0e7751732a6f246fac45b6ef901dd8a7f31917cf..f9c50dd2b2e07907170fe72af942f9565196f1d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,4 @@ num_enum = "0.4.2" ws = "0.9.1" hashbrown = "0.7.0" serde_json = "1.0.47" +rocket_cors = "0.5.1" diff --git a/src/main.rs b/src/main.rs index 3af5ff43c00464ae1d3ffb84d5a9285aca9b1865..1a27d934733632ea6ea0de442108bf25338c92de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ pub mod email; use dotenv; use std::thread; +use rocket_cors::AllowedOrigins; fn main() { dotenv::dotenv().ok(); @@ -19,5 +20,12 @@ fn main() { websocket::launch_server(); }); - routes::mount(rocket::ignite()).launch(); + let cors = rocket_cors::CorsOptions { + allowed_origins: AllowedOrigins::All, + ..Default::default() + }.to_cors().unwrap(); + + routes::mount(rocket::ignite()) + .attach(cors) + .launch(); } diff --git a/src/routes/account.rs b/src/routes/account.rs index 7d94e597c20dca35483da02d5402fe518d5c2399..41d4a1ab9a9193ad04d8fbb1e61a59943a2c5a2f 100644 --- a/src/routes/account.rs +++ b/src/routes/account.rs @@ -267,7 +267,8 @@ pub fn login(info: Json<Login>) -> JsonValue { json!({ "success": true, - "access_token": token + "access_token": token, + "id": user.id }) }, false => json!({ @@ -282,3 +283,28 @@ pub fn login(info: Json<Login>) -> JsonValue { }) } } + + +#[derive(Serialize, Deserialize)] +pub struct Token { + token: String, +} + +/// login to a Revolt account via token +#[post("/token", data = "<info>")] +pub fn token(info: Json<Token>) -> JsonValue { + let col = database::get_collection("users"); + + if let Some(u) = + col.find_one(doc! { "access_token": info.token.clone() }, None).expect("Failed user lookup") { + json!({ + "success": true, + "id": u.get_str("_id").unwrap(), + }) + } else { + json!({ + "success": false, + "error": "Invalid token!", + }) + } +} diff --git a/src/routes/channel.rs b/src/routes/channel.rs index 7c0b5d9ffea2b9990d448e36176bef08eea2fb35..134e82e5aa7824d3ded7e44b1b82d29664abe432 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -53,7 +53,8 @@ pub fn channel(user: User, target: Channel) -> Option<JsonValue> { Some( json!({ "id": target.id, - "type": target.channel_type + "type": target.channel_type, + "recipients": get_recipients(&target), } )) } @@ -158,10 +159,12 @@ pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> get_recipients(&target), json!({ "type": "message", - "id": id.clone(), - "channel": target.id, - "author": user.id, - "content": message.content.clone(), + "data": { + "id": id.clone(), + "channel": target.id, + "author": user.id, + "content": message.content.clone(), + }, }).to_string() ); @@ -178,6 +181,23 @@ pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> }) } +/// get a message +#[get("/<target>/messages/<message>")] +pub fn get_message(user: User, target: Channel, message: Message) -> Option<JsonValue> { + if !has_permission(&user, &target) { + return None + } + + Some( + json!({ + "id": message.id, + "author": message.author, + "content": message.content, + "edited": if let Some(t) = message.edited { Some(t.timestamp()) } else { None } + }) + ) +} + #[derive(Serialize, Deserialize)] pub struct EditMessage { content: String, @@ -215,10 +235,12 @@ pub fn edit_message(user: User, target: Channel, message: Message, edit: Json<Se get_recipients(&target), json!({ "type": "message_update", - "id": message.id, - "channel": target.id, - "content": message.content.clone(), - "edited": edited.timestamp() + "data": { + "id": message.id, + "channel": target.id, + "content": edit.content.clone(), + "edited": edited.timestamp() + }, }).to_string() ); @@ -261,8 +283,10 @@ pub fn delete_message(user: User, target: Channel, message: Message) -> Option<J get_recipients(&target), json!({ "type": "message_delete", - "id": message.id, - "channel": target.id + "data": { + "id": message.id, + "channel": target.id + }, }).to_string() ); diff --git a/src/routes/mod.rs b/src/routes/mod.rs index ef4de3380303e526baaffdb6908e4d297fb93b2c..d1ec62a54d8f64dc214ee01915bfbc9cd884bacd 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -6,7 +6,7 @@ pub mod channel; pub fn mount(rocket: Rocket) -> Rocket { rocket - .mount("/api/account", routes![ account::create, account::verify_email, account::resend_email, account::login ]) + .mount("/api/account", routes![ account::create, account::verify_email, account::resend_email, account::login, account::token ]) .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 ]) .mount("/api/channels", routes![ channel::channel, channel::delete, channel::messages, channel::send_message, channel::edit_message, channel::delete_message ]) } diff --git a/src/routes/user.rs b/src/routes/user.rs index a1b6259004bbb531abce057a6c3f62feca2586d6..43d8890f16825667d005ada961b86bc25b52323d 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -15,14 +15,17 @@ pub fn me(user: User) -> JsonValue { "username": user.username, "email": user.email, "verified": user.email_verification.verified, - "created_timestamp": Ulid::from_string(&user.id).unwrap().datetime().timestamp(), }) } /// retrieve another user's information -#[get("/<_target>")] -pub fn user(_user: User, _target: User) -> JsonValue { - json!([]) +#[get("/<target>")] +pub fn user(user: User, target: User) -> JsonValue { + json!({ + "id": target.id, + "username": target.username, + "relationship": get_relationship(&user, &target) as u8 + }) } #[derive(Serialize, Deserialize)] @@ -33,7 +36,7 @@ pub struct Query { /// lookup a user on Revolt /// currently only supports exact username searches #[post("/lookup", data = "<query>")] -pub fn lookup(_user: User, query: Json<Query>) -> JsonValue { +pub fn lookup(user: User, query: Json<Query>) -> JsonValue { let col = database::get_collection("users"); let users = col.find( @@ -42,12 +45,13 @@ pub fn lookup(_user: User, query: Json<Query>) -> JsonValue { ).expect("Failed user lookup"); let mut results = Vec::new(); - for user in users { - let u: User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user."); + for item in users { + let u: User = from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap user."); results.push( json!({ "id": u.id, - "username": u.username + "username": u.username, + "relationship": get_relationship(&user, &u) as u8 }) ); } @@ -98,11 +102,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.id.clone(), target.id.clone() ] }, + doc! { "type": channel::ChannelType::DM as i32, "recipients": { "$all": [ user.id.clone(), target.id.clone() ] } }, None ).expect("Failed channel lookup") { Some(channel) => json!({ + "success": true, "id": channel.get_str("_id").unwrap() }), None => { @@ -244,7 +249,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue { ).expect("Failed update query."); json!({ - "success": true + "success": true, + "status": Relationship::FRIEND as u8, }) }, Relationship::BLOCKED => @@ -289,7 +295,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue { ).expect("Failed update query."); json!({ - "success": true + "success": true, + "status": Relationship::OUTGOING as u8, }) }, Relationship::SELF => diff --git a/src/websocket/mod.rs b/src/websocket/mod.rs index 5204050ae406c89a12e2506ae6cd0d1cfab95309..d0fbdf51bc04729963a15a0f8737d4a5b369a6b9 100644 --- a/src/websocket/mod.rs +++ b/src/websocket/mod.rs @@ -40,6 +40,8 @@ impl Handler for Server { if let Some(_) = self.id { self.out.send( json!({ + "type": "authenticate", + "success": false, "error": "Already authenticated!" }) .to_string() @@ -71,6 +73,7 @@ impl Handler for Server { self.id = Some(id.to_string()); self.out.send( json!({ + "type": "authenticate", "success": true }) .to_string() @@ -79,6 +82,8 @@ impl Handler for Server { None => self.out.send( json!({ + "type": "authenticate", + "success": false, "error": "Invalid authentication token." }) .to_string() @@ -87,6 +92,8 @@ impl Handler for Server { } else { self.out.send( json!({ + "type": "authenticate", + "success": false, "error": "Missing authentication token." }) .to_string() @@ -141,7 +148,7 @@ pub fn launch_server() { } } - listen("127.0.0.1:3012", |out| { Server { out: out, id: None, internal: Ulid::new().to_string() } }).unwrap() + listen("192.168.0.10:9999", |out| { Server { out: out, id: None, internal: Ulid::new().to_string() } }).unwrap() } pub fn send_message(id: String, message: String) -> std::result::Result<(), ()> {