api fixes
This commit is contained in:
parent
5102606f51
commit
39aedf8fcc
12
TODO.md
Normal file
12
TODO.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Backend
|
||||||
|
-[x] Migrate to sqlx as backend database queryer
|
||||||
|
-[ ] Allow Private Accounts
|
||||||
|
-[ ] Secrets to authenicate that its the user
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
-[ ] Make js api asynchronous
|
||||||
|
-[ ] Hash passwords on front end so server plaintext password is never sent over the internet
|
||||||
|
-[ ] Use secret to uniquely identify
|
||||||
|
-[ ] Scrollbars
|
||||||
|
-[ ] Change Color Scheme
|
||||||
|
-[ ] Be able to view others accounts
|
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
use rocket::{ serde::json::Json, State, Data };
|
use rocket::{ serde::json::Json, State };
|
||||||
use crate::typing::sql::{
|
use crate::typing::sql::{
|
||||||
Database,
|
Database,
|
||||||
LeaderBoardTest
|
LeaderBoardTest
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
use sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
|
use sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
|
||||||
use rocket::serde::Serialize;
|
use rocket::serde::Serialize;
|
||||||
|
|
||||||
|
/// Contains the database connection pool
|
||||||
pub struct Database(SqlitePool);
|
pub struct Database(SqlitePool);
|
||||||
|
|
||||||
/// gets a connection to the database and returns it as
|
/// gets a connection to the database and returns it as
|
||||||
@ -71,11 +72,11 @@ impl Database {
|
|||||||
|
|
||||||
/// takes a username and password and creates a database
|
/// takes a username and password and creates a database
|
||||||
/// entry for a new user
|
/// entry for a new user
|
||||||
pub async fn create_user(&self, username: &str, password: &str) -> Result<(), sqlx::Error> {
|
pub async fn create_user(&self, username: &str, password: &str, secret: &str) -> Result<(), sqlx::Error> {
|
||||||
sqlx::query!("
|
sqlx::query!("
|
||||||
INSERT INTO Users (username, password)
|
INSERT INTO Users (username, password, secret)
|
||||||
VALUES (?1, ?2)",
|
VALUES (?1, ?2, ?3)",
|
||||||
username, password
|
username, password, secret
|
||||||
).execute(&self.0).await?;
|
).execute(&self.0).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -87,12 +88,12 @@ impl Database {
|
|||||||
let user = sqlx::query!("
|
let user = sqlx::query!("
|
||||||
SELECT user_id, secret
|
SELECT user_id, secret
|
||||||
FROM Users
|
FROM Users
|
||||||
WHERE username=:username AND password=:password",
|
WHERE username=? AND password=?",
|
||||||
username, password
|
username, password
|
||||||
).fetch_all(&self.0).await?;
|
).fetch_one(&self.0).await?;
|
||||||
|
|
||||||
let user_id = user[0].user_id.unwrap() as u32;
|
let user_id = user.user_id.unwrap() as u32;
|
||||||
let secret = user[0].secret.clone();
|
let secret = user.secret.clone();
|
||||||
|
|
||||||
Ok(Some((user_id, secret)))
|
Ok(Some((user_id, secret)))
|
||||||
}
|
}
|
||||||
@ -104,10 +105,12 @@ impl Database {
|
|||||||
SELECT test_type, test_length, test_time, test_seed, quote_id, wpm, accuracy
|
SELECT test_type, test_length, test_time, test_seed, quote_id, wpm, accuracy
|
||||||
FROM tests
|
FROM tests
|
||||||
INNER JOIN users ON users.user_id = tests.user_id
|
INNER JOIN users ON users.user_id = tests.user_id
|
||||||
WHERE users.user_id=:user_id AND users.secret=:secret",
|
WHERE users.user_id=? AND users.secret=?",
|
||||||
user_id, secret
|
user_id, secret
|
||||||
).fetch_all(&self.0).await?;
|
).fetch_all(&self.0).await?;
|
||||||
|
|
||||||
|
println!("{}", tests.len());
|
||||||
|
|
||||||
let user_tests = tests.iter()
|
let user_tests = tests.iter()
|
||||||
.map(|test| Test {
|
.map(|test| Test {
|
||||||
test_type: test.test_type.clone(),
|
test_type: test.test_type.clone(),
|
||||||
|
@ -3,6 +3,8 @@ use rocket::{
|
|||||||
State
|
State
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use rand::{ distributions::Alphanumeric, Rng };
|
||||||
|
|
||||||
use crate::typing::sql::{ Database, Test };
|
use crate::typing::sql::{ Database, Test };
|
||||||
|
|
||||||
/// Struct representing the user
|
/// Struct representing the user
|
||||||
@ -18,9 +20,15 @@ pub struct User<'r> {
|
|||||||
/// Acessible from http://url/api/create_user
|
/// Acessible from http://url/api/create_user
|
||||||
#[post("/create_user", data = "<user>")]
|
#[post("/create_user", data = "<user>")]
|
||||||
pub async fn sign_up(user: Json<User<'_>>, database: &State<Database>) {
|
pub async fn sign_up(user: Json<User<'_>>, database: &State<Database>) {
|
||||||
match database.create_user( user.username, &sha256::digest(user.password) ).await {
|
let secret: String = rand::thread_rng()
|
||||||
|
.sample_iter(&Alphanumeric)
|
||||||
|
.take(50)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
match database.create_user( user.username, &sha256::digest(user.password), &secret ).await {
|
||||||
Err(why) => { println!("A database error occured during signup, {why}"); }
|
Err(why) => { println!("A database error occured during signup, {why}"); }
|
||||||
Ok(()) => { println!("Succesfully Signed up user {}", user.username); }
|
Ok(()) => { println!("Succesfully Signed up User: {}", user.username); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,16 +53,16 @@ pub async fn get_tests(user_id: u32, secret: String, database: &State<Database>)
|
|||||||
/// which can be used to identify their tests etc.
|
/// which can be used to identify their tests etc.
|
||||||
/// Accessible from http://url/api/login
|
/// Accessible from http://url/api/login
|
||||||
#[get("/login/<username>/<password>")]
|
#[get("/login/<username>/<password>")]
|
||||||
pub async fn login(username: &str, password: &str, database: &State<Database>) -> Option<Json<LoginResponse>> {
|
pub async fn login(username: &str, password: &str, database: &State<Database>) -> Json<Option<LoginResponse>> {
|
||||||
match database.find_user(username, &sha256::digest(password)).await {
|
match database.find_user(username, &sha256::digest(password)).await {
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
println!("A database error occured during login for {username}, {why}");
|
println!("A database error occured during login for {username}, {why}");
|
||||||
None
|
Json(None)
|
||||||
}
|
}
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
match user {
|
match user {
|
||||||
None => None,
|
None => Json(None),
|
||||||
Some(user) => { Some(Json(LoginResponse { user_id: user.0, secret: user.1 })) }
|
Some(user) => { Json(Some(LoginResponse { user_id: user.0, secret: user.1 })) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +70,7 @@ pub async fn login(username: &str, password: &str, database: &State<Database>) -
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(crate = "rocket::serde")]
|
#[serde(crate = "rocket::serde")]
|
||||||
struct LoginResponse {
|
pub struct LoginResponse {
|
||||||
user_id: u32,
|
user_id: u32,
|
||||||
secret: String,
|
secret: String,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
class API {
|
class API {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.url = "https://arlofilley.com/api/";
|
// this.url = "https://arlofilley.com/api/";
|
||||||
|
this.url = "../api";
|
||||||
// this is the url of the server
|
// this is the url of the server
|
||||||
// this may have to change later on
|
// this may have to change later on
|
||||||
}
|
}
|
||||||
@ -33,16 +34,7 @@ class API {
|
|||||||
* @param {int} accuracy
|
* @param {int} accuracy
|
||||||
* @param {int} userId
|
* @param {int} userId
|
||||||
*/
|
*/
|
||||||
postTest(
|
postTest(pTestType, pTestLength, pTestTime, pTestSeed, pQuoteId, pWpm, pAccuracy, pUserId) {
|
||||||
pTestType,
|
|
||||||
pTestLength,
|
|
||||||
pTestTime,
|
|
||||||
pTestSeed,
|
|
||||||
pQuoteId,
|
|
||||||
pWpm,
|
|
||||||
pAccuracy,
|
|
||||||
pUserId
|
|
||||||
) {
|
|
||||||
const data = {
|
const data = {
|
||||||
'test_type': pTestType,
|
'test_type': pTestType,
|
||||||
'test_length': pTestLength,
|
'test_length': pTestLength,
|
||||||
@ -57,7 +49,7 @@ class API {
|
|||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open(
|
xhr.open(
|
||||||
"POST",
|
"POST",
|
||||||
this.url+"post_test"
|
`${this.url}/post_test/`
|
||||||
);
|
);
|
||||||
|
|
||||||
xhr.send(
|
xhr.send(
|
||||||
@ -174,16 +166,7 @@ class API {
|
|||||||
|
|
||||||
// there will be other tests here in later iterations but for now these tests should suffice
|
// there will be other tests here in later iterations but for now these tests should suffice
|
||||||
|
|
||||||
this.postTest(
|
this.postTest(testType, testLength, testTime, testSeed, quoteId, wpm, accuracy, userId);
|
||||||
testType,
|
|
||||||
testLength,
|
|
||||||
testTime,
|
|
||||||
testSeed,
|
|
||||||
quoteId,
|
|
||||||
wpm,
|
|
||||||
accuracy,
|
|
||||||
userId
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,10 +177,7 @@ class API {
|
|||||||
* @param {String} password
|
* @param {String} password
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
createUser(
|
createUser( username, password ) {
|
||||||
username,
|
|
||||||
password
|
|
||||||
) {
|
|
||||||
console.log( username, password );
|
console.log( username, password );
|
||||||
const user = {
|
const user = {
|
||||||
username: username,
|
username: username,
|
||||||
@ -205,48 +185,65 @@ class API {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open(
|
xhr.open( "POST", `${this.url}/create_user/` );
|
||||||
"POST",
|
|
||||||
`${this.url}create_user/`
|
|
||||||
);
|
|
||||||
|
|
||||||
xhr.send(
|
xhr.send( JSON.stringify(user) );
|
||||||
JSON.stringify(user)
|
|
||||||
);
|
|
||||||
|
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
if (xhr.status === 500) {
|
if (xhr.status === 500) {
|
||||||
alert("Sorry, looks like your username isn't unique");
|
alert("Sorry, looks like your username isn't unique");
|
||||||
|
console.error("Sorry, looks like your username isn't unique")
|
||||||
} else {
|
} else {
|
||||||
this.login(username, password);
|
this.login(username, password);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
login(pUsername, pPassword) {
|
|
||||||
if (localStorage.userId === null || localStorage.userId === 0 || localStorage.userId === undefined) {
|
/**
|
||||||
|
* takes a validated name and password and sends
|
||||||
|
* a post request to make a user with the given
|
||||||
|
* username and password
|
||||||
|
* @param {String} username
|
||||||
|
* @param {String} password
|
||||||
|
* @param {boolean} initial
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
login(pUsername, pPassword, initial = false) {
|
||||||
|
// Variable Validation
|
||||||
|
if (pUsername == undefined || pPassword == undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Local Storage has the information we need there is no need to make a request to the server
|
||||||
|
if (localStorage.getItem("username") == pUsername) {
|
||||||
|
user.userId = localStorage.getItem("userId");
|
||||||
|
user.secret = localStorage.getItem("secret");
|
||||||
|
user.username = localStorage.getItem("username");
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', `${this.url}login/${pUsername}/${pPassword}`);
|
xhr.open('GET', `${this.url}/login/${pUsername}/${pPassword}`);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
user.userId = Number(xhr.response);
|
let response = JSON.parse(xhr.response);
|
||||||
if (user.userId > 0) {
|
|
||||||
|
// If there is an error with the login we need
|
||||||
|
if (xhr.response == null) {
|
||||||
|
alert("Error Logging in, maybe check your password");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user.userId = response.user_id;
|
||||||
user.username = pUsername
|
user.username = pUsername
|
||||||
|
user.secret = response.secret;
|
||||||
|
|
||||||
localStorage.setItem("userId", user.userId);
|
localStorage.setItem("userId", user.userId);
|
||||||
localStorage.setItem("username", pUsername);
|
localStorage.setItem("username", pUsername);
|
||||||
localStorage.setItem("password", pPassword);
|
localStorage.setItem("secret", user.secret);
|
||||||
} else {
|
|
||||||
user.username = "no one";
|
|
||||||
user.password = "none";
|
|
||||||
user.userId = 0;
|
|
||||||
user.tests = [];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} else if (localStorage.userId > 0) {
|
|
||||||
user.userId = localStorage.userId;
|
|
||||||
user.username = localStorage.username;
|
|
||||||
user.password = localStorage.password;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
@ -265,8 +262,8 @@ class API {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
let userId = Number(user.userId);
|
|
||||||
xhr.open('GET', `${this.url}get_user_tests/${userId}/`);
|
xhr.open('GET', `${this.url}/get_tests/${user.userId}/${user.secret}`);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
user.tests = JSON.parse(xhr.response);
|
user.tests = JSON.parse(xhr.response);
|
||||||
@ -275,7 +272,7 @@ class API {
|
|||||||
|
|
||||||
getLeaderBoard() {
|
getLeaderBoard() {
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', `${this.url}leaderboard/`);
|
xhr.open('GET', `${this.url}/leaderboard/`);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
user.leaderboard = JSON.parse(xhr.response);
|
user.leaderboard = JSON.parse(xhr.response);
|
||||||
@ -284,7 +281,7 @@ class API {
|
|||||||
|
|
||||||
getTest() {
|
getTest() {
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', `${this.url}new_test/`);
|
xhr.open('GET', `${this.url}/new_test/`);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
xhr.onload = () =>{
|
xhr.onload = () =>{
|
||||||
const effectiveWidth = (windowWidth - 200) / 13;
|
const effectiveWidth = (windowWidth - 200) / 13;
|
||||||
|
@ -16,8 +16,9 @@
|
|||||||
class User {
|
class User {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.username = "not logged in";
|
this.username = "not logged in";
|
||||||
this.password = "there";
|
|
||||||
this.userId = 0;
|
this.userId = 0;
|
||||||
|
this.secret = "";
|
||||||
|
|
||||||
this.leaderboard;
|
this.leaderboard;
|
||||||
this.time = 15;
|
this.time = 15;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user