Wave/Wave/Components/Pages/ManageUsers.razor

136 lines
4.6 KiB
Plaintext

@page "/manage/users"
@using Microsoft.AspNetCore.Identity
@using Wave.Data
@using Humanizer
@using Wave.Utilities
@rendermode InteractiveServer
@attribute [Authorize(Policy = "RoleAssignPermissions")]
@attribute [StreamRendering]
@inject RoleManager<IdentityRole> RoleManager
@inject UserManager<ApplicationUser> UserManager
@inject IStringLocalizer<ManageUsers> Localizer
<PageTitle>@(TitlePrefix + Localizer["Title"])</PageTitle>
<h1 class="text-3xl lg:text-5xl font-light mb-6 text-primary">@Localizer["Title"]</h1>
<ModalComponent Id="@ModalId">
<ChildContent>
<InputLabelComponent LabelText="@Localizer["UserName_Label"]">
<InputText class="input input-bordered w-full" type="email" autocomplete="off"
@bind-Value="@UserName" />
</InputLabelComponent>
</ChildContent>
<Actions>
<button class="btn btn-primary" @onclick="Add">@Localizer["UserName_Submit"]</button>
</Actions>
</ModalComponent>
<section class="mb-3 overflow-x-auto">
<h3 class="text-xl lg:text-3xl mb-2">
@Localizer[CurrentRole.ToString().Pluralize()]
</h3>
<div class="flex gap-2">
<InputSelect class="select select-bordered select-sm w-full max-w-xs" Value="CurrentRole"
ValueExpression="() => CurrentRole"
TValue="Role" ValueChanged="async c => await LoadAsync(c)">
@foreach (var role in Enum.GetValues<Role>()) {
<option value="@role">@Localizer[role.ToString()]</option>
}
</InputSelect>
<button class="btn btn-sm btn-square btn-ghost text-success" onclick="@(ModalId).showModal()">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
</div>
@if (Busy) {
<div class="flex place-content-center">
<span class="loading loading-spinner loading-lg"></span>
</div>
} else {
<UserTable Users="Users" RemoveCallback="@(async u => await RemoveAsync(u, CurrentRole))"/>
}
</section>
<ToastComponent @ref="Toast" />
@code {
[CascadingParameter(Name = "TitlePrefix")]
private string TitlePrefix { get; set; } = default!;
public IMessageDisplay Toast { get; set; } = null!;
private string ModalId { get; } = "UserDialog";
[CascadingParameter]
private Task<AuthenticationState> AuthenticationState { get; set; } = default!;
private ApplicationUser? User { get; set; }
private Role CurrentRole { get; set; } = Role.Admin;
private List<ApplicationUser> Users { get; } = [];
private bool Busy { get; set; }
private string UserName { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender) {
if (!firstRender) return;
var state = await AuthenticationState;
User = await UserManager.GetUserAsync(state.User);
await LoadAsync(CurrentRole);
}
private async Task LoadAsync(Role role) {
try {
Busy = true;
var users = await UserManager.GetUsersInRoleAsync(role.ToString());
Users.Clear();
CurrentRole = role;
Users.AddRange(users);
} finally {
Busy = false;
}
await InvokeAsync(StateHasChanged);
}
private async Task Add() {
if (User is null) return;
var user = await UserManager.FindByNameAsync(UserName);
if (user is null) {
Toast.ShowError(Localizer["Error_UserNotFound"]);
return;
}
if (user.Id == User.Id) {
Toast.ShowError(Localizer["Error_EditSelf"]);
return;
}
if (!await RoleManager.RoleExistsAsync(CurrentRole.ToString())) {
var result = await RoleManager.CreateAsync(new IdentityRole(CurrentRole.ToString()));
if (result.Succeeded is not true) {
Toast.ShowError(Localizer["Error_CreateRole"]);
return;
}
}
await UserManager.AddToRoleAsync(user, CurrentRole.ToString());
await LoadAsync(CurrentRole);
Toast.ShowSuccess(Localizer["Success_AddUser"]);
}
private async Task RemoveAsync(ApplicationUser user, Role role) {
if (User is null) return;
if (user.Id == User.Id) {
Toast.ShowError(Localizer["Error_EditSelf"]);
return;
}
await UserManager.RemoveFromRoleAsync(user, role.ToString());
Toast.ShowSuccess(Localizer["Success_RemoveUser"]);
await LoadAsync(CurrentRole);
}
private enum Role {
Author, Reviewer, Moderator, Admin
}
}