Philipp Hofer 6b07772a18
All checks were successful
CI/CD Pipeline / test (push) Successful in 5m20s
CI/CD Pipeline / deploy (push) Successful in 3m56s
format
2025-04-21 15:14:52 +02:00

96 lines
2.7 KiB
Rust

use super::generate_random_alphanumeric;
use crate::{AppState, auth::User};
use argon2::password_hash::rand_core::OsRng;
use argon2::{Argon2, PasswordHasher, password_hash::SaltString};
use axum::Router;
use sqlx::SqlitePool;
mod web;
impl User {
pub(crate) async fn all(db: &SqlitePool) -> Vec<Self> {
sqlx::query_as::<_, Self>(
"SELECT id, name, pw, require_new_password_code FROM user ORDER BY name;",
)
.fetch_all(db)
.await
.unwrap()
}
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
sqlx::query_as!(
Self,
"SELECT id, name, pw, require_new_password_code FROM user WHERE id = ?",
id
)
.fetch_one(db)
.await
.ok()
}
async fn create(db: &SqlitePool, name: &str) -> Result<i64, String> {
let code = generate_random_alphanumeric(8);
let result = sqlx::query!(
"INSERT INTO user(name, pw, require_new_password_code) VALUES (?, 'pw-to-be-defined', ?) RETURNING id",
name,
code
)
.fetch_one(db)
.await
.map_err(|e| e.to_string())?;
Ok(result.id)
}
async fn update_name(&self, db: &SqlitePool, name: &str) {
sqlx::query!("UPDATE user SET name = ? WHERE id = ?", name, self.id)
.execute(db)
.await
.unwrap();
}
async fn new_pw(&self, db: &SqlitePool) {
let code = generate_random_alphanumeric(8);
sqlx::query!(
"UPDATE user SET pw='pw-to-be-redefined', require_new_password_code=? WHERE id = ?",
code,
self.id
)
.execute(db)
.await
.unwrap();
}
pub(crate) async fn update_pw(&self, db: &SqlitePool, pw: &str) -> Result<(), String> {
if self.require_new_password_code.is_some() {
let argon2 = Argon2::default();
let salt = SaltString::generate(&mut OsRng);
let password_hash = argon2
.hash_password(pw.as_bytes(), &salt)
.unwrap()
.to_string();
sqlx::query!(
"UPDATE user SET pw = ?, require_new_password_code=NULL WHERE id = ?",
password_hash,
self.id
)
.execute(db)
.await
.unwrap();
return Ok(());
}
Err(t!("cant_update_pw_if_already_existing").into())
}
async fn delete(&self, db: &SqlitePool) -> Result<(), String> {
sqlx::query!("DELETE FROM user WHERE id = ?", self.id)
.execute(db)
.await
.map_err(|e| e.to_string())?;
Ok(())
}
}
pub(super) fn routes() -> Router<AppState> {
web::routes()
}