From a5388826281a598d33dbd331fe180f7ea18ec443 Mon Sep 17 00:00:00 2001 From: Mariano Riefolo Date: Sat, 10 Aug 2024 15:51:30 +0200 Subject: [PATCH] feat: implement database functions --- src/db/mod.rs | 160 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 2 deletions(-) diff --git a/src/db/mod.rs b/src/db/mod.rs index 41723b5..032bf1d 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,8 +1,8 @@ use argon2::{ password_hash::{rand_core::OsRng, PasswordHasher, SaltString}, - Argon2, + Argon2, PasswordHash, PasswordVerifier, }; -use rusqlite::{Connection, Result}; +use rusqlite::{Connection, Result, ToSql}; pub fn init(conn: &Connection) -> Result<()> { conn.execute( @@ -46,3 +46,159 @@ pub fn add_account(conn: &Connection, username: &str, email: &str, password: &st Ok(()) } + +pub fn get_account(conn: &Connection, id: usize, password: &str) -> Result> { + let mut stmt = conn.prepare("SELECT password FROM accounts WHERE id= ?1")?; + let mut rows = stmt.query([id])?; + if let Some(row) = rows.next()? { + let hash: String = row.get(0)?; + let argon2 = Argon2::default(); + if argon2 + .verify_password(password.as_bytes(), &PasswordHash::new(&hash).unwrap()) + .is_ok() + { + Ok(Some(id)) + } else { + Ok(None) + } + } else { + Ok(None) + } +} + +pub fn delete_account(conn: &Connection, id: usize) -> Result<()> { + conn.execute("DELETE FROM accounts WHERE id = ?1", (id,))?; + + Ok(()) +} + +pub fn change_username(conn: &Connection, id: usize, username: &str) -> Result<()> { + conn.execute( + "UPDATE accounts SET username = ?1 WHERE id = ?2", + (username, id), + )?; + + Ok(()) +} + +pub fn change_email(conn: &Connection, id: usize, email: &str) -> Result<()> { + conn.execute("UPDATE accounts SET email = ?1 WHERE id = ?2", (email, id))?; + + Ok(()) +} + +pub fn change_password(conn: &Connection, id: usize, password: &str) -> Result<()> { + let salt = SaltString::generate(&mut OsRng); + let argon2 = Argon2::default(); + let password_hash = argon2 + .hash_password(password.as_bytes(), &salt) + .unwrap() + .to_string(); + conn.execute( + "UPDATE accounts SET password = ?1 WHERE id = ?2", + (password_hash, id), + )?; + + Ok(()) +} + +pub fn get_account_id_from_username(conn: &Connection, username: &str) -> Result> { + let mut stmt = conn.prepare("SELECT id FROM accounts WHERE username = ?1")?; + let mut rows = stmt.query([username])?; + if let Some(row) = rows.next()? { + Ok(Some(row.get(0)?)) + } else { + Ok(None) + } +} + +pub fn get_account_id_from_email(conn: &Connection, email: &str) -> Result> { + let mut stmt = conn.prepare("SELECT id FROM accounts WHERE email = ?1")?; + let mut rows = stmt.query([email])?; + if let Some(row) = rows.next()? { + Ok(Some(row.get(0)?)) + } else { + Ok(None) + } +} + +pub fn get_scripts(conn: &Connection, account_id: usize) -> Result> { + let mut stmt = conn.prepare("SELECT id, name, last_edit FROM scripts WHERE account_id = ?1")?; + let mut rows = stmt.query([account_id])?; + let mut scripts = Vec::new(); + + while let Ok(row) = rows.next() { + let row = match row { + Some(row) => row, + None => break, + }; + scripts.push((row.get(0)?, row.get(1)?, row.get(2)?)); + } + + Ok(scripts) +} + +pub fn add_script( + conn: &Connection, + name: &str, + last_edit: usize, + account_id: usize, +) -> Result<()> { + let mut stmt = conn.prepare("SELECT id FROM scripts WHERE name = ?1 AND account_id = ?2")?; + let mut rows = stmt.query([&name as &dyn ToSql, &account_id as &dyn ToSql])?; + if rows.next()?.is_some() { + return Err(rusqlite::Error::InvalidQuery); + } + + conn.execute( + "INSERT INTO scripts (name, last_edit, account_id) VALUES (?1, ?2, ?3)", + (name, last_edit, account_id), + )?; + + Ok(()) +} + +pub fn script_is_owned_by(conn: &Connection, script_id: usize, account_id: usize) -> Result { + let mut stmt = conn.prepare("SELECT account_id FROM scripts WHERE id = ?1")?; + let mut rows = stmt.query([script_id])?; + if let Some(row) = rows.next()? { + let script_owner: usize = row.get(0)?; + Ok(script_owner == account_id) + } else { + Ok(false) + } +} + +pub fn get_script_id(conn: &Connection, name: &str, account_id: usize) -> Result> { + let mut stmt = conn.prepare("SELECT id FROM scripts WHERE name = ?1 AND account_id = ?2")?; + let mut rows = stmt.query([&name as &dyn ToSql, &account_id as &dyn ToSql])?; + if let Some(row) = rows.next()? { + Ok(Some(row.get(0)?)) + } else { + Ok(None) + } +} + +pub fn remove_script(conn: &Connection, script_id: usize) -> Result<()> { + conn.execute("DELETE FROM scripts WHERE id = ?1", (script_id,))?; + + Ok(()) +} + +pub fn modify_script_name(conn: &Connection, script_id: usize, name: &str) -> Result<()> { + conn.execute( + "UPDATE scripts SET name = ?1 WHERE id = ?2", + (name, script_id), + )?; + + Ok(()) +} + +pub fn update_script_last_edit(conn: &Connection, script_id: usize) -> Result<()> { + conn.execute( + "UPDATE scripts SET last_edit = CURRENT_TIMESTAMP WHERE id = ?1", + (script_id,), + )?; + + Ok(()) +}