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::{
|
||||
Database,
|
||||
LeaderBoardTest
|
||||
|
@ -13,6 +13,7 @@
|
||||
use sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
|
||||
use rocket::serde::Serialize;
|
||||
|
||||
/// Contains the database connection pool
|
||||
pub struct Database(SqlitePool);
|
||||
|
||||
/// 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
|
||||
/// 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!("
|
||||
INSERT INTO Users (username, password)
|
||||
VALUES (?1, ?2)",
|
||||
username, password
|
||||
INSERT INTO Users (username, password, secret)
|
||||
VALUES (?1, ?2, ?3)",
|
||||
username, password, secret
|
||||
).execute(&self.0).await?;
|
||||
|
||||
Ok(())
|
||||
@ -87,12 +88,12 @@ impl Database {
|
||||
let user = sqlx::query!("
|
||||
SELECT user_id, secret
|
||||
FROM Users
|
||||
WHERE username=:username AND password=:password",
|
||||
WHERE username=? AND password=?",
|
||||
username, password
|
||||
).fetch_all(&self.0).await?;
|
||||
).fetch_one(&self.0).await?;
|
||||
|
||||
let user_id = user[0].user_id.unwrap() as u32;
|
||||
let secret = user[0].secret.clone();
|
||||
let user_id = user.user_id.unwrap() as u32;
|
||||
let secret = user.secret.clone();
|
||||
|
||||
Ok(Some((user_id, secret)))
|
||||
}
|
||||
@ -104,10 +105,12 @@ impl Database {
|
||||
SELECT test_type, test_length, test_time, test_seed, quote_id, wpm, accuracy
|
||||
FROM tests
|
||||
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
|
||||
).fetch_all(&self.0).await?;
|
||||
|
||||
println!("{}", tests.len());
|
||||
|
||||
let user_tests = tests.iter()
|
||||
.map(|test| Test {
|
||||
test_type: test.test_type.clone(),
|
||||
|
@ -3,6 +3,8 @@ use rocket::{
|
||||
State
|
||||
};
|
||||
|
||||
use rand::{ distributions::Alphanumeric, Rng };
|
||||
|
||||
use crate::typing::sql::{ Database, Test };
|
||||
|
||||
/// Struct representing the user
|
||||
@ -18,9 +20,15 @@ pub struct User<'r> {
|
||||
/// Acessible from http://url/api/create_user
|
||||
#[post("/create_user", data = "<user>")]
|
||||
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}"); }
|
||||
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.
|
||||
/// Accessible from http://url/api/login
|
||||
#[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 {
|
||||
Err(why) => {
|
||||
println!("A database error occured during login for {username}, {why}");
|
||||
None
|
||||
Json(None)
|
||||
}
|
||||
Ok(user) => {
|
||||
match user {
|
||||
None => None,
|
||||
Some(user) => { Some(Json(LoginResponse { user_id: user.0, secret: user.1 })) }
|
||||
None => Json(None),
|
||||
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)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
struct LoginResponse {
|
||||
pub struct LoginResponse {
|
||||
user_id: u32,
|
||||
secret: String,
|
||||
}
|
||||
|
@ -16,7 +16,8 @@
|
||||
class API {
|
||||
|
||||
constructor() {
|
||||
this.url = "https://arlofilley.com/api/";
|
||||
// this.url = "https://arlofilley.com/api/";
|
||||
this.url = "../api";
|
||||
// this is the url of the server
|
||||
// this may have to change later on
|
||||
}
|
||||
@ -33,16 +34,7 @@ class API {
|
||||
* @param {int} accuracy
|
||||
* @param {int} userId
|
||||
*/
|
||||
postTest(
|
||||
pTestType,
|
||||
pTestLength,
|
||||
pTestTime,
|
||||
pTestSeed,
|
||||
pQuoteId,
|
||||
pWpm,
|
||||
pAccuracy,
|
||||
pUserId
|
||||
) {
|
||||
postTest(pTestType, pTestLength, pTestTime, pTestSeed, pQuoteId, pWpm, pAccuracy, pUserId) {
|
||||
const data = {
|
||||
'test_type': pTestType,
|
||||
'test_length': pTestLength,
|
||||
@ -57,7 +49,7 @@ class API {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(
|
||||
"POST",
|
||||
this.url+"post_test"
|
||||
`${this.url}/post_test/`
|
||||
);
|
||||
|
||||
xhr.send(
|
||||
@ -174,16 +166,7 @@ class API {
|
||||
|
||||
// there will be other tests here in later iterations but for now these tests should suffice
|
||||
|
||||
this.postTest(
|
||||
testType,
|
||||
testLength,
|
||||
testTime,
|
||||
testSeed,
|
||||
quoteId,
|
||||
wpm,
|
||||
accuracy,
|
||||
userId
|
||||
);
|
||||
this.postTest(testType, testLength, testTime, testSeed, quoteId, wpm, accuracy, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,10 +177,7 @@ class API {
|
||||
* @param {String} password
|
||||
* @returns
|
||||
*/
|
||||
createUser(
|
||||
username,
|
||||
password
|
||||
) {
|
||||
createUser( username, password ) {
|
||||
console.log( username, password );
|
||||
const user = {
|
||||
username: username,
|
||||
@ -205,48 +185,65 @@ class API {
|
||||
};
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(
|
||||
"POST",
|
||||
`${this.url}create_user/`
|
||||
);
|
||||
xhr.open( "POST", `${this.url}/create_user/` );
|
||||
|
||||
xhr.send(
|
||||
JSON.stringify(user)
|
||||
);
|
||||
xhr.send( JSON.stringify(user) );
|
||||
|
||||
xhr.onload = () => {
|
||||
if (xhr.status === 500) {
|
||||
alert("Sorry, looks like your username isn't unique");
|
||||
console.error("Sorry, looks like your username isn't unique")
|
||||
} else {
|
||||
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();
|
||||
xhr.open('GET', `${this.url}login/${pUsername}/${pPassword}`);
|
||||
xhr.open('GET', `${this.url}/login/${pUsername}/${pPassword}`);
|
||||
xhr.send();
|
||||
xhr.onload = () => {
|
||||
user.userId = Number(xhr.response);
|
||||
if (user.userId > 0) {
|
||||
let response = JSON.parse(xhr.response);
|
||||
|
||||
// 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.secret = response.secret;
|
||||
|
||||
localStorage.setItem("userId", user.userId);
|
||||
localStorage.setItem("username", pUsername);
|
||||
localStorage.setItem("password", pPassword);
|
||||
} else {
|
||||
user.username = "no one";
|
||||
user.password = "none";
|
||||
user.userId = 0;
|
||||
user.tests = [];
|
||||
}
|
||||
localStorage.setItem("secret", user.secret);
|
||||
};
|
||||
} else if (localStorage.userId > 0) {
|
||||
user.userId = localStorage.userId;
|
||||
user.username = localStorage.username;
|
||||
user.password = localStorage.password;
|
||||
}
|
||||
}
|
||||
|
||||
logout() {
|
||||
@ -265,8 +262,8 @@ class API {
|
||||
return;
|
||||
}
|
||||
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.onload = () => {
|
||||
user.tests = JSON.parse(xhr.response);
|
||||
@ -275,7 +272,7 @@ class API {
|
||||
|
||||
getLeaderBoard() {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', `${this.url}leaderboard/`);
|
||||
xhr.open('GET', `${this.url}/leaderboard/`);
|
||||
xhr.send();
|
||||
xhr.onload = () => {
|
||||
user.leaderboard = JSON.parse(xhr.response);
|
||||
@ -284,7 +281,7 @@ class API {
|
||||
|
||||
getTest() {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', `${this.url}new_test/`);
|
||||
xhr.open('GET', `${this.url}/new_test/`);
|
||||
xhr.send();
|
||||
xhr.onload = () =>{
|
||||
const effectiveWidth = (windowWidth - 200) / 13;
|
||||
|
@ -16,8 +16,9 @@
|
||||
class User {
|
||||
constructor() {
|
||||
this.username = "not logged in";
|
||||
this.password = "there";
|
||||
this.userId = 0;
|
||||
this.secret = "";
|
||||
|
||||
this.leaderboard;
|
||||
this.time = 15;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user