2026-06-21 07:52:03 +02:00
|
|
|
@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>
|
|
|
|
|
|
2026-07-04 10:32:35 +02:00
|
|
|
<button @onclick="GeneratePassword" disabled="@_generateDisabled">Passwort generieren</button>
|
2026-06-21 07:52:03 +02:00
|
|
|
|
|
|
|
|
@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>
|
|
|
|
|
|
2026-07-04 10:32:35 +02:00
|
|
|
<button @onclick="CreateAdmin" disabled="@_createAdminDisabled">Admin erstellen</button>
|
2026-06-21 07:52:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
2026-07-04 10:32:35 +02:00
|
|
|
private bool _generateDisabled => _isBusy || string.IsNullOrWhiteSpace(_username);
|
|
|
|
|
private bool _createAdminDisabled => _isBusy || _password != _generatedPassword;
|
2026-06-21 07:52:03 +02:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|