230 lines
8.2 KiB
Plaintext
230 lines
8.2 KiB
Plaintext
@page "/admin/login"
|
|
@rendermode InteractiveServer
|
|
@inject AdminAuthService AuthService
|
|
@inject NavigationManager NavManager
|
|
|
|
<div class="portal-wrapper">
|
|
<div class="portal-header">
|
|
<div class="brand-icon" style="margin: 0 auto 1rem auto; width: 60px; height: 60px; font-size: 1.8rem; background: linear-gradient(135deg, var(--accent-purple), var(--primary));">
|
|
<i class="bi bi-shield-lock-fill"></i>
|
|
</div>
|
|
@if (isFirstRun)
|
|
{
|
|
<h1 class="portal-title">First-Time Setup</h1>
|
|
<p class="portal-subtitle">Create your primary administrator account to secure the RADIUS Controller panel</p>
|
|
}
|
|
else
|
|
{
|
|
<h1 class="portal-title">Administrator Login</h1>
|
|
<p class="portal-subtitle">Access RADIUS server policies, session limits, and data accounting</p>
|
|
}
|
|
</div>
|
|
|
|
<div class="glass-card">
|
|
@if (isCheckingFirstRun)
|
|
{
|
|
<div style="text-align: center; padding: 2rem;">
|
|
<div class="spinner-border text-primary" role="status"></div>
|
|
<p style="margin-top: 1rem; color: var(--text-muted); font-size: 0.9rem;">Checking system configuration...</p>
|
|
</div>
|
|
}
|
|
else if (isFirstRun)
|
|
{
|
|
<div style="background: rgba(20, 184, 166, 0.1); border: 1px solid rgba(20, 184, 166, 0.3); border-radius: 8px; padding: 0.85rem 1rem; margin-bottom: 1.5rem; font-size: 0.85rem; color: var(--accent-teal);">
|
|
<i class="bi bi-info-circle-fill"></i> <strong>Welcome!</strong> No admin user exists in the database. Please create your administrator credentials below.
|
|
</div>
|
|
|
|
<EditForm Model="this" OnValidSubmit="HandleFirstTimeSetup">
|
|
<div class="form-group">
|
|
<label class="form-label" for="setupUsername">Administrator Username</label>
|
|
<input id="setupUsername"
|
|
type="text"
|
|
class="form-control-glass"
|
|
placeholder="e.g. admin"
|
|
@bind="username"
|
|
required />
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="setupPassword">Password</label>
|
|
<input id="setupPassword"
|
|
type="password"
|
|
class="form-control-glass"
|
|
placeholder="••••••••"
|
|
@bind="password"
|
|
required />
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="confirmPassword">Confirm Password</label>
|
|
<input id="confirmPassword"
|
|
type="password"
|
|
class="form-control-glass"
|
|
placeholder="••••••••"
|
|
@bind="confirmPassword"
|
|
required />
|
|
</div>
|
|
|
|
@if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
<div style="color: var(--accent-rose); font-size: 0.875rem; margin-bottom: 1rem;">
|
|
<i class="bi bi-exclamation-triangle-fill"></i> @errorMessage
|
|
</div>
|
|
}
|
|
|
|
<button type="submit" class="btn-gradient-primary" disabled="@isSubmitting">
|
|
@if (isSubmitting)
|
|
{
|
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
|
<span>Creating Administrator Account...</span>
|
|
}
|
|
else
|
|
{
|
|
<i class="bi bi-person-check-fill"></i>
|
|
<span>Create Admin Account & Log In</span>
|
|
}
|
|
</button>
|
|
</EditForm>
|
|
}
|
|
else
|
|
{
|
|
<EditForm Model="this" OnValidSubmit="HandleLogin">
|
|
<div class="form-group">
|
|
<label class="form-label" for="adminUsername">Username</label>
|
|
<input id="adminUsername"
|
|
type="text"
|
|
class="form-control-glass"
|
|
placeholder="Username"
|
|
@bind="username"
|
|
required />
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="adminPassword">Password</label>
|
|
<input id="adminPassword"
|
|
type="password"
|
|
class="form-control-glass"
|
|
placeholder="••••••••"
|
|
@bind="password"
|
|
required />
|
|
</div>
|
|
|
|
@if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
<div style="color: var(--accent-rose); font-size: 0.875rem; margin-bottom: 1rem;">
|
|
<i class="bi bi-exclamation-triangle-fill"></i> @errorMessage
|
|
</div>
|
|
}
|
|
|
|
<button type="submit" class="btn-gradient-primary" disabled="@isSubmitting">
|
|
@if (isSubmitting)
|
|
{
|
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
|
<span>Authenticating...</span>
|
|
}
|
|
else
|
|
{
|
|
<i class="bi bi-box-arrow-in-right"></i>
|
|
<span>Sign In to Admin Panel</span>
|
|
}
|
|
</button>
|
|
</EditForm>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
private string username = string.Empty;
|
|
private string password = string.Empty;
|
|
private string confirmPassword = string.Empty;
|
|
|
|
private bool isCheckingFirstRun = true;
|
|
private bool isFirstRun = false;
|
|
private bool isSubmitting = false;
|
|
private string errorMessage = string.Empty;
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
try
|
|
{
|
|
await AuthService.InitializeAsync();
|
|
if (AuthService.IsAuthenticated)
|
|
{
|
|
NavManager.NavigateTo("/admin");
|
|
return;
|
|
}
|
|
|
|
isFirstRun = !await AuthService.HasAnyAdminAsync();
|
|
}
|
|
catch
|
|
{
|
|
isFirstRun = false;
|
|
}
|
|
finally
|
|
{
|
|
isCheckingFirstRun = false;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task HandleFirstTimeSetup()
|
|
{
|
|
isSubmitting = true;
|
|
errorMessage = string.Empty;
|
|
|
|
if (string.IsNullOrWhiteSpace(username) || username.Trim().Length < 3)
|
|
{
|
|
errorMessage = "Username must be at least 3 characters long.";
|
|
isSubmitting = false;
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(password) || password.Length < 6)
|
|
{
|
|
errorMessage = "Password must be at least 6 characters long.";
|
|
isSubmitting = false;
|
|
return;
|
|
}
|
|
|
|
if (password != confirmPassword)
|
|
{
|
|
errorMessage = "Password and Confirm Password do not match.";
|
|
isSubmitting = false;
|
|
return;
|
|
}
|
|
|
|
bool success = await AuthService.RegisterInitialAdminAsync(username, password);
|
|
if (success)
|
|
{
|
|
NavManager.NavigateTo("/admin");
|
|
}
|
|
else
|
|
{
|
|
errorMessage = "Failed to create administrator account. An admin user may already exist.";
|
|
}
|
|
|
|
isSubmitting = false;
|
|
}
|
|
|
|
private async Task HandleLogin()
|
|
{
|
|
isSubmitting = true;
|
|
errorMessage = string.Empty;
|
|
|
|
bool success = await AuthService.LoginAsync(username, password);
|
|
if (success)
|
|
{
|
|
NavManager.NavigateTo("/admin");
|
|
}
|
|
else
|
|
{
|
|
errorMessage = "Invalid admin username or password.";
|
|
}
|
|
|
|
isSubmitting = false;
|
|
}
|
|
}
|