Compare commits
3 commits
00979cacff
...
65947193b9
Author | SHA1 | Date | |
---|---|---|---|
|
65947193b9 | ||
|
cdf0b7bd29 | ||
|
8bb227f48e |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
user_db.db3
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub struct Account {
|
||||||
creation_time: DateTime<Utc>,
|
creation_time: DateTime<Utc>,
|
||||||
// Donator role
|
// Donator role
|
||||||
premium: bool,
|
premium: bool,
|
||||||
|
random: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
|
@ -17,12 +18,14 @@ impl Account {
|
||||||
user_id: UserID,
|
user_id: UserID,
|
||||||
creation_time: DateTime<Utc>,
|
creation_time: DateTime<Utc>,
|
||||||
premium: bool,
|
premium: bool,
|
||||||
|
random: i64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
username,
|
username,
|
||||||
user_id,
|
user_id,
|
||||||
creation_time,
|
creation_time,
|
||||||
premium,
|
premium,
|
||||||
|
random,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,4 +36,8 @@ impl Account {
|
||||||
pub fn creation_time(&self) -> DateTime<Utc> {
|
pub fn creation_time(&self) -> DateTime<Utc> {
|
||||||
self.creation_time
|
self.creation_time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> UserID {
|
||||||
|
self.user_id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,23 @@ pub enum UserCreationError {
|
||||||
DBError(rusqlite::Error),
|
DBError(rusqlite::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum HandleDBError {
|
||||||
|
HandleAlreadyExists,
|
||||||
|
DBError(rusqlite::Error),
|
||||||
|
}
|
||||||
|
|
||||||
impl From<rusqlite::Error> for UserCreationError {
|
impl From<rusqlite::Error> for UserCreationError {
|
||||||
fn from(value: rusqlite::Error) -> Self {
|
fn from(value: rusqlite::Error) -> Self {
|
||||||
Self::DBError(value)
|
Self::DBError(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<rusqlite::Error> for HandleDBError {
|
||||||
|
fn from(value: rusqlite::Error) -> Self {
|
||||||
|
Self::DBError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::error::Error for UserCreationError {}
|
impl std::error::Error for UserCreationError {}
|
||||||
impl Display for UserCreationError {
|
impl Display for UserCreationError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -35,6 +47,20 @@ impl Display for UserCreationError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for HandleDBError {}
|
||||||
|
impl Display for HandleDBError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
HandleDBError::HandleAlreadyExists => {
|
||||||
|
write!(f, "Handle already exists.")
|
||||||
|
}
|
||||||
|
HandleDBError::DBError(e) => {
|
||||||
|
write!(f, "DBError: {}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let conn = Connection::open("user_db.db3").unwrap();
|
let conn = Connection::open("user_db.db3").unwrap();
|
||||||
|
@ -44,7 +70,7 @@ impl Database {
|
||||||
// use the existing table instead
|
// use the existing table instead
|
||||||
// NOTE: Look at the other possible errors here
|
// NOTE: Look at the other possible errors here
|
||||||
let _val = conn.execute(
|
let _val = conn.execute(
|
||||||
"CREATE TABLE users (
|
"CREATE TABLE user (
|
||||||
user_id INTEGER PRIMARY KEY,
|
user_id INTEGER PRIMARY KEY,
|
||||||
username TINYTEXT NOT NULL,
|
username TINYTEXT NOT NULL,
|
||||||
password_hash TINYTEXT NOT NULL,
|
password_hash TINYTEXT NOT NULL,
|
||||||
|
@ -55,19 +81,30 @@ impl Database {
|
||||||
(),
|
(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let _val = conn.execute(
|
||||||
|
"CREATE TABLE handle (
|
||||||
|
handle_id INTEGER PRIMARY KEY,
|
||||||
|
handle_val BIGINT UNSIGNED NOT NULL
|
||||||
|
CONSTRAINT fk_usr_handle FOREIGN KEY (user)
|
||||||
|
REFERENCES person (id)
|
||||||
|
)",
|
||||||
|
(),
|
||||||
|
);
|
||||||
|
|
||||||
Self { conn }
|
Self { conn }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_user(&self, username: &str) -> Result<Account> {
|
pub fn get_user(&self, username: &str) -> Result<Account> {
|
||||||
let (user_id, creation_time, premium): (UserID, DateTime<Utc>, bool) =
|
let (user_id, creation_time, premium, random): (UserID, DateTime<Utc>, bool, i64) =
|
||||||
self.conn.query_row(
|
self.conn.query_row(
|
||||||
"SELECT username, user_id, creation_time, is_premium FROM users WHERE username=?1",
|
"SELECT username, user_id, creation_time, is_premium, random_value FROM user WHERE username=?1",
|
||||||
[username],
|
[username],
|
||||||
|row| {
|
|row| {
|
||||||
let user_id = row.get(1)?;
|
let user_id = row.get(1)?;
|
||||||
let creation_time = row.get(2)?;
|
let creation_time = row.get(2)?;
|
||||||
let premium = row.get(3)?;
|
let premium = row.get(3)?;
|
||||||
Ok((user_id, creation_time, premium))
|
let random = row.get(4)?;
|
||||||
|
Ok((user_id, creation_time, premium, random))
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
Ok(Account::new(
|
Ok(Account::new(
|
||||||
|
@ -75,6 +112,7 @@ impl Database {
|
||||||
user_id,
|
user_id,
|
||||||
creation_time,
|
creation_time,
|
||||||
premium,
|
premium,
|
||||||
|
random,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +124,7 @@ impl Database {
|
||||||
let num = rand::random::<u64>();
|
let num = rand::random::<u64>();
|
||||||
let password_hash = self.hash_password(password, creation_time, num);
|
let password_hash = self.hash_password(password, creation_time, num);
|
||||||
self.conn.execute(
|
self.conn.execute(
|
||||||
"INSERT INTO users (
|
"INSERT INTO user (
|
||||||
username,
|
username,
|
||||||
password_hash,
|
password_hash,
|
||||||
creation_time,
|
creation_time,
|
||||||
|
@ -108,7 +146,7 @@ impl Database {
|
||||||
|
|
||||||
pub fn check_login(&self, username: &str, password: &str) -> bool {
|
pub fn check_login(&self, username: &str, password: &str) -> bool {
|
||||||
let result = self.conn.query_row(
|
let result = self.conn.query_row(
|
||||||
"SELECT creation_time, random_value, username FROM users WHERE username=?1",
|
"SELECT creation_time, random_value, username FROM user WHERE username=?1",
|
||||||
[username],
|
[username],
|
||||||
|row| {
|
|row| {
|
||||||
let creation_time = row.get(0)?;
|
let creation_time = row.get(0)?;
|
||||||
|
@ -121,7 +159,7 @@ impl Database {
|
||||||
}
|
}
|
||||||
let (creation_time, num) = result.unwrap();
|
let (creation_time, num) = result.unwrap();
|
||||||
let saved_password_hash: Result<Rc<str>> = self.conn.query_row(
|
let saved_password_hash: Result<Rc<str>> = self.conn.query_row(
|
||||||
"SELECT password_hash, username FROM users WHERE username=?1",
|
"SELECT password_hash, username FROM user WHERE username=?1",
|
||||||
[username],
|
[username],
|
||||||
|row| row.get::<usize, Rc<str>>(0),
|
|row| row.get::<usize, Rc<str>>(0),
|
||||||
);
|
);
|
||||||
|
@ -131,4 +169,28 @@ impl Database {
|
||||||
|
|
||||||
*saved_password_hash.unwrap() == self.hash_password(password, creation_time, num)
|
*saved_password_hash.unwrap() == self.hash_password(password, creation_time, num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HANDLE FUNCTIONS --------------------------------------------------
|
||||||
|
pub fn add_handle_to_db(&self, user: &Account, handle: u64) -> Result<(), HandleDBError> {
|
||||||
|
let saved_handle = self
|
||||||
|
.conn
|
||||||
|
.query_row(
|
||||||
|
"SELECT handle_val FROM handle WHERE handle_val=?1",
|
||||||
|
[handle],
|
||||||
|
|row| row.get::<usize, u64>(0),
|
||||||
|
)
|
||||||
|
.is_ok();
|
||||||
|
if saved_handle {
|
||||||
|
return Err(HandleDBError::HandleAlreadyExists);
|
||||||
|
}
|
||||||
|
self.conn.execute(
|
||||||
|
"INSERT INTO handle (
|
||||||
|
handle_val
|
||||||
|
fk_usr_handle
|
||||||
|
)
|
||||||
|
VALUES (?1, ?2)",
|
||||||
|
(handle, user.id()),
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/handle.rs
Normal file
26
src/handle.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use crate::{
|
||||||
|
account::Account,
|
||||||
|
database::{Database, HandleDBError},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Handle(u64);
|
||||||
|
|
||||||
|
impl Handle {
|
||||||
|
pub fn new(user: &Account, db: Database) -> Result<Handle, HandleDBError> {
|
||||||
|
loop {
|
||||||
|
let num = rand::random::<u64>();
|
||||||
|
let res = db.add_handle_to_db(user, num);
|
||||||
|
match res {
|
||||||
|
Ok(_) => return Ok(Handle(num)),
|
||||||
|
Err(x) => match x {
|
||||||
|
HandleDBError::HandleAlreadyExists => continue,
|
||||||
|
HandleDBError::DBError(e) => return Err(HandleDBError::DBError(e)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -2,7 +2,7 @@ use routes::get_routes;
|
||||||
|
|
||||||
mod account;
|
mod account;
|
||||||
mod database;
|
mod database;
|
||||||
mod handlers;
|
mod handle;
|
||||||
mod routes;
|
mod routes;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
|
||||||
use crate::database::Database;
|
use crate::{database::Database, handle::Handle};
|
||||||
|
|
||||||
pub fn get_routes() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
pub fn get_routes() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||||
create_user().or(auth_user()).or(get_user())
|
create_user().or(auth_user()).or(get_user())
|
||||||
|
@ -80,6 +80,7 @@ struct UserAuthRequest {
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
struct UserAuthResponse {
|
struct UserAuthResponse {
|
||||||
success: bool,
|
success: bool,
|
||||||
|
handle: Option<u64>,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
fn auth_user() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
fn auth_user() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||||
|
@ -89,14 +90,17 @@ fn auth_user() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejectio
|
||||||
.map(|body: UserAuthRequest| {
|
.map(|body: UserAuthRequest| {
|
||||||
let db = Database::new();
|
let db = Database::new();
|
||||||
let reply = if db.check_login(&body.username, &body.password) {
|
let reply = if db.check_login(&body.username, &body.password) {
|
||||||
|
let handle = Handle::new(&(db.get_user(&body.username).unwrap()), db).unwrap();
|
||||||
UserAuthResponse {
|
UserAuthResponse {
|
||||||
success: true,
|
success: true,
|
||||||
message: "".to_string(),
|
message: "".to_string(),
|
||||||
|
handle: Some(handle.get()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UserAuthResponse {
|
UserAuthResponse {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Username or Password is invalid".to_string(),
|
message: "Username or Password is invalid".to_string(),
|
||||||
|
handle: None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
warp::reply::json(&reply)
|
warp::reply::json(&reply)
|
||||||
|
|
BIN
user_db.db3
BIN
user_db.db3
Binary file not shown.
Loading…
Reference in a new issue