hexagonal refactor

This commit is contained in:
2026-08-01 18:27:22 -04:00
parent 6979cabe8b
commit 188ce23e67
13 changed files with 3590 additions and 1795 deletions
+35 -9
View File
@@ -1,9 +1,11 @@
use std::path::Path;
use std::sync::Arc;
use serde::Deserialize;
use tracing::{info, warn};
use crate::db::Database;
use crate::ports::{PasswordHasher, UserRepository};
use crate::sqlite::SqliteDatabase;
#[derive(Debug, Deserialize)]
pub struct SeedConfig {
@@ -21,7 +23,12 @@ pub struct SeedUser {
/// Reads the seed config file and creates the configured default user if the
/// database has no users yet. The file is optional; if it does not exist (or
/// cannot be parsed) seeding is skipped.
pub async fn seed_if_needed(db: &Database, path: &Path) {
pub async fn seed_if_needed(
db: &SqliteDatabase,
users: &Arc<dyn UserRepository>,
hasher: &Arc<dyn PasswordHasher>,
path: &Path,
) {
let Ok(contents) = std::fs::read_to_string(path) else {
return;
};
@@ -39,23 +46,42 @@ pub async fn seed_if_needed(db: &Database, path: &Path) {
warn!("seed user requires a non-empty email; skipping");
return;
}
if db.has_users().await.unwrap_or(true) {
let users_for_check = users.clone();
let has_users = match db
.run(move |txn| Box::pin(async move { users_for_check.has_users(txn).await }))
.await
{
Ok(has_users) => has_users,
Err(error) => {
warn!(%error, "could not check for existing users; skipping seed");
return;
}
};
if has_users {
info!("database already has users; skipping seed");
return;
}
let password_hash = match crate::hash_password(&user.password) {
let password_hash = match hasher.hash(&user.password) {
Ok(hash) => hash,
Err(error) => {
warn!(%error, "could not hash seed password; skipping");
return;
}
};
let users_for_create = users.clone();
match db
.create_user(
user.email.trim().to_lowercase(),
user.display_name.trim().to_owned(),
password_hash,
)
.run(move |txn| {
Box::pin(async move {
users_for_create
.create_user(
txn,
user.email.trim().to_lowercase(),
user.display_name.trim().to_owned(),
password_hash,
)
.await
})
})
.await
{
Ok(user) => info!(id = user.id, email = %user.email, "seeded default user"),