From e3ea93f4aef075c9df8f509afae6ae578aabc7e7 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Wed, 16 Aug 2023 20:05:19 +0200 Subject: [PATCH] feat(tokens): implemented token validation --- src/api/mod.rs | 26 +++++++++++----------- src/tokens/mod.rs | 56 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/api/mod.rs b/src/api/mod.rs index 360d7da..f4a7ed2 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -15,13 +15,13 @@ pub async fn start(port: u16, pool: MySqlPool) -> Result<()> { sqlx::query!( r#" CREATE TABLE IF NOT EXISTS Accounts ( - id INT NOT NULL AUTO_INCREMENT, - username VARCHAR(32) NOT NULL, - email TEXT NOT NULL, - salt VARCHAR(22) NOT NULL, - password VARCHAR(96) NOT NULL, - joined DATETIME NOT NULL, - verified BOOLEAN NOT NULL, + id INT8 UNSIGNED NOT NULL AUTO_INCREMENT, + username VARCHAR(32) NOT NULL, + email TEXT NOT NULL, + salt VARCHAR(22) NOT NULL, + password VARCHAR(96) NOT NULL, + joined DATETIME NOT NULL, + verified BOOLEAN NOT NULL, PRIMARY KEY(id) ); "# @@ -32,9 +32,9 @@ pub async fn start(port: u16, pool: MySqlPool) -> Result<()> { sqlx::query!( r#" CREATE TABLE IF NOT EXISTS AuthTokens ( - token VARCHAR(32) NOT NULL, - account INT NOT NULL, - expire DATETIME NOT NULL + token VARCHAR(32) NOT NULL, + account INT8 UNSIGNED NOT NULL, + expire DATETIME NOT NULL ); "# ) @@ -44,9 +44,9 @@ pub async fn start(port: u16, pool: MySqlPool) -> Result<()> { sqlx::query!( r#" CREATE TABLE IF NOT EXISTS VerificationTokens ( - token VARCHAR(32) NOT NULL, - account INT NOT NULL, - expire DATETIME NOT NULL + token VARCHAR(32) NOT NULL, + account INT8 UNSIGNED NOT NULL, + expire DATETIME NOT NULL ); "# ) diff --git a/src/tokens/mod.rs b/src/tokens/mod.rs index 4b1b8cc..f574313 100644 --- a/src/tokens/mod.rs +++ b/src/tokens/mod.rs @@ -1,10 +1,11 @@ use anyhow::{Error, Result}; use sqlx::{mysql::MySqlPool, types::chrono as sqlx_chrono}; +#[derive(Debug)] pub struct AuthToken { token: String, - account: i64, - expire: sqlx_chrono::DateTime, + account: u64, + expire: sqlx_chrono::NaiveDateTime, } impl AuthToken { @@ -13,7 +14,10 @@ impl AuthToken { account_id: usize, lifetime: chrono::Duration, ) -> Result { - let expire = match sqlx_chrono::Utc::now().checked_add_signed(lifetime) { + let expire = match sqlx_chrono::Utc::now() + .naive_utc() + .checked_add_signed(lifetime) + { Some(e) => e, None => { return Err(Error::msg( @@ -24,7 +28,7 @@ impl AuthToken { let token = Self { token: uuid::Uuid::new_v4().simple().to_string(), - account: account_id as i64, + account: account_id as u64, expire, }; @@ -41,12 +45,29 @@ impl AuthToken { Ok(token) } + + pub async fn check(pool: &MySqlPool, token: String) -> Result> { + let query_result = sqlx::query!(r#"SELECT * FROM AuthTokens WHERE token = ?;"#, token) + .fetch_one(pool) + .await; + + match query_result { + Ok(row) => Ok(Some(Self { + token: row.token, + account: row.account, + expire: row.expire, + })), + Err(sqlx::Error::RowNotFound) => Ok(None), + Err(e) => Err(Error::new(e)), + } + } } +#[derive(Debug)] pub struct VerificationToken { token: String, - account: i64, - expire: sqlx_chrono::DateTime, + account: u64, + expire: sqlx_chrono::NaiveDateTime, } impl VerificationToken { @@ -55,7 +76,10 @@ impl VerificationToken { account_id: usize, lifetime: chrono::Duration, ) -> Result { - let expire = match sqlx_chrono::Utc::now().checked_add_signed(lifetime) { + let expire = match sqlx_chrono::Utc::now() + .naive_utc() + .checked_add_signed(lifetime) + { Some(e) => e, None => { return Err(Error::msg( @@ -66,7 +90,7 @@ impl VerificationToken { let token = Self { token: uuid::Uuid::new_v4().simple().to_string(), - account: account_id as i64, + account: account_id as u64, expire, }; @@ -83,4 +107,20 @@ impl VerificationToken { Ok(token) } + + pub async fn check(pool: &MySqlPool, token: String) -> Result> { + let query_result = sqlx::query!(r#"SELECT * FROM VerificationTokens WHERE token = ?;"#, token) + .fetch_one(pool) + .await; + + match query_result { + Ok(row) => Ok(Some(Self { + token: row.token, + account: row.account, + expire: row.expire, + })), + Err(sqlx::Error::RowNotFound) => Ok(None), + Err(e) => Err(Error::new(e)), + } + } }