From 92f4eb8ec18f424e45d456ef4533027c4d6a2759 Mon Sep 17 00:00:00 2001 From: Erin Nova Date: Mon, 26 Jul 2021 14:09:10 -0400 Subject: [PATCH] aaaaaaa --- Cargo.lock | 334 ++++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 3 + src/auth.rs | 96 ++++++++------- src/chat.rs | 73 ++++++++---- src/main.rs | 28 ++++- src/user.rs | 22 ++-- 6 files changed, 452 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b12326..cba127f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + [[package]] name = "cfg-if" version = "0.1.10" @@ -320,6 +326,22 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding 2.1.0", +] + [[package]] name = "fs2" version = "0.4.3" @@ -365,6 +387,55 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "futures-core" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" + +[[package]] +name = "futures-macro" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" +dependencies = [ + "autocfg", + "proc-macro-hack", + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.74", +] + +[[package]] +name = "futures-sink" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" + +[[package]] +name = "futures-task" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" + +[[package]] +name = "futures-util" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" +dependencies = [ + "autocfg", + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -446,6 +517,17 @@ dependencies = [ "digest", ] +[[package]] +name = "http" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "httparse" version = "1.4.1" @@ -474,7 +556,7 @@ dependencies = [ "traitobject", "typeable", "unicase", - "url", + "url 1.7.2", ] [[package]] @@ -488,6 +570,17 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.7.0" @@ -576,6 +669,28 @@ version = "0.2.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +[[package]] +name = "lila-chat" +version = "0.6.0" +dependencies = [ + "bincode", + "chrono", + "env_logger", + "futures-util", + "log 0.4.14", + "once_cell", + "random-string", + "rocket", + "rocket_contrib", + "serde", + "serde_json", + "sha1", + "sled", + "tokio", + "tokio-tungstenite", + "uuid", +] + [[package]] name = "lock_api" version = "0.4.4" @@ -646,12 +761,25 @@ dependencies = [ "kernel32-sys", "libc", "log 0.4.14", - "miow", + "miow 0.2.2", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +dependencies = [ + "libc", + "log 0.4.14", + "miow 0.3.7", + "ntapi", + "winapi 0.3.9", +] + [[package]] name = "mio-extras" version = "2.0.6" @@ -660,7 +788,7 @@ checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", "log 0.4.14", - "mio", + "mio 0.6.23", "slab", ] @@ -676,6 +804,15 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "net2" version = "0.2.37" @@ -699,12 +836,21 @@ dependencies = [ "fsevent-sys", "inotify", "libc", - "mio", + "mio 0.6.23", "mio-extras", "walkdir", "winapi 0.3.9", ] +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -806,24 +952,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] -name = "pogchat" -version = "0.6.0" +name = "pin-project" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" dependencies = [ - "bincode", - "chrono", - "env_logger", - "log 0.4.14", - "once_cell", - "random-string", - "rocket", - "rocket_contrib", - "serde", - "serde_json", - "sha1", - "sled", - "uuid", + "pin-project-internal", ] +[[package]] +name = "pin-project-internal" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.74", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "polyval" version = "0.4.5" @@ -841,6 +1000,18 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -1076,6 +1247,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" +dependencies = [ + "block-buffer", + "cfg-if 1.0.0", + "cpufeatures", + "digest", + "opaque-debug", +] + [[package]] name = "sha1" version = "0.6.0" @@ -1095,6 +1279,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.3" @@ -1166,6 +1359,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.74", +] + [[package]] name = "time" version = "0.1.43" @@ -1191,6 +1404,50 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tokio" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio 0.7.13", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-macros" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +dependencies = [ + "proc-macro2 1.0.27", + "quote 1.0.9", + "syn 1.0.74", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" +dependencies = [ + "futures-util", + "log 0.4.14", + "pin-project", + "tokio", + "tungstenite", +] + [[package]] name = "toml" version = "0.4.10" @@ -1206,6 +1463,25 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +[[package]] +name = "tungstenite" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" +dependencies = [ + "base64 0.13.0", + "byteorder", + "bytes", + "http", + "httparse", + "log 0.4.14", + "rand", + "sha-1", + "thiserror", + "url 2.2.2", + "utf-8", +] + [[package]] name = "typeable" version = "0.1.2" @@ -1273,11 +1549,29 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna", + "idna 0.1.5", "matches", "percent-encoding 1.0.1", ] +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna 0.2.3", + "matches", + "percent-encoding 2.1.0", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "uuid" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index 5b8f25f..00e9d7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,3 +24,6 @@ once_cell = "1.8.0" random-string = "1.0" sled = "0.34.6" bincode = "1.3.3" +tokio = { version = "1.9.0", features = ["full"] } +futures-util = "0.3.16" +tokio-tungstenite = "0.15.0" diff --git a/src/auth.rs b/src/auth.rs index 2c81a8e..36efe4b 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,10 +1,10 @@ extern crate log; -use uuid::Uuid; use crate::file_io::*; -use rocket::http::{Cookie, Cookies}; use crate::user::*; -use rocket_contrib::json::{Json, JsonValue}; use random_string::generate; +use rocket::http::{Cookie, Cookies}; +use rocket_contrib::json::{Json, JsonValue}; +use uuid::Uuid; extern crate sha1; // Post request to register a user and pin @@ -12,14 +12,17 @@ extern crate sha1; pub fn register(data: Json) -> JsonValue { // check if the user exists if let Some(_user) = db_read_user(&data.name.to_lowercase()).ok().flatten() { - warn!("Cannot create user {}! User is already in system.", data.name); + warn!( + "Cannot create user {}! User is already in system.", + data.name + ); return json!({ "status": "fail", "reason": "user already exists", }); } else { let pin_hashed = sha1::Sha1::from(&data.pin).digest().to_string(); // hash the pin - + let mut new_user: User = User { name: data.name.to_string().to_lowercase(), pin_hashed, @@ -29,20 +32,21 @@ pub fn register(data: Json) -> JsonValue { id: Uuid::new_v4(), }; - if new_user.name == "admin".to_string() { // if name is admin, make them an admin + if new_user.name == "admin".to_string() { + // if name is admin, make them an admin new_user.role = UserType::Admin; } - db_add(&new_user); + db_add(&new_user); - info!( - "succesfully created user {} with pin hash {}", - new_user.name.to_string(), - new_user.pin_hashed - ); - return json!({ - "status": "ok", - "reason": format!("user {} registered", new_user.name.to_string().to_lowercase()), - }); + info!( + "succesfully created user {} with pin hash {}", + new_user.name.to_string(), + new_user.pin_hashed + ); + return json!({ + "status": "ok", + "reason": format!("user {} registered", new_user.name.to_string().to_lowercase()), + }); } } @@ -69,7 +73,7 @@ pub fn check_token(name: String, mut cookies: Cookies) -> JsonValue { "status": "fail", "reason": "could not read cookie", }); - }, + } Some(token) => token, }; @@ -94,11 +98,11 @@ pub fn check_token(name: String, mut cookies: Cookies) -> JsonValue { }); } } else { - warn!("user {} not found", name); - return json!({ - "status": "fail", - "reason": "user not found", - }); + warn!("user {} not found", name); + return json!({ + "status": "fail", + "reason": "user not found", + }); } } @@ -113,7 +117,7 @@ pub fn logout(info: Json, mut cookies: Cookies) -> JsonValue { "status": "fail", "reason": "could not read cookie", }); - }, + } Some(token) => token, }; if token.value() == "NULL" { @@ -153,14 +157,13 @@ pub fn login(data: Json, mut cookies: Cookies) -> JsonValue { if let Some(user) = db_read_user(&data.name.to_lowercase()).ok().flatten() { let hashed_pin_input = sha1::Sha1::from(&data.pin.to_string()).digest().to_string(); - if user.pin_hashed == hashed_pin_input { // check if pin hash matches + if user.pin_hashed == hashed_pin_input { + // check if pin hash matches info!("pin correct for user {}", &user.name); // Create token for user & set a cookie let token = create_token(user); - let cookie = Cookie::build("token", token) - .path("/") - .finish(); + let cookie = Cookie::build("token", token).path("/").finish(); cookies.remove_private(Cookie::named("token")); cookies.add_private(cookie); info!("set the token cookie"); @@ -203,7 +206,7 @@ pub fn change_info(input: Json, mut cookies: Cookies) -> JsonValue "status": "fail", "reason": "could not read cookie", }); - }, + } Some(token) => token, }; if token.value() == "NULL" { @@ -216,7 +219,8 @@ pub fn change_info(input: Json, mut cookies: Cookies) -> JsonValue // find the user if let Some(mut user) = db_read_user(&input.name.to_lowercase()).ok().flatten() { - if token.value() == user.session_token { // & if token matches: + if token.value() == user.session_token { + // & if token matches: match input.changed_event { ChangeEventType::Name => { // remove the user first @@ -229,7 +233,7 @@ pub fn change_info(input: Json, mut cookies: Cookies) -> JsonValue "status": "ok", "reason": format!("changed name of {} to {}", input.name, input.new_event), }); - }, + } ChangeEventType::Pin => { // change the pin let new_hashed_pin = sha1::Sha1::from(&input.new_event).digest().to_string(); @@ -240,7 +244,7 @@ pub fn change_info(input: Json, mut cookies: Cookies) -> JsonValue "status": "ok", "reason": "changed pin", }); - }, + } ChangeEventType::Pronouns => { // change the pronouns user.pronouns = input.new_event.clone(); @@ -250,7 +254,7 @@ pub fn change_info(input: Json, mut cookies: Cookies) -> JsonValue "status": "ok", "reason": "successfully changed pronouns", }); - }, + } }; } else { warn!("incorrect pin for user {}", input.name); @@ -258,7 +262,7 @@ pub fn change_info(input: Json, mut cookies: Cookies) -> JsonValue "status": "fail", "reason": "incorrect pin", }); - }; + }; } else { warn!("couldn't change users info, user does not exist"); return json!({ @@ -290,7 +294,8 @@ pub fn get_user(name: String) -> JsonValue { // Make a user into a moderator fn premote(name: &str) -> JsonValue { if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() { - if user.role != UserType::Admin { // make sure mods can't demote admins ;3 + if user.role != UserType::Admin { + // make sure mods can't demote admins ;3 user.role = UserType::Moderator; db_remove(&user); db_add(&user); @@ -318,7 +323,8 @@ fn premote(name: &str) -> JsonValue { // Make a user into a normal user fn demote(name: &str) -> JsonValue { if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() { - if user.role != UserType::Admin { // make sure mods can't demote admins ;3 + if user.role != UserType::Admin { + // make sure mods can't demote admins ;3 user.role = UserType::Normal; db_remove(&user); db_add(&user); @@ -346,7 +352,8 @@ fn demote(name: &str) -> JsonValue { // Kick a user (temporarilly log them out for a certain amount of time) fn kick(name: &str) -> JsonValue { if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() { - if user.role != UserType::Admin { // make sure mods can't kick admins + if user.role != UserType::Admin { + // make sure mods can't kick admins user.session_token = "NULL".to_string(); db_remove(&user); db_add(&user); @@ -369,13 +376,13 @@ fn kick(name: &str) -> JsonValue { "reason": "user not found", }); } - } // Ban a user (remove their account) fn ban(name: &str) -> JsonValue { if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() { - if user.role != UserType::Admin { // make sure mods can't kick admins + if user.role != UserType::Admin { + // make sure mods can't kick admins db_remove(&user); info!("succesfully banned user {}", &user.name); return json!({ @@ -396,7 +403,6 @@ fn ban(name: &str) -> JsonValue { "reason": "user not found", }); } - } /* User Management */ @@ -409,19 +415,21 @@ pub fn moderation_actions(data: Json, mut cookies: Cookies) -> "status": "fail", "reason": "could not read cookie", }); - }, + } Some(token) => token, }; if let Some(user) = db_read_user(&data.name.to_lowercase()).ok().flatten() { - if token.value() == "NULL" { // fail if token is NULL + if token.value() == "NULL" { + // fail if token is NULL warn!("NULL token!"); return json!({ "status": "fail", "reason": "NULL token", }); - } else if user.session_token == token.value() { // if token matches + } else if user.session_token == token.value() { + // if token matches if user.role == UserType::Moderator || user.role == UserType::Admin { - match data.action { + match data.action { ModActions::Kick => kick(&data.target), ModActions::Ban => ban(&data.target), ModActions::Demote => demote(&data.target), @@ -441,7 +449,7 @@ pub fn moderation_actions(data: Json, mut cookies: Cookies) -> return json!({ "status": "fail", "reason": "token does not match", - }) + }); }; } else { warn!("user not found"); diff --git a/src/chat.rs b/src/chat.rs index 5d53524..220fd5d 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1,14 +1,17 @@ /* Contains Rocket code for chat/message functionality */ extern crate log; -use once_cell::sync::Lazy; -use std::sync::Mutex; use crate::file_io::db_read_user; -use rocket::http::{Cookie, Cookies}; use crate::message::{Message, MessageInput, MessageType}; -use rocket_contrib::json::{Json, JsonValue}; -use chrono::prelude::*; -use uuid::Uuid; use crate::user::User; +use chrono::prelude::*; +use futures_util::StreamExt; +use once_cell::sync::Lazy; +use rocket::http::{Cookie, Cookies}; +use rocket_contrib::json::{Json, JsonValue}; +use std::sync::Mutex; +use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::broadcast; +use uuid::Uuid; static MESSAGES: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); @@ -21,6 +24,15 @@ pub fn fetch_messages() -> Json> { Json(messages) } +async fn send_message_to_websocket() { + let (tx, mut rx1) = broadcast::channel(16); + let mut rx2 = tx.subscribe(); + tokio::spawn(async move { + info!("message: {}", rx1.recv().await.unwrap()); + }); + tx.send(10).unwrap(); +} + // Create full message object and write to file fn create_message(message: Json, user: &User) -> JsonValue { let event_type = match message.body.chars().nth(0).unwrap() { @@ -28,7 +40,7 @@ fn create_message(message: Json, user: &User) -> JsonValue { ':' => MessageType::Emote, _ => MessageType::Normal, }; - + if (message.body == "") | (message.body == " ") { warn!("blank message given"); return json!({ @@ -48,9 +60,13 @@ fn create_message(message: Json, user: &User) -> JsonValue { info!("created mesage: {:?}", message_obj); info!("Date is: {}", message_obj.created_at.to_rfc2822()); + + std::thread::spawn(|| send_message_to_websocket()); + /* // append message to file let mut messages = MESSAGES.lock().unwrap(); messages.push(message_obj.to_owned()); + */ return json!({ "status": "ok", "reason": "message created", @@ -67,7 +83,8 @@ fn check_token(token: Cookie, message: Json>) -> JsonValue { "status": "fail", "reason": "NULL token", }); - } else if user.session_token == token.value() { // if token matches + } else if user.session_token == token.value() { + // if token matches info!("user exists and given token matches"); return create_message(message, &user); } else { @@ -75,7 +92,7 @@ fn check_token(token: Cookie, message: Json>) -> JsonValue { return json!({ "status": "fail", "reason": "token does not match", - }) + }); }; }; warn!("user not found"); @@ -95,25 +112,31 @@ pub fn send_message(message: Json>, mut cookies: Cookies) -> Js "status": "fail", "reason": "could not read cookie", }); - }, + } Some(token) => token, }; check_token(token, message) } -// Delete a message -/* -#[post("/message/delete", format = "json", data = "")] -pub fn delete_message(message: Json>, mut cookies: Cookies) -> JsonValue { - let token = match cookies.get_private("token") { - None => { - warn!("couldn't get token cookie!"); - return json!({ - "status": "fail", - "reason": "could not read cookie", - }); - }, - Some(token) => token, - }; +// Websocket Stuff // + +pub async fn accept_connection(stream: TcpStream) { + let addr = stream + .peer_addr() + .expect("connected streams should have a peer address"); + info!("Peer address: {}", addr); + + let ws_stream = tokio_tungstenite::accept_async(stream) + .await + .expect("Error during the websocket handshake occurred"); + + info!("New WebSocket connection: {}", addr); + + let (tx, mut rx1) = broadcast::channel::(16); + let mut rx2 = tx.subscribe(); + + loop { + let message = rx2.recv().await.unwrap(); + info!("message recieved: {}", message); + } } -*/ diff --git a/src/main.rs b/src/main.rs index fbba3eb..e83a7eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,11 @@ extern crate log; extern crate rocket; #[macro_use] extern crate rocket_contrib; -use rocket_contrib::serve::StaticFiles; - +use chat::accept_connection; use rocket::fairing::AdHoc; +use rocket_contrib::serve::StaticFiles; +use std::io::Error; +use tokio::net::{TcpListener, TcpStream}; mod auth; mod chat; @@ -16,14 +18,32 @@ mod file_io; mod message; mod user; +#[tokio::main] +async fn startup_websocket() -> Result<(), Error> { + let addr = "127.0.0.1:1312".to_string(); + // Create the event loop and TCP listener we'll accept connections on. + let try_socket = TcpListener::bind(&addr).await; + let listener = try_socket.expect("Failed to bind"); + info!("Listening on: {}", addr); + + while let Ok((stream, _)) = listener.accept().await { + tokio::spawn(accept_connection(stream)); + } + + Ok(()) +} + fn main() { env_logger::init(); - info!("Started up rocket"); + + // Start thread for tungstenite websockets + std::thread::spawn(|| startup_websocket()); + let cors_fairing = AdHoc::on_response("CORS", |_, res| { res.set_raw_header("Access-Control-Allow-Origin", "http://localhost:8000"); }); info!("Built CORS fairing"); - + info!("Started up rocket"); rocket::ignite() .mount( "/api", diff --git a/src/user.rs b/src/user.rs index 3d43855..49fc3a8 100644 --- a/src/user.rs +++ b/src/user.rs @@ -13,11 +13,11 @@ pub enum UserType { // Struct to store basic user data #[derive(Clone, Serialize, Deserialize, Debug)] pub struct User { - pub name: String, // unique username - pub pin_hashed: String, // sha1 hash of the pin - pub pronouns: String, // user's pronouns + pub name: String, // unique username + pub pin_hashed: String, // sha1 hash of the pin + pub pronouns: String, // user's pronouns pub session_token: String, // generated session token - pub role: UserType, // type/role of user + pub role: UserType, // type/role of user pub id: Uuid, } @@ -25,18 +25,18 @@ pub struct User { // enum of different moderator actions #[derive(Deserialize, Debug)] pub enum ModActions { - Kick, // Log the user out of their current session - Ban, // Remove the user - Demote, // Demote a user to a lower role + Kick, // Log the user out of their current session + Ban, // Remove the user + Demote, // Demote a user to a lower role Premote, // Premote a user to a higher role } // struct to use for json input #[derive(Deserialize, Debug)] pub struct ModerationAction { - pub name: String, // name of the moderator + pub name: String, // name of the moderator pub action: ModActions, // what action to take - pub target: String, // who to take the action on + pub target: String, // who to take the action on } /* Miscellaneous Events */ @@ -72,7 +72,7 @@ pub enum ChangeEventType { // change info event struct #[derive(Deserialize, Debug)] pub struct ChangeEvent { - pub name: String, // name of the user + pub name: String, // name of the user pub changed_event: ChangeEventType, // which event to change - pub new_event: String, // the new value for the event + pub new_event: String, // the new value for the event }