From 0cfffed52e92ecb02ca7a97fd71234684777cee2 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Tue, 13 Jun 2023 19:24:03 +0530 Subject: [PATCH] feat: impl auth challenges interfaces for mariadb --- .../20230610113728_mcaptcha_challenge.sql | 20 +++++ db/db-sqlx-maria/sqlx-data.json | 55 ++++++++++++ db/db-sqlx-maria/src/lib.rs | 83 +++++++++++++++++++ db/db-sqlx-maria/src/tests.rs | 1 + 4 files changed, 159 insertions(+) create mode 100644 db/db-sqlx-maria/migrations/20230610113728_mcaptcha_challenge.sql diff --git a/db/db-sqlx-maria/migrations/20230610113728_mcaptcha_challenge.sql b/db/db-sqlx-maria/migrations/20230610113728_mcaptcha_challenge.sql new file mode 100644 index 00000000..6d5b05aa --- /dev/null +++ b/db/db-sqlx-maria/migrations/20230610113728_mcaptcha_challenge.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS mcaptcha_challenge_reason ( + id INT auto_increment, + PRIMARY KEY(id), + name VARCHAR(40) NOT NULL UNIQUE +); + +CREATE TABLE IF NOT EXISTS mcaptcha_challenge ( + id INT auto_increment, + PRIMARY KEY(id), + reason INT NOT NULL, + challenge_id varchar(40) NOT NULL UNIQUE, + received timestamp NOT NULL DEFAULT now(), + + CONSTRAINT `fk_mcaptcha_mcaptcha_challenge_reason` + FOREIGN KEY (reason) + REFERENCES mcaptcha_challenge_reason (id) + ON DELETE CASCADE + ON UPDATE CASCADE + +); diff --git a/db/db-sqlx-maria/sqlx-data.json b/db/db-sqlx-maria/sqlx-data.json index 35887e6f..11a7d6a6 100644 --- a/db/db-sqlx-maria/sqlx-data.json +++ b/db/db-sqlx-maria/sqlx-data.json @@ -1,5 +1,15 @@ { "db": "MySQL", + "04e79a67bc8c1b18eca95fc4d2602ed5dd41b6d864796f034540efec3da05fa8": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 1 + } + }, + "query": "INSERT IGNORE INTO\n mcaptcha_challenge_reason (name)\n VALUES (?)" + }, "1367dceb151a766a901b5dd771d0b75d0bc61d2fef17a94a90c8ffa0065e2c44": { "describe": { "columns": [ @@ -199,6 +209,16 @@ }, "query": "UPDATE mcaptcha_users set name = ?\n WHERE name = ?" }, + "6a31a6745dc005449f742b516979f195674848222b16c72c48da553a379a4e6f": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 3 + } + }, + "query": "INSERT INTO mcaptcha_challenge (challenge_id, received, reason)\n VALUES (?, ?, (SELECT id FROM mcaptcha_challenge_reason WHERE name = ?));\n " + }, "6d1b6e5e58ca2ba285cab7b050bbdc43de1f3e46cf7d420bc95c124a1c7c9d1f": { "describe": { "columns": [], @@ -332,6 +352,31 @@ }, "query": "insert into mcaptcha_users \n (name , password, email, secret) values (?, ?, ?, ?)" }, + "900a1f8c30fed90f8e56f88c4d0a2e81a7ea6af24d90c3a76764ee411b01af73": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": { + "char_set": 63, + "flags": { + "bits": 515 + }, + "max_size": 11, + "type": "Long" + } + } + ], + "nullable": [ + false + ], + "parameters": { + "Right": 2 + } + }, + "query": "SELECT id\n FROM mcaptcha_challenge\n WHERE\n challenge_id = ?\n AND reason = (SELECT id FROM mcaptcha_challenge_reason WHERE name = ?);" + }, "9c435148ed5655e79dd1e73e3566ce23b7c6d38edcedbb988c95813c5da893ed": { "describe": { "columns": [ @@ -873,6 +918,16 @@ }, "query": "SELECT name, password FROM mcaptcha_users WHERE email = ?" }, + "f47c05c0a7da41a2176f08a44c6c945dabb84558a4d09369b6108bfce8b9d2bf": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 2 + } + }, + "query": "DELETE\n FROM mcaptcha_challenge\n WHERE\n challenge_id = ?\n AND reason = (SELECT id FROM mcaptcha_challenge_reason WHERE name = ?);" + }, "fc717ff0827ccfaa1cc61a71cc7f71c348ebb03d35895c54b011c03121ad2385": { "describe": { "columns": [], diff --git a/db/db-sqlx-maria/src/lib.rs b/db/db-sqlx-maria/src/lib.rs index ed6e8cf5..f6843628 100644 --- a/db/db-sqlx-maria/src/lib.rs +++ b/db/db-sqlx-maria/src/lib.rs @@ -95,6 +95,22 @@ impl Migrate for Database { .run(&self.pool) .await .map_err(|e| DBError::DBError(Box::new(e)))?; + + for reason in [ + ChallengeReason::EmailVerification, + ChallengeReason::PasswordReset, + ] { + sqlx::query!( + "INSERT IGNORE INTO + mcaptcha_challenge_reason (name) + VALUES (?)", + reason.to_str() + ) + .execute(&self.pool) + .await + .map_err(|e| DBError::DBError(Box::new(e)))?; + } + Ok(()) } } @@ -895,6 +911,73 @@ impl MCDatabase for Database { Ok(Date::dates_to_unix(records)) } + + /// Record challenge in database + async fn new_challenge(&self, challenge: &mut Challenge) -> DBResult<()> { + let now = now_unix_time_stamp(); + loop { + let res = sqlx::query!( + "INSERT INTO mcaptcha_challenge (challenge_id, received, reason) + VALUES (?, ?, (SELECT id FROM mcaptcha_challenge_reason WHERE name = ?)); + ", + &challenge.challenge.to_string(), + now, + challenge.reason.to_str() + ) + .execute(&self.pool) + .await; + if let Err(Error::Database(err)) = res { + use std::borrow::Cow; + + if err.code() == Some(Cow::from("23505")) { + let msg = err.message(); + if msg.contains("for key 'challenge_id'") { + challenge.new_id(); + continue; + } + } + } + break; + } + Ok(()) + } + + /// Record challenge in database + async fn fetch_challenge(&self, challenge: &Challenge) -> DBResult { + struct C { + id: i32, + } + sqlx::query_as!( + C, + "SELECT id + FROM mcaptcha_challenge + WHERE + challenge_id = ? + AND reason = (SELECT id FROM mcaptcha_challenge_reason WHERE name = ?);", + &challenge.challenge.to_string(), + challenge.reason.to_str(), + ) + .fetch_one(&self.pool) + .await + .map_err(map_register_err)?; + Ok(challenge.clone()) + } + + /// Delete a challenge from database + async fn delete_challenge(&self, challenge: &Challenge) -> DBResult<()> { + let _ = sqlx::query!( + "DELETE + FROM mcaptcha_challenge + WHERE + challenge_id = ? + AND reason = (SELECT id FROM mcaptcha_challenge_reason WHERE name = ?);", + &challenge.challenge.to_string(), + challenge.reason.to_str(), + ) + .execute(&self.pool) + .await; + Ok(()) + } } #[derive(Clone)] diff --git a/db/db-sqlx-maria/src/tests.rs b/db/db-sqlx-maria/src/tests.rs index 62fe290f..4b9ea63e 100644 --- a/db/db-sqlx-maria/src/tests.rs +++ b/db/db-sqlx-maria/src/tests.rs @@ -89,4 +89,5 @@ async fn everyting_works() { description: CAPTCHA_DESCRIPTION, }; database_works(&db, &p, &c, &LEVELS, &TRAFFIC_PATTERN, &ADD_NOTIFICATION).await; + challenges_works(&db).await; }