From cd2ee7bddd12752ac58b762b869049e72c9fcc51 Mon Sep 17 00:00:00 2001 From: Tygozwolle Date: Fri, 24 Jul 2026 12:09:46 +0200 Subject: [PATCH] feat: implement admin dashboard with authentication, session monitoring, and user management UI --- .../Components/Layout/MainLayout.razor | 12 ++- .../Components/Pages/Admin/Dashboard.razor | 88 +++++++++++++++---- .../Components/Pages/Admin/Login.razor | 38 ++++---- 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/radiuscontroller/Components/Layout/MainLayout.razor b/radiuscontroller/Components/Layout/MainLayout.razor index d8fe16d..99604af 100644 --- a/radiuscontroller/Components/Layout/MainLayout.razor +++ b/radiuscontroller/Components/Layout/MainLayout.razor @@ -45,10 +45,18 @@ @code { - protected override async Task OnInitializedAsync() + protected override void OnInitialized() { AuthService.OnAuthStateChanged += StateHasChanged; - await AuthService.InitializeAsync(); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await AuthService.InitializeAsync(); + StateHasChanged(); + } } private async Task LogoutAdmin() diff --git a/radiuscontroller/Components/Pages/Admin/Dashboard.razor b/radiuscontroller/Components/Pages/Admin/Dashboard.razor index eb6d888..665db23 100644 --- a/radiuscontroller/Components/Pages/Admin/Dashboard.razor +++ b/radiuscontroller/Components/Pages/Admin/Dashboard.razor @@ -23,9 +23,14 @@ Manage guest bandwidth caps, session durations, and monitor live PostgreSQL accounting.

- +
+ + +
@if (notificationMessage != null) @@ -196,7 +201,7 @@ } - @@ -364,6 +369,37 @@ } + + + @if (selectedUserForDelete != null) + { +
+
+
+

+ Delete Guest Account +

+ +
+ +

+ Are you sure you want to permanently delete guest account @selectedUserForDelete.GuestName (@selectedUserForDelete.Username)? +

+

+ This will remove their RADIUS credentials from radcheck and radreply tables. This action cannot be undone. +

+ +
+ + +
+
+
+ } } @@ -385,16 +421,28 @@ private long editModalDataLimit; private string editModalNewPassword = string.Empty; - protected override async Task OnInitializedAsync() - { - await AuthService.InitializeAsync(); - if (!AuthService.IsAuthenticated) - { - NavManager.NavigateTo("/admin/login"); - return; - } + private UserUsageDto? selectedUserForDelete; - await LoadDataAsync(); + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await AuthService.InitializeAsync(); + if (!AuthService.IsAuthenticated) + { + NavManager.NavigateTo("/admin/login"); + return; + } + + await LoadDataAsync(); + StateHasChanged(); + } + } + + private async Task LogoutAdmin() + { + await AuthService.LogoutAsync(); + NavManager.NavigateTo("/admin/login"); } private async Task LoadDataAsync() @@ -495,13 +543,23 @@ } } - private async Task DeleteUser(int profileId) + private void OpenDeleteModal(UserUsageDto user) { + selectedUserForDelete = user; + } + + private async Task ConfirmDeleteUser() + { + if (selectedUserForDelete == null) return; + + int profileId = selectedUserForDelete.ProfileId; + selectedUserForDelete = null; + try { await RadiusService.DeleteUserAsync(profileId); await LoadDataAsync(); - ShowNotification("User deleted."); + ShowNotification("User account deleted successfully."); } catch (Exception ex) { diff --git a/radiuscontroller/Components/Pages/Admin/Login.razor b/radiuscontroller/Components/Pages/Admin/Login.razor index a700626..99f9cf5 100644 --- a/radiuscontroller/Components/Pages/Admin/Login.razor +++ b/radiuscontroller/Components/Pages/Admin/Login.razor @@ -143,26 +143,30 @@ private bool isSubmitting = false; private string errorMessage = string.Empty; - protected override async Task OnInitializedAsync() + protected override async Task OnAfterRenderAsync(bool firstRender) { - await AuthService.InitializeAsync(); - if (AuthService.IsAuthenticated) + if (firstRender) { - NavManager.NavigateTo("/admin"); - return; - } + try + { + await AuthService.InitializeAsync(); + if (AuthService.IsAuthenticated) + { + NavManager.NavigateTo("/admin"); + return; + } - try - { - isFirstRun = !await AuthService.HasAnyAdminAsync(); - } - catch - { - isFirstRun = false; - } - finally - { - isCheckingFirstRun = false; + isFirstRun = !await AuthService.HasAnyAdminAsync(); + } + catch + { + isFirstRun = false; + } + finally + { + isCheckingFirstRun = false; + StateHasChanged(); + } } } -- 2.52.0