From 26d3a9b3d0059ccd2a86822bcc72b0073b72e29f Mon Sep 17 00:00:00 2001 From: Erin Nova Date: Thu, 22 Jul 2021 15:01:41 -0400 Subject: [PATCH 1/3] Switch to registering with JSON data --- README.md | 8 +++++--- src/auth.rs | 26 ++++++++++++++++++-------- src/main.rs | 2 +- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6cd6bdd..70fa754 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ # Chat Registration System The basic backend code needed to register & login to a chat system (to be built). -Send it the unhashed username and pin, and it'll store it in the `users.json` file with the pin hashed with SHA1. +Send it the unhashed username and pin, and it'll store it in the database with the pin hashed with SHA1. ## API Documentation +`POST /api/register {"name":"","pin":"","pronouns":""}` Register a user if they don't already exist + `POST /api/register///` Register the username with the pin provided if it doesn't already exist Returns status & reason json. @@ -28,7 +30,7 @@ or `GET /api/token/` Check if the current token matches the user provided -DEPRECATED `GET /api/users//` Check if the user exists, and if the pin provided matches +`GET /api/users//` Check if the user exists, and if the pin provided matches Returns status & reason json. `POST /api/users/change {"name":"","pin":"","changed_event":"name/pin/pronouns","new_event":""` Change a users details via a json post. @@ -43,7 +45,7 @@ Returns status & reason json. ## Chat Documentation -`POST /api/message/send {"name":"username","body":"message body","date":"yyy-mm-dd","token":"USER_TOKEN"}` Post a json message. +`POST /api/message/send {"name":"username","body":"message body","date":"yyyy-mm-dd"}` Post a json message. Returns status & reason json. `GET /api/message/messages.json` Get a json file of all the messages diff --git a/src/auth.rs b/src/auth.rs index 5a11db3..fe4e5bc 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -24,13 +24,20 @@ pub fn index() -> &'static str { `GET /api/about/pronouns/` Get the pronouns of a user" } +#[derive(Deserialize, Debug)] +pub struct RegisterEvent { + pub name: String, + pub pin: String, + pub pronouns: String, +} + // Post request to register a user and pin -#[post("/register///")] -pub fn register_user(name: String, pin: i32, pronouns: String) -> JsonValue { - let mut users: Vec = db_read(); // Create an array of users out of parsed json +#[post("/register", format = "json", data = "")] +pub fn register_user(info: Json) -> JsonValue { + let users: Vec = db_read(); // Create an array of users out of parsed json for i in &users { // loop through elements of the vector - if i.name == name.to_lowercase() { + if i.name == info.name.to_lowercase() { warn!("Cannot create user {}! User is already in system.", i.name); return json!({ "status": "fail", @@ -39,12 +46,12 @@ pub fn register_user(name: String, pin: i32, pronouns: String) -> JsonValue { }; } - let pin_hashed = sha1::Sha1::from(&pin.to_string()).digest().to_string(); // hash the pin + let pin_hashed = sha1::Sha1::from(&info.pin.to_string()).digest().to_string(); // hash the pin let new_user: User = User { - name: name.to_string().to_lowercase(), + name: info.name.to_string().to_lowercase(), pin_hashed: pin_hashed, - pronouns: pronouns.to_string().to_lowercase(), + pronouns: info.pronouns.to_string().to_lowercase(), session_token: "NULL".to_string(), }; // append the user to the vec @@ -161,6 +168,7 @@ pub fn logout(info: Json, mut cookies: Cookies) -> JsonValue { "reason": "NULL token", }); } else if token.value() == users[i].session_token { + cookies.remove_private(Cookie::named("token")); users[i].session_token = "NULL".to_string(); info!("logged out user {}", info.name); @@ -186,7 +194,7 @@ pub fn logout(info: Json, mut cookies: Cookies) -> JsonValue { // Check if pin matches user #[get("/users//")] -pub fn check_pin(mut cookies: Cookies, name: String, pin: i32) -> JsonValue { +pub fn login(mut cookies: Cookies, name: String, pin: i32) -> JsonValue { let users: Vec = db_read(); let hashed_pin_input = sha1::Sha1::from(&pin.to_string()).digest().to_string(); for i in &users { @@ -199,6 +207,8 @@ pub fn check_pin(mut cookies: Cookies, name: String, pin: i32) -> JsonValue { let token = create_token(i.name.clone(), users); let cookie = Cookie::build("token", token) .path("/") + .same_site(SameSite::Strict) + .secure(true) .finish(); cookies.remove_private(Cookie::named("token")); cookies.add_private(cookie); diff --git a/src/main.rs b/src/main.rs index 42a9a1c..1efa8d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,7 +31,7 @@ fn main() { auth::index, auth::get_user, auth::register_user, - auth::check_pin, + auth::login, auth::change, chat::send_message, chat::fetch_messages, From 05ecacc50bf140d39f3309f8950b1fcbbb2cdb2a Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 22 Jul 2021 23:53:53 -0700 Subject: [PATCH 2/3] Frontend: fixed updateInfo? Misc changes and fixed bugs. --- frontend/chat.css | 43 +++++++ frontend/chat.html | 37 ++++++ frontend/chat.js | 75 +++++++++++ frontend/login.html | 2 +- frontend/login.js | 2 +- frontend/loginchange.js | 77 ------------ frontend/register.html | 2 +- frontend/register.js | 12 +- frontend/style.css | 6 +- .../{loginchange.html => updateinfo.html} | 27 +++- frontend/updateinfo.js | 119 ++++++++++++++++++ 11 files changed, 310 insertions(+), 92 deletions(-) create mode 100644 frontend/chat.css create mode 100644 frontend/chat.html create mode 100644 frontend/chat.js delete mode 100644 frontend/loginchange.js rename frontend/{loginchange.html => updateinfo.html} (54%) create mode 100644 frontend/updateinfo.js diff --git a/frontend/chat.css b/frontend/chat.css new file mode 100644 index 0000000..5ed8007 --- /dev/null +++ b/frontend/chat.css @@ -0,0 +1,43 @@ +html { + background: #F7A8B8; + text-align: center; + font-family: "Lucida Console", "Courier New", monospace; +} + +form { + width: 100% +} + +input { + padding: 3%; +} + +label { + visibility: hidden; +} + +#chatbox { + background-color: white; + padding: 1rem; + box-shadow: 10px 10px 10px black; + width: 40rem; + height: 40rem; + display: inline-flex; + flex-direction: column; +} + +#innerchatbox { + background-color: rgba(60, 60, 60, .75); + width: 100%; + height: 90%; + overflow-y: scroll; + text-align: left; +} + +#loggeduser { + padding-top: 1% +} + +#error { + padding-top: 2.5%; +} \ No newline at end of file diff --git a/frontend/chat.html b/frontend/chat.html new file mode 100644 index 0000000..62d56fc --- /dev/null +++ b/frontend/chat.html @@ -0,0 +1,37 @@ + + + + + Chat Room + + + + + + + + + + +

