Enhance user management: prevent deletion of the last admin user and restrict admin type changes for the last admin account
All checks were successful
Build And Push Dev Docker Image / docker (push) Successful in 1m47s
All checks were successful
Build And Push Dev Docker Image / docker (push) Successful in 1m47s
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -105,6 +105,13 @@ namespace FoodsharingSiegen.Server.Data.Service
|
|||||||
var user = await Context.Users!.Include(x => x.Interactions).FirstOrDefaultAsync(x => x.Id == userId);
|
var user = await Context.Users!.Include(x => x.Interactions).FirstOrDefaultAsync(x => x.Id == userId);
|
||||||
if (user == null) return new(new Exception("User not found"));
|
if (user == null) return new(new Exception("User not found"));
|
||||||
|
|
||||||
|
if (user.Type == UserType.Admin)
|
||||||
|
{
|
||||||
|
var adminCount = await Context.Users!.CountAsync(x => x.Type == UserType.Admin && x.Id != userId);
|
||||||
|
if (adminCount == 0)
|
||||||
|
return new(new Exception("Der letzte Administrator kann nicht gelöscht werden."));
|
||||||
|
}
|
||||||
|
|
||||||
// Interaktionen vom aktuellen Nutzer übernehmen
|
// Interaktionen vom aktuellen Nutzer übernehmen
|
||||||
if(CurrentUser?.Id != null)
|
if(CurrentUser?.Id != null)
|
||||||
foreach (var userInteraction in user.Interactions)
|
foreach (var userInteraction in user.Interactions)
|
||||||
@@ -184,6 +191,13 @@ namespace FoodsharingSiegen.Server.Data.Service
|
|||||||
var entityUser = await Context.Users!.FirstOrDefaultAsync(x => x.Id == user.Id);
|
var entityUser = await Context.Users!.FirstOrDefaultAsync(x => x.Id == user.Id);
|
||||||
if (entityUser == null) return new(new Exception("User not found"));
|
if (entityUser == null) return new(new Exception("User not found"));
|
||||||
|
|
||||||
|
if (entityUser.Type == UserType.Admin && user.Type != UserType.Admin)
|
||||||
|
{
|
||||||
|
var adminCount = await Context.Users!.CountAsync(x => x.Type == UserType.Admin && x.Id != user.Id);
|
||||||
|
if (adminCount == 0)
|
||||||
|
return new(new Exception("Der Typ des letzten Administrators kann nicht geändert werden."));
|
||||||
|
}
|
||||||
|
|
||||||
if (entityUser.Mail != user.Mail ||
|
if (entityUser.Mail != user.Mail ||
|
||||||
entityUser.Type != user.Type ||
|
entityUser.Type != user.Type ||
|
||||||
entityUser.Groups != user.Groups)
|
entityUser.Groups != user.Groups)
|
||||||
|
|||||||
@@ -55,13 +55,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
<CardFooter Class="d-flex justify-content-between">
|
<CardFooter Class="d-flex justify-content-between">
|
||||||
<div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<Button Color="Color.Primary" Size="Size.Small" Clicked="() => EditUser(user)"><Icon Name="IconName.Edit" /></Button>
|
<Button Color="Color.Primary" Size="Size.Small" Clicked="() => EditUser(user)"><Icon Name="IconName.Edit" /></Button>
|
||||||
<Button Color="Color.Info" Size="Size.Small" Clicked="() => SetPassword(user)"><i class="fa-solid fa-key"></i></Button>
|
<Button Color="Color.Info" Size="Size.Small" Clicked="() => SetPassword(user)"><i class="fa-solid fa-key"></i></Button>
|
||||||
<Button Color="Color.Secondary" Size="Size.Small" Clicked="() => SendPasswordSetupMail(user)"><Icon Name="IconName.Mail" /></Button>
|
<Button Color="Color.Secondary" Size="Size.Small" Clicked="() => SendPasswordSetupMail(user)"><Icon Name="IconName.Mail" /></Button>
|
||||||
|
@if (!(user.Type == UserType.Admin && SortedUsers.Count(x => x.Type == UserType.Admin) <= 1))
|
||||||
|
{
|
||||||
<Button Color="Color.Danger" Size="Size.Small" Clicked="() => RemoveUserAsync(user)"><Icon Name="IconName.Delete" /></Button>
|
<Button Color="Color.Danger" Size="Size.Small" Clicked="() => RemoveUserAsync(user)"><Icon Name="IconName.Delete" /></Button>
|
||||||
|
}
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
}
|
}
|
||||||
@@ -105,12 +105,16 @@
|
|||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel>Typ</FieldLabel>
|
<FieldLabel>Typ</FieldLabel>
|
||||||
<Select TValue="UserType" SelectedValue="EditModel.Type" SelectedValueChanged="@(v => EditModel.Type = v)">
|
<Select TValue="UserType" SelectedValue="EditModel.Type" SelectedValueChanged="@(v => EditModel.Type = v)" Disabled="@IsLastAdmin">
|
||||||
@foreach (var enumValue in Enum.GetValues<UserType>())
|
@foreach (var enumValue in Enum.GetValues<UserType>())
|
||||||
{
|
{
|
||||||
<SelectItem TValue="UserType" Value="enumValue">@enumValue</SelectItem>
|
<SelectItem TValue="UserType" Value="enumValue">@enumValue</SelectItem>
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
|
@if (IsLastAdmin)
|
||||||
|
{
|
||||||
|
<small class="text-danger mt-1 d-block">Das ist der letzte Administrator-Account. Der Typ kann nicht geändert werden.</small>
|
||||||
|
}
|
||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel>Gruppen</FieldLabel>
|
<FieldLabel>Gruppen</FieldLabel>
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ namespace FoodsharingSiegen.Server.Pages
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool IsEditing { get; set; }
|
private bool IsEditing { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the current editing user is the last admin
|
||||||
|
/// </summary>
|
||||||
|
private bool IsLastAdmin => IsEditing && EditModel?.Type == UserType.Admin && UserList?.Count(x => x.Type == UserType.Admin) <= 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value of the user groups (ab)
|
/// Gets the value of the user groups (ab)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -184,12 +189,6 @@ namespace FoodsharingSiegen.Server.Pages
|
|||||||
/// <returns>A task that represents the asynchronous remove operation.</returns>
|
/// <returns>A task that represents the asynchronous remove operation.</returns>
|
||||||
private async Task RemoveUserAsync(User user)
|
private async Task RemoveUserAsync(User user)
|
||||||
{
|
{
|
||||||
if (user.IsAdmin())
|
|
||||||
{
|
|
||||||
await Notification.Error("Admins können nicht gelöscht werden!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await ConfirmDialog.ShowAsync(ModalService, "Bestätigen", $"User {user.Mail} löschen?", async () =>
|
await ConfirmDialog.ShowAsync(ModalService, "Bestätigen", $"User {user.Mail} löschen?", async () =>
|
||||||
{
|
{
|
||||||
var removeR = await UserService.RemoveAsync(user.Id);
|
var removeR = await UserService.RemoveAsync(user.Id);
|
||||||
|
|||||||
Reference in New Issue
Block a user