Files
RpgRoller/RpgRoller/Components/Pages/HomeControls/AdminHome.razor.cs
2026-04-05 01:40:26 +02:00

208 lines
5.5 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using RpgRoller.Contracts;
using RpgRoller.Domain;
namespace RpgRoller.Components.Pages.HomeControls;
[ExcludeFromCodeCoverage]
public partial class AdminHome
{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
return;
await InitializeAsync();
await InvokeAsync(StateHasChanged);
}
private async Task InitializeAsync()
{
try
{
var me = await ApiClient.RequestAsync<MeResponse>("GET", "/api/me");
CurrentUser = me.User;
IsCurrentUserAdmin = HasAdminRole(me.User);
if (!IsCurrentUserAdmin)
return;
Users = (await ApiClient.RequestAsync<IReadOnlyList<AdminUserSummary>>("GET", "/api/admin/users")).OrderBy(user => user.Username, StringComparer.OrdinalIgnoreCase).ToList();
}
catch (ApiRequestException ex) when (ex.StatusCode == 401)
{
await LoggedOut.InvokeAsync("Session expired. Please log in again.");
}
catch (ApiRequestException ex)
{
SetStatus(ex.Message, true);
}
finally
{
IsLoading = false;
}
}
private Task OpenPlayAsync()
{
return OpenWorkspaceAsync("play");
}
private Task OpenCampaignManagementAsync()
{
return OpenWorkspaceAsync("management");
}
private Task OpenAdminAsync()
{
IsScreenMenuOpen = false;
return Task.CompletedTask;
}
private async Task LogoutAsync()
{
if (IsMutating)
return;
IsMutating = true;
try
{
await ApiClient.RequestWithoutPayloadAsync("POST", "/api/auth/logout");
}
catch (ApiRequestException)
{
}
finally
{
IsMutating = false;
}
await LoggedOut.InvokeAsync("Logged out.");
}
private async Task ToggleAdminRoleAsync(AdminUserSummary user)
{
if (IsMutating || CurrentUser is null || user.Id == CurrentUser.Id)
return;
IsMutating = true;
try
{
IReadOnlyList<string> roles = HasAdminRole(user) ? Array.Empty<string>() : [UserRoles.Admin];
_ = await ApiClient.RequestAsync<AdminUserSummary>("PUT", $"/api/admin/users/{user.Id}/roles", new UpdateUserRolesRequest(roles));
await ReloadUsersAsync();
SetStatus("User roles updated.", false);
}
catch (ApiRequestException ex)
{
SetStatus(ex.Message, true);
}
finally
{
IsMutating = false;
}
}
private async Task DeleteUserAsync(AdminUserSummary user)
{
if (IsMutating || CurrentUser is null || user.Id == CurrentUser.Id)
return;
var confirmed = await JS.InvokeAsync<bool>("confirm", $"Delete user '{user.Username}'?");
if (!confirmed)
return;
IsMutating = true;
try
{
_ = await ApiClient.RequestAsync<bool>("DELETE", $"/api/admin/users/{user.Id}");
await ReloadUsersAsync();
SetStatus("User deleted.", false);
}
catch (ApiRequestException ex)
{
SetStatus(ex.Message, true);
}
finally
{
IsMutating = false;
}
}
private async Task ReloadUsersAsync()
{
Users = (await ApiClient.RequestAsync<IReadOnlyList<AdminUserSummary>>("GET", "/api/admin/users")).OrderBy(user => user.Username, StringComparer.OrdinalIgnoreCase).ToList();
}
private static bool HasAdminRole(UserSummary user)
{
return user.Roles.Contains(UserRoles.Admin, StringComparer.OrdinalIgnoreCase);
}
private static bool HasAdminRole(AdminUserSummary user)
{
return user.Roles.Contains(UserRoles.Admin, StringComparer.OrdinalIgnoreCase);
}
private void SetStatus(string message, bool isError)
{
StatusMessage = message;
StatusIsError = isError;
}
private void ToggleScreenMenu()
{
IsScreenMenuOpen = !IsScreenMenuOpen;
}
private async Task OpenWorkspaceAsync(string screen)
{
IsScreenMenuOpen = false;
await WorkspaceRequested.InvokeAsync(screen);
}
[Inject]
private RpgRollerApiClient ApiClient { get; set; } = null!;
[Inject]
private IJSRuntime JS { get; set; } = null!;
private bool IsLoading { get; set; } = true;
private bool IsMutating { get; set; }
private bool IsScreenMenuOpen { get; set; }
private bool IsCurrentUserAdmin { get; set; }
private UserSummary? CurrentUser { get; set; }
private List<AdminUserSummary> Users { get; set; } = [];
private string? StatusMessage { get; set; }
private bool StatusIsError { get; set; }
private IReadOnlyList<AppHeaderMenuItem> HeaderMenuItems =>
[
new()
{
Label = "Play",
IsActive = false,
OnSelected = OpenPlayAsync
},
new()
{
Label = "Campaign Management",
IsActive = false,
OnSelected = OpenCampaignManagementAsync
},
new()
{
Label = "Admin",
IsActive = true,
OnSelected = OpenAdminAsync
}
];
[Parameter]
public EventCallback<string?> LoggedOut { get; set; }
[Parameter]
public EventCallback<string> WorkspaceRequested { get; set; }
}