feat: admin can create users manually + disable registration (#85)

Backend:
- POST /api/admin/users — admin-only user creation endpoint
  - username & password required, email optional (auto-generated placeholder)
  - role, quota_bytes, active all configurable
  - creates personal folder automatically
- PUT /api/admin/users/{id}/password — admin password reset
- GET/PUT /api/admin/settings/registration — toggle public registration
  - Supports env var OXICLOUD_DISABLE_REGISTRATION override
  - Blocks POST /api/auth/register when disabled
- AdminCreateUserDto, AdminResetPasswordDto added to settings DTOs
- registration_enabled field added to DashboardStatsDto

Frontend (admin.html):
- 'Create User' button in Users tab with full modal form
  (username, password, email, role, quota)
- 'Reset Password' button per user in actions column
- 'Allow public self-registration' toggle in Dashboard > System
  with warning banner when disabled

Closes #85
This commit is contained in:
Dionisio
2026-02-13 16:46:59 +01:00
parent 12ceea9e54
commit 1be3e4230a
7 changed files with 473 additions and 2 deletions
@@ -267,4 +267,37 @@ impl AdminSettingsService {
provider_name_suggestion: suggestion,
})
}
// ========================================================================
// Registration Control
// ========================================================================
/// Check if public self-registration is enabled.
/// Priority: env var `OXICLOUD_DISABLE_REGISTRATION` > DB setting > default (true).
pub async fn get_registration_enabled(&self) -> bool {
// Env var override takes priority
if let Ok(val) = std::env::var("OXICLOUD_DISABLE_REGISTRATION") {
return !matches!(val.to_lowercase().as_str(), "true" | "1" | "yes");
}
// Check DB setting
match self.settings_repo.get("registration_enabled").await {
Ok(Some(val)) => val == "true",
_ => true, // default: enabled
}
}
/// Enable or disable public self-registration.
pub async fn set_registration_enabled(
&self,
enabled: bool,
updated_by: &str,
) -> Result<(), DomainError> {
self.settings_repo.set(
"registration_enabled",
if enabled { "true" } else { "false" },
"general",
false,
Some(updated_by),
).await
}
}