created api routes for signup login and getting user tests

This commit is contained in:
Arlo Filley 2022-11-11 19:54:52 +00:00
parent 9f2a5641db
commit d53fe82cc7
10 changed files with 205 additions and 26 deletions

View File

@ -14,6 +14,7 @@ use rocket::{
json::Json
}
};
use crate::sql::Test;
#[get("/")]
fn test() -> String {
@ -80,10 +81,16 @@ fn login(username: &str, password: &str) -> String {
user_id.to_string()
}
#[get("/get_user_tests/<user_id>")]
fn get_user_tests(user_id: u32) -> Json<Vec<Test>> {
let tests = sql::get_user_tests(user_id).expect("error finding user_id");
Json(tests)
}
#[launch]
fn rocket() -> Rocket<Build> {
rocket::build()
.mount("/test", routes![test]) // testing only, should return "Hello world"
.mount("/api", routes![post_test, create_user, login])
.mount("/api", routes![post_test, create_user, login, get_user_tests])
.mount("/typing", FileServer::from(relative!("website"))) // hosts the fileserver
}

View File

@ -1,4 +1,5 @@
use rusqlite::{Connection, Result};
use rocket::serde::Serialize;
fn get_connection() -> rusqlite::Connection {
Connection::open("database/database.sqlite")
@ -143,4 +144,49 @@ pub fn find_user(
}
Ok(user_id)
}
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
pub struct Test {
test_type: String,
test_length: u32,
test_time: u32,
test_seed: i64,
quote_id: i32,
wpm: u8,
accuracy: u8,
}
pub fn get_user_tests(
user_id: u32
) -> Result<Vec<Test>> {
let connection = get_connection();
let mut statement = connection.prepare(
"SELECT test_type, test_length, test_time, test_seed, quote_id, wpm, accuracy
FROM tests
WHERE user_id=:user_id",
)?;
let mut user_id: u32 = 0;
let test_iter = statement
.query_map(&[(":user_id", &user_id.to_string())], |row| {
Ok( Test {
test_type: row.get(0)?,
test_length: row.get(1)?,
test_time: row.get(2)?,
test_seed: row.get(3)?,
quote_id: row.get(4)?,
wpm: row.get(5)?,
accuracy: row.get(6)?
})
})?;
let mut tests: Vec<Test> = vec![];
for test in test_iter {
tests.push(test.unwrap());
}
Ok(tests)
}

View File

@ -54,7 +54,7 @@ class API {
* Validates all the parameters used for the postTest function which it then calls
*/
validateTest() {
const test = screenManager.textbox.getLetters();
const test = screenManager.screen.textbox.getLetters();
const testType = "words";
let testLength = test.length;
let testTime = screenManager.timer.getTime();
@ -62,7 +62,7 @@ class API {
const quoteId = 0;
let wpm;
const accuracy = 0;
const userId = 0;
const userId = Number(user.userId);
// this is the wpm calculation factoring in the time of test
// it assumes that all words are 5 characters long because on average
@ -184,26 +184,33 @@ class API {
xhr.send(
JSON.stringify(user)
);
this.login(username, password);
}
login(pUsername, pPassword) {
if (localStorage.getItem("userId") === null) {
if (localStorage.userId === null || localStorage.userId === 0 || localStorage.userId === undefined) {
let xhr = new XMLHttpRequest();
xhr.open('GET', `${this.url}/login/${pUsername}/${pPassword}`);
xhr.send();
xhr.onload = () => {
user.userId = Number(xhr.response);
if (user.userId > 0) {
user.username = pUsername
localStorage.setItem("userId", user.userId);
localStorage.setItem("username", pUsername);
localStorage.setItem("password", pPassword);
}
};
} else {
this.userId = localStorage.getItem("userId");
this.username = localStorage.getItem("username");
xhr.open('GET', `${this.url}login/${pUsername}/${pPassword}`);
xhr.send();
xhr.onload = () => {
user.userId = Number(xhr.response);
if (user.userId > 0) {
user.username = pUsername
localStorage.setItem("userId", user.userId);
localStorage.setItem("username", pUsername);
localStorage.setItem("password", pPassword);
}
};
} else if (localStorage.userId > 0) {
user.userId = localStorage.userId;
user.username = localStorage.username;
user.password = localStorage.password;
}
}
logout() {
user = new User();
localStorage.clear();
}
}

View File

@ -1,7 +1,7 @@
class User {
constructor() {
this.username;
this.password;
this.userId;
this.username = "not logged in";
this.password = "there";
this.userId = 0;
}
}

View File

@ -23,6 +23,7 @@
<script src="./screens/testscreen.js"></script>
<script src="./screens/endscreen.js"></script>
<script src="./screens/signUpScreen.js"></script>
<script src="./screens/loginscreen.js"></script>
<!-- API Script Files -->
<script src="./api/api.js"></script>

View File

@ -1,4 +1,4 @@
let canvas, api, screenManager;
let canvas, api, screenManager, user;
function setup() {
// Creating the canvas
@ -11,6 +11,10 @@ function setup() {
api = new API();
screenManager = new ScreenManager();
screenManager.setScreen(new StartScreen());
user = new User();
// will log the user in if there details are in local storage
api.login();
}
// this function is called once per frame and draws all other elements

View File

@ -10,4 +10,8 @@ class EndScreen {
fill(0);
text("Test Complete\nPress enter to start another test", 0, 0, windowWidth - 100, windowHeight - 100);
}
letterTyped() {
screenManager.setScreen(new StartScreen());
}
}

View File

@ -0,0 +1,98 @@
class LoginScreen {
constructor() {
this.textboxes = [
new Textbox(
120,250,
500,100,
0,
true,
"#000",
false, "#000",
"#000"
),
new Textbox(
120,400,
500,100,
0,
true,
"#000",
false,"000",
"#000"
)
]
this.buttons = [
new Button(
100,200,
500,100,
0,
true,
"#000",
false,"#000",
"#fff",""
),
new Button(
100,350,
500,100,
0,
true,
"#000",
false,"#000",
"#fff",""
),
new Button(
700,300,
100,50,
0,
true,
"#000",
false,"#000",
"#00ff00","Login"
),
]
this.activeTextBox = 0
// keeps track of which textbox the user last clicked on
}
/**
* Draws the SignUpScreen class with all
* appropriate elements
*/
draw() {
background("#eeeee4");
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
}
for (let i = 0; i < this.textboxes.length; i++) {
this.textboxes[i].draw();
}
text("Username", 110, 175);
text("Password", 110, 325);
if (this.buttons[0].isPressed()) {
this.activeTextBox=0;
} else if (this.buttons[1].isPressed()) {
this.activeTextBox=1;
} else if (this.buttons[2].isPressed()) {
api.login(
this.textboxes[0].getWords(),
this.textboxes[1].getWords()
)
screenManager.setScreen(new StartScreen());
}
}
/**
*
* @param {key} key
*/
letterTyped(key) {
this.textboxes[this.activeTextBox].letterTyped(key);
}
}

View File

@ -1,6 +1,10 @@
class StartScreen {
constructor() {
this.buttons = [new Button(0,0,100,30,0,true,"#fff",false,"#000","#000","Sign Up")]
this.buttons = [
new Button(0,0,100,30,0,true,"#fff",false,"#000","#000","Sign Up"),
new Button(110,0,100,30,0,true,"#fff",false,"#000","#000","Login"),
new Button(220,0,100,30,0,true,"#fff",false,"#000","#000","Logout"),
]
}
draw() {
@ -10,9 +14,17 @@ class StartScreen {
fill("#000");
text("Press enter to start test", 0, 0, windowWidth - 100, windowHeight - 100);
this.buttons[0].draw();
this.buttons[1].draw();
this.buttons[2].draw();
if (this.buttons[0].isPressed()) {
screenManager.setScreen(new SignUpScreen());
}
} else if (this.buttons[1].isPressed()) {
screenManager.setScreen(new LoginScreen());
} else if (this.buttons[2].isPressed()) {
api.logout();
}
fill("#000");
text(`${user.username}`, windowWidth-100, 15);
}
letterTyped(key) {

View File

@ -133,7 +133,7 @@ class Textbox {
if (pKey === "Backspace" && this.letters.length > 0) {
this.letters.pop();
this.words.substring(0, this.words.length-1)
this.words = this.words.substring(0, this.words.length-1)
return;
}