Auth integration

This commit is contained in:
Wieland, Marc
2026-05-22 10:39:26 +02:00
parent 8f6d070e6b
commit 523c74028b
21 changed files with 141 additions and 7 deletions
+5
View File
@@ -7,6 +7,11 @@
<MudNavLink Href="urlaub-maximizer" Icon="@Icons.Material.Filled.AutoAwesome">Urlaubs-Maximizer</MudNavLink>
<MudNavLink Href="settings" Icon="@Icons.Material.Filled.Settings">Einstellungen</MudNavLink>
<MudDivider Class="mt-2 mb-2" />
<AuthorizeView Policy="AdminOnly">
<MudNavLink Href="admin/users" Icon="@Icons.Material.Filled.AdminPanelSettings" IconColor="Color.Error">
Benutzerverwaltung
</MudNavLink>
</AuthorizeView>
<AuthorizeView>
<Authorized>
<MudStack Row="true" AlignItems="AlignItems.Center" Class="px-4 py-1" Spacing="1">
+103
View File
@@ -0,0 +1,103 @@
@page "/admin/users"
@rendermode InteractiveServer
@attribute [Authorize(Policy = "AdminOnly")]
@inject AuthService AuthService
@inject ISnackbar Snackbar
@inject AuthenticationStateProvider AuthStateProvider
<PageTitle>Benutzerverwaltung Timetracker</PageTitle>
@if (_loading)
{
<MudStack AlignItems="AlignItems.Center" Class="mt-16" Spacing="3">
<MudProgressCircular Color="Color.Primary" Indeterminate="true" Size="Size.Large" />
<MudText Color="Color.Secondary">Lade Benutzer…</MudText>
</MudStack>
}
else
{
<MudStack Spacing="4">
@* ── Header ── *@
<MudPaper Elevation="4" Class="pa-5 rounded-xl"
Style="background: linear-gradient(135deg, #B71C1C 0%, #7F0000 100%); color:white;">
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="3">
<MudIcon Icon="@Icons.Material.Filled.AdminPanelSettings" Style="color:white; font-size:2rem" />
<MudStack Spacing="0">
<MudText Typo="Typo.h5" Style="color:white; font-weight:700">Benutzerverwaltung</MudText>
<MudText Typo="Typo.caption" Style="color:rgba(255,255,255,0.72)">
@_users.Count Benutzer registriert
</MudText>
</MudStack>
</MudStack>
</MudPaper>
@* ── Tabelle ── *@
<MudCard Elevation="3" Class="rounded-xl">
<MudCardContent Class="pa-0">
<MudTable Items="_users" Hover="true" Striped="true" Dense="false"
SortLabel="Sortieren">
<HeaderContent>
<MudTh><MudTableSortLabel SortBy="new Func<User, object>(u => u.Id)">ID</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<User, object>(u => u.Username)" InitialDirection="SortDirection.Ascending">Benutzername</MudTableSortLabel></MudTh>
<MudTh Style="text-align:right">Aktionen</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>
<MudText Typo="Typo.body2" Color="Color.Secondary">@context.Id</MudText>
</MudTd>
<MudTd>
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
<MudIcon Icon="@Icons.Material.Filled.AccountCircle"
Color="@(context.Username == "marc" ? Color.Error : Color.Default)"
Size="Size.Small" />
<MudText Style="@(context.Username == "marc" ? "font-weight:700" : "")">
@context.Username
</MudText>
@if (context.Username == "marc")
{
<MudChip T="string" Size="Size.Small" Color="Color.Error" Variant="Variant.Outlined">Admin</MudChip>
}
</MudStack>
</MudTd>
<MudTd Style="text-align:right">
@if (context.Username != "marc")
{
<MudIconButton Icon="@Icons.Material.Filled.DeleteOutline"
Color="Color.Error"
Size="Size.Small"
OnClick="@(() => DeleteUser(context))" />
}
</MudTd>
</RowTemplate>
<NoRecordsContent>
<MudText Color="Color.Secondary" Class="pa-4">Keine Benutzer gefunden.</MudText>
</NoRecordsContent>
</MudTable>
</MudCardContent>
</MudCard>
</MudStack>
}
@code {
private List<User> _users = [];
private bool _loading = true;
protected override async Task OnInitializedAsync()
{
var claim = (await AuthStateProvider.GetAuthenticationStateAsync())
.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return;
_users = await AuthService.GetAllUsersAsync();
_loading = false;
}
private async Task DeleteUser(User user)
{
await AuthService.DeleteUserAsync(user.Id);
_users.Remove(user);
Snackbar.Add($"Benutzer \"{user.Username}\" gelöscht.", Severity.Info);
}
}