fix: resolve admin registration failure on fresh Docker installs (#81)

Three bugs caused 403 errors when creating the first admin on fresh
Docker deployments (Unraid, Komodo):

1. db.rs: Schema application failures were silently swallowed. The app
   started with no tables, causing all auth queries to fail. Now the
   startup aborts if schema cannot be applied, with a fallback
   statement-by-statement executor that handles dollar-quoted blocks.
   Retries increased to 5 with 2s intervals.

2. auth_application_service.rs: count_admin_users() used fragile string
   matching (contains "does not exist")) on multi-layer wrapped errors.
   count_all_users() rejected admin creation on any DB error. Both now
   allow admin creation on any error for bootstrap scenarios.

3. auth_handler.rs: Redundant 60-line handler-level admin detection
   duplicated service-layer logic and generated noisy ERROR logs on
   fresh installs. Removed entirely - service layer handles it all.

Closes #81
This commit is contained in:
Dionisio
2026-02-12 23:20:46 +01:00
parent 8123406ab9
commit e2297d276a
3 changed files with 190 additions and 121 deletions
+2 -60
View File
@@ -66,66 +66,8 @@ async fn register(
));
}
// Check if this is a fresh install
tracing::info!("New user registration detected, checking if it's a fresh install");
// Detect if we're in a fresh install with just the default admin user
match auth_service.auth_application_service.count_admin_users().await {
Ok(admin_count) => {
// If we have exactly one admin user (the default one from migrations)
if admin_count == 1 {
tracing::info!("Found one admin user - checking if it's the default admin");
// Verify it's truly a fresh install by counting all users
match auth_service.auth_application_service.count_all_users().await {
Ok(user_count) => {
// In a fresh install with only the default admin (and possibly test user)
if user_count <= 2 { // Allow for admin + test user from migrations
tracing::info!("This appears to be a fresh install with just default users");
// Check if the user is trying to create an admin user (via role field or username)
let is_admin_registration =
dto.username.to_lowercase() == "admin" ||
(dto.role.is_some() && dto.role.as_ref().unwrap().to_lowercase() == "admin");
// If we're registering an admin user in a fresh install
if is_admin_registration {
tracing::info!("Admin user registration detected in fresh install");
// Remove the default admin user and create the new customized one
match auth_service.auth_application_service.delete_default_admin().await {
Ok(_) => {
tracing::info!("Successfully deleted default admin");
// Proceed with normal registration (now that default admin is removed)
// Normal registration will continue below
},
Err(err) => {
tracing::error!("Failed to delete default admin: {}", err);
// Continue anyway - worst case we'll get an error during registration
// if there's a username conflict
}
}
} else {
// Non-admin user registration in fresh install, proceed normally
tracing::info!("Regular user registration in fresh install, proceeding normally");
}
}
},
Err(err) => {
tracing::error!("Error counting users: {}", err);
// Not critical, continue with registration
}
}
}
},
Err(err) => {
tracing::error!("Error counting admin users: {}", err);
// Not critical, continue with registration
}
}
// Try the normal registration process
// Registration logic (admin detection, fresh-install handling, duplicate
// checks) is all inside the service layer. Call it directly.
match auth_service.auth_application_service.register(dto.clone()).await {
Ok(user) => {
tracing::info!("Registration successful for user: {}", dto.username);