AuthorBuddy/Components/Pages/FirstRunSetup.razor
2026-07-04 10:32:35 +02:00

128 lines
4.5 KiB
Text

@page "/first-run-setup"
@inject IAuthService AuthService
@inject ISettingsService SettingsService
@inject NavigationManager Navigation
@inject ILocalizationService Loc
@rendermode InteractiveServer
<PageTitle>Ersteinrichtung</PageTitle>
<div class="auth-page">
<div class="auth-card">
<div class="auth-logo">
<img src="/Assets/logo.jpg" alt="Author Buddy" />
</div>
<h2>Ersteinrichtung</h2>
<p>Willkommen bei Author Buddy! Richten Sie Ihren Administrator-Account ein.</p>
@if (!_setupComplete)
{
<div class="form-group">
<label for="adminUsername">Admin-Benutzername</label>
<input id="adminUsername" @bind="_username" disabled="@_isBusy" />
</div>
<button @onclick="GeneratePassword" disabled="@_generateDisabled">Passwort generieren</button>
@if (!string.IsNullOrEmpty(_generatedPassword))
{
<div class="auth-error" style="margin-top: 1rem; padding: 1rem; border: 2px solid red; background: #fff0f0; color: #c00; border-radius: 8px;">
<strong style="font-size: 1.2rem;">Sicherheitswarnung!</strong>
<p>Dieses Passwort wird nur <strong>einmalig</strong> angezeigt. Speichern Sie es sofort sicher ab.</p>
<div style="font-family: monospace; font-size: 1.4rem; text-align: center; padding: 0.5rem; background: white; border: 1px solid #c00; margin: 0.5rem 0; letter-spacing: 2px;">
@_generatedPassword
</div>
<p style="font-size: 0.85rem; color: #888;">Nach dem Klick auf "Admin erstellen" wird das Passwort nicht mehr angezeigt.</p>
</div>
<div class="form-group">
<label for="adminPassword">Passwort eingeben (zur Bestätigung)</label>
<input id="adminPassword" type="password" @bind="_password" />
</div>
<button @onclick="CreateAdmin" disabled="@_createAdminDisabled">Admin erstellen</button>
}
}
else
{
<div class="auth-success" style="margin-top: 1rem; padding: 1rem; border: 2px solid green; background: #f0fff0; color: #080; border-radius: 8px;">
<strong>Admin-Account erfolgreich erstellt!</strong>
<p>Sie werden zum Login weitergeleitet...</p>
</div>
}
@if (!string.IsNullOrEmpty(_errorMessage))
{
<div class="auth-error">@_errorMessage</div>
}
</div>
</div>
@code {
private string _username = "admin";
private string? _generatedPassword;
private string _password = string.Empty;
private string _errorMessage = string.Empty;
private bool _isBusy;
private bool _setupComplete;
private bool _generateDisabled => _isBusy || string.IsNullOrWhiteSpace(_username);
private bool _createAdminDisabled => _isBusy || _password != _generatedPassword;
protected override async Task OnInitializedAsync()
{
var users = await SettingsService.GetUsersAsync();
if (users.Count > 0)
{
Navigation.NavigateTo("/login");
}
}
private void GeneratePassword()
{
using var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
var bytes = new byte[12];
rng.GetBytes(bytes);
_generatedPassword = Convert.ToBase64String(bytes).TrimEnd('=').Replace('+', 'X').Replace('/', 'Y');
_password = string.Empty;
_errorMessage = string.Empty;
}
private async Task CreateAdmin()
{
if (string.IsNullOrWhiteSpace(_username) || string.IsNullOrWhiteSpace(_password))
{
_errorMessage = "Benutzername und Passwort dürfen nicht leer sein.";
return;
}
_isBusy = true;
_errorMessage = string.Empty;
try
{
var result = await AuthService.RegisterAsync(_username, _password);
if (result)
{
_generatedPassword = null;
_password = string.Empty;
_setupComplete = true;
StateHasChanged();
await Task.Delay(2000);
Navigation.NavigateTo("/login");
}
else
{
_errorMessage = "Benutzername bereits vergeben.";
}
}
catch (Exception ex)
{
_errorMessage = $"Fehler: {ex.Message}";
}
finally
{
_isBusy = false;
}
}
}