Welcome to the chat!

+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/frontend/chat.js b/frontend/chat.js new file mode 100644 index 0000000..f216c0c --- /dev/null +++ b/frontend/chat.js @@ -0,0 +1,75 @@ +// VARIABLES +let date = '2021-07-22' +let messageCount = 0; +let username = localStorage.getItem('username'); +const form = document.querySelector('form'); + +// SEND A MESSAGE + +// GRABS MESSAGE FROM FORM & SENDS +form.addEventListener("submit", async function (event) { + event.preventDefault(); + const formData = new FormData(form); + + formMessage = formData.get('message'); + + sendMessage() + +}) + +//SEND MESSAGE FETCH FUNCTION + +async function sendMessage() { + sendMessageInfo = { "name": username, "body": formMessage, "date": date } + fetch('/api/message/send', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(sendMessageInfo), + }) + form.reset() +} + + +// RECIEVE MESSAGES + +let messageUpdate = window.setInterval(fetchMessages, 500); + +async function fetchMessages() { + const response = await fetch('/api/message/messages.json'); + const recievedMessages = await response.json(); + document.getElementById("innerchatbox").innerHTML = "" + + for (const message of recievedMessages) { + printText(message.user.bold() + ": " + message.body); + } + + + if (recievedMessages.length != messageCount) { + let scroll = document.getElementById("innerchatbox"); + scroll.scrollTop = scroll.scrollHeight; + } + + messageCount = recievedMessages.length; +} + + +// FUNCTION TO PRINT MESSAGES IN THE CHAT BOX + +function printText(text) { + let p = document.createElement("p"); + const div = document.getElementById("innerchatbox"); + div.appendChild(p) + p.innerHTML = text +} + + +//LOGGED IN STUFF +//TODO ADD CHECK TO SEE IF USERNAME AND TOKEN MATCHES +if (username === null) { + document.querySelector("#loggeduser").innerHTML = 'You are not logged in' + username = '' +} else { + document.querySelector("#loggeduser").innerHTML = `You are logged in as ${username}` +} \ No newline at end of file diff --git a/frontend/login.html b/frontend/login.html index 6915897..48ad76a 100644 --- a/frontend/login.html +++ b/frontend/login.html @@ -16,7 +16,7 @@

Login:

-
+

diff --git a/frontend/login.js b/frontend/login.js index e8af605..5494aca 100644 --- a/frontend/login.js +++ b/frontend/login.js @@ -29,7 +29,7 @@ form.addEventListener("submit", async function (event) { function login() { console.log('You have logged in!') - document.querySelector("#username").innerHTML = `${uname}` + document.querySelector("#username").innerHTML = `Logged in as ${uname}` document.querySelector("#errormessage").innerHTML = '' localStorage.setItem("username", `${uname}`); } diff --git a/frontend/loginchange.js b/frontend/loginchange.js deleted file mode 100644 index 1fc0941..0000000 --- a/frontend/loginchange.js +++ /dev/null @@ -1,77 +0,0 @@ - -//SETTING VARIABLES. GRABBING ELEMENT VALUES FROM FORM. - -let uname = document.querySelector('#uname').value; -let pin = document.querySelector('#pin').value; -let newUname = document.querySelector('#newuname').value; -let newPin = document.querySelector('#newpin').value; -const form = document.querySelector('form'); -let responseText; - - -//TODO -// let selected = document.querySelector('#selected').value; -// let custom = document.querySelector('#custom').value; -// let pronouns = '' - -//FORM SUMBIT FUNCTION & GET THE USERS USERNAME AND SEE IF IT IS CORRECT. - - -form.addEventListener("submit", async function (event) { - event.preventDefault(); - const formData = new FormData(form); - - uname = formData.get('uname'); - pin = formData.get('pin'); - newUname = formData.get('newuname'); - newPin = formData.get('newpin'); - - //TODO - // selected = formData.get('selected'); - // custom = formData.get('custom') - - // if (custom !== '') { - // pronouns = custom - // } else { - // pronouns = selected - // } - - if (newUname === '') { - newUname = uname - } - if (newPin === '') { - newPin = pin - } - - try { - const userNotFound = await getUname(); - - if (userNotFound.status === 'fail') { - document.querySelector("#errormessage").innerHTML = `user ${uname} was not found` - } else { - loginChange() - } - } catch { - document.querySelector("#errormessage").innerHTML = 'An Error has Occurred. Try again later.' - } -}) - - -//FETCH FUNTIONS. FETCHING USERNAME FROM API AND SUBMITTING NEW PIN AND USERNAME TO API. - -async function getUname() { - let response = await fetch(`/api/users/${uname}`); - responseJson = await response.json(); - return responseJson; -} - -async function loginChange() { - const rawResponse = await fetch(`/api/users/change/${uname}/${pin}/${newUname}/${newPin}`, { - method: 'POST', - headers: { - }, - body: "" - }); - document.querySelector("#errormessage").innerHTML = 'Login Changed!' - window.location.replace("/login.html") -} diff --git a/frontend/register.html b/frontend/register.html index 66b3201..fcd4654 100644 --- a/frontend/register.html +++ b/frontend/register.html @@ -15,7 +15,7 @@
- +

diff --git a/frontend/register.js b/frontend/register.js index dea709f..c2604bb 100644 --- a/frontend/register.js +++ b/frontend/register.js @@ -27,9 +27,9 @@ form.addEventListener("submit", async function (event) { } try { - const isTaken = await getUname(); + const isNotTaken = await getUname(); - if (isTaken.status === "fail") { + if (isNotTaken.status === "fail") { register() } else { document.querySelector("#errormessage").innerHTML = `${uname} is already taken.` @@ -48,11 +48,13 @@ async function getUname() { } async function register() { - const rawResponse = await fetch(`/api/register/${uname.toString().toLowerCase()}/${pin.toString()}/${pronouns.toString().toLowerCase().replace("/", ".")}`, { + let sendRegisterInfo = { "name": uname, "pin": pin, "pronouns": pronouns } + fetch('/api/register/', { method: 'POST', headers: { - }, - body: "" + 'Content-Type': 'application/json', + }, + body: JSON.stringify(sendRegisterInfo), }); document.querySelector("#errormessage").innerHTML = 'Registered!' window.location.replace("/login.html") diff --git a/frontend/style.css b/frontend/style.css index 1ea339f..a7f671a 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -5,7 +5,7 @@ html { } body { - margin-top: 10%; + margin-top: 3%; } form { @@ -17,7 +17,7 @@ form { padding: 5%; box-shadow: 10px 10px 10px black; border-radius: 5px; - display:inline-flex; + display: inline-flex; width: 20%; } @@ -50,4 +50,4 @@ input[type=number]::-webkit-outer-spin-button { input[type=number] { -moz-appearance: textfield; -} +} \ No newline at end of file diff --git a/frontend/loginchange.html b/frontend/updateinfo.html similarity index 54% rename from frontend/loginchange.html rename to frontend/updateinfo.html index 3fbf4c1..5cc9e75 100644 --- a/frontend/loginchange.html +++ b/frontend/updateinfo.html @@ -2,7 +2,7 @@ - Login Change + Update Info @@ -13,28 +13,47 @@ -

Change username and/or pin:

+

Change username/pin/pronouns.

(leave field blank if not changing)

- +




+

What are you changing?

+




+
+ + +

Or.

+ +
+ + +

Format: pronoun/pronoun


+
- +
diff --git a/frontend/updateinfo.js b/frontend/updateinfo.js new file mode 100644 index 0000000..c235472 --- /dev/null +++ b/frontend/updateinfo.js @@ -0,0 +1,119 @@ + +//SETTING VARIABLES. GRABBING ELEMENT VALUES FROM FORM. + +let uname = document.querySelector('#uname').value; +let pin = document.querySelector('#pin').value; +let newUname = document.querySelector('#newuname').value; +let newPin = document.querySelector('#newpin').value; +const form = document.querySelector('form'); +let selected = document.querySelector('#selected').value; +let custom = document.querySelector('#custom').value; +let responseText; +let updateEvent = '' +let newEvent = '' +let newPronouns = '' + +//FORM SUMBIT FUNCTION & GET THE USERS USERNAME AND SEE IF IT IS CORRECT. + + +form.addEventListener("submit", async function (event) { + event.preventDefault(); + const formData = new FormData(form); + + uname = formData.get('uname'); + pin = formData.get('pin'); + newUname = formData.get('newuname'); + newPin = formData.get('newpin'); + selected = formData.get('selected'); + custom = formData.get('custom') + + if (custom === '' && selected === 'none') { + newPronouns = '' + } else if (custom !== '') { + newPronouns = custom + } else { + newPronouns = selected + } + +//CHECKS IF THE USER IS CHANGING MORE THAN ONE TEXT FIELD AT A TIME + let onlyChangeOne = document.querySelector("#errormessage").innerHTML = 'You can only change one at a time!' + if (newUname !== '' && newPin !== '') { + onlyChangeOne + } else if (newUname !== '' && newPronouns !== '') { + onlyChangeOne + } else if (newPin !== '' && newPronouns !== '') { + onlyChangeOne + } else { + checkLoginInfo() + } + + +// ASSIGNS VARIABLES TO BE SENT TO API + if (newUname === '' && newPin === '' && newPronouns !== '') { + newEvent = newPronouns + updateEvent = 'pronouns' + } else if (newUname === '' && newPronouns === '' && newPin !== '') { + newEvent = newPin + updateEvent = 'pin' + } else if (newPin === '' && newPronouns === '' && newUname !== '') { + newEvent = newUname + updateEvent = 'name' + } else if (newPin === '' && newUname === '' && newPronouns === '') { + document.querySelector("#errormessage").innerHTML = 'Please enter a new name, pin, or pronouns!' + } else { + checkLoginInfo() + } + + //CHECKS IF USERNAME IS TAKEN + const isTaken = await getUname(); + + if (isTaken.status === 'ok') { + document.querySelector("#errormessage").innerHTML = `username ${newUname} is already taken! ` + } +}) + + +// FETCH FUNTIONS. FETCHING USERNAME TO SEE IF ITS TAKEN. + +async function getUname() { + let response = await fetch(`/api/users/${newUname}`); + responseJson = await response.json(); + return responseJson; +} + + +//FETCH FUNCTION TO UPDATE USER INFO + + //TODO ADD CHECKING THE TOKEN with LOGIN IN IF STATEMENT +//CHECKING IF THE USER CAN LOGIN WITH GIVEN CURRENT USERNAME AND PIN +async function checkLoginInfo() { + const response = await fetch(`/api/users/${uname}/${pin}`); + const loginInfo = await response.json(); + + if (loginInfo.status === "ok") { + updateInfo() + } else { + incorrectLogin() + } +} + +async function updateInfo() { + let sendUpdateInfo = { "name": uname, "pin": pin, "changed_event": updateEvent, "new_event": newEvent } + fetch('/api/users/change', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(sendUpdateInfo), + }); + //document.querySelector("#errormessage").innerHTML = 'Login Changed!' + //window.location.replace("/login.html") +} + +function incorrectLogin() { + document.querySelector("#errormessage").innerHTML = 'Username and pin combination do not match! Or user not found.' +} + +function errorMessage() { + document.querySelector("#errormessage").innerHTML = 'An Error has Occurred. Try again later.' +} From 69b7259571f36bbed3ac9d4e5765f3c521273ab6 Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 23 Jul 2021 01:05:11 -0700 Subject: [PATCH 3/3] Frontend: added more to index.html --- frontend/index.html | 18 +++++++++++++----- frontend/stream.css | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 frontend/stream.css diff --git a/frontend/index.html b/frontend/index.html index b002de1..cbf32f7 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7,20 +7,28 @@ - + - - -Login Page + +
+
+

Test Text

+
+ + + +
diff --git a/frontend/stream.css b/frontend/stream.css new file mode 100644 index 0000000..9a3cbe1 --- /dev/null +++ b/frontend/stream.css @@ -0,0 +1,34 @@ +html { + background: #F7A8B8; + text-align: center; + font-family: "Lucida Console", "Courier New", monospace; +} + +body { + margin-top: 3%; +} + +#streamchat { + display: flex; + height: 100%; + max-width: 960px; + margin: 0 auto; + +} + +#stream { + background-color: white; + padding: 5%; + box-shadow: 10px 10px 10px black; + border-radius: 5px; + width: 100%; + height: 100%; + margin-right: 4em; +} + +#chatbox { + width: 100%; + height: 100%; + margin-left: 4em; +} +