state after adding all of the user stuff and messing around with the wierd brave bug
This commit is contained in:
323
OpenArchival.Blazor.AdminPages.Shared/UsersTable.razor
Normal file
323
OpenArchival.Blazor.AdminPages.Shared/UsersTable.razor
Normal file
@@ -0,0 +1,323 @@
|
||||
@namespace OpenArchival.Blazor.AdminPages.Shared
|
||||
|
||||
@using OpenArchival.Blazor.AdminPages.Shared;
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using MudBlazor
|
||||
@using MudExtensions
|
||||
@using OpenArchival.Blazor.ArchiveSearch
|
||||
@using OpenArchival.DataAccess
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
|
||||
@layout AdminControlPanelLayout
|
||||
|
||||
<MudDataGrid T="UserDto"
|
||||
MultiSelection=false
|
||||
Filterable=false
|
||||
SelectOnRowClick=true
|
||||
ServerData="new Func<GridState<UserDto>, Task<GridData<UserDto>>>(ServerReload)"
|
||||
@ref=@DataGrid
|
||||
@bind-SelectedItems="_selectedItems"
|
||||
Comparer="_comparer">
|
||||
|
||||
<ToolBarContent>
|
||||
|
||||
<MudSpacer />
|
||||
|
||||
<MudButton Variant="Variant.Filled"
|
||||
StartIcon="@Icons.Material.Filled.Add"
|
||||
Color="Color.Primary"
|
||||
OnClick="CreateNewUser">New User</MudButton>
|
||||
</ToolBarContent>
|
||||
|
||||
<Columns>
|
||||
<PropertyColumn
|
||||
Title="Id"
|
||||
Property="x=>x.Id"
|
||||
Filterable="false"/>
|
||||
|
||||
<PropertyColumn
|
||||
Title="Username"
|
||||
Property="x=>x.Username"
|
||||
Filterable="false"/>
|
||||
|
||||
<PropertyColumn
|
||||
Title="Roles"
|
||||
Property="x=>x.RolesDisplay"
|
||||
Filterable="false"/>
|
||||
|
||||
<TemplateColumn Title="Edit">
|
||||
<CellTemplate>
|
||||
<MudIconButton
|
||||
Color="Color.Primary"
|
||||
Icon="@Icons.Material.Filled.Edit"
|
||||
Variant="Variant.Filled"
|
||||
OnClick="@(() => OnEditClicked(context.Item))">Edit</MudIconButton>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn Title="Delete">
|
||||
<CellTemplate>
|
||||
<MudIconButton
|
||||
Color="Color.Warning"
|
||||
Icon="@Icons.Material.Filled.Delete"
|
||||
Variant="Variant.Filled"
|
||||
OnClick="@(() => OnDeleteClicked(context.Item))"
|
||||
>
|
||||
|
||||
</MudIconButton>
|
||||
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
</Columns>
|
||||
|
||||
<PagerContent>
|
||||
<MudDataGridPager T="UserDto"/>
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
|
||||
|
||||
@inject IArtifactGroupingProvider GroupingProvider;
|
||||
@inject IDialogService DialogService;
|
||||
@inject IArtifactGroupingProvider GroupingProvider;
|
||||
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
|
||||
@inject ISnackbar Snackbar;
|
||||
@inject NavigationManager NavigationManager;
|
||||
@inject UserManager<ApplicationUser> UserManager;
|
||||
@inject RoleManager<IdentityRole> RoleManager;
|
||||
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
|
||||
|
||||
@code
|
||||
{
|
||||
public class UserRowElementComparer: IEqualityComparer<UserDto>
|
||||
{
|
||||
public bool Equals(UserDto? x, UserDto? y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (x is null || y is null) return false;
|
||||
return x.Id == y.Id;
|
||||
}
|
||||
|
||||
public int GetHashCode(UserDto obj)
|
||||
{
|
||||
return obj.Id.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private UserRowElementComparer _comparer = new();
|
||||
|
||||
public MudDataGrid<UserDto> DataGrid { get; set; } = default!;
|
||||
|
||||
private HashSet<UserDto> _selectedItems = new(new UserRowElementComparer());
|
||||
|
||||
private string _searchString { get; set; } = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task CreateNewUser(MouseEventArgs args)
|
||||
{
|
||||
|
||||
var options = new DialogOptions { CloseOnEscapeKey = true, BackdropClick = false};
|
||||
var dialog = await DialogService.ShowAsync<UserManagementDialog>("Create a User", options);
|
||||
|
||||
var newUserDto = await dialog.Result;
|
||||
|
||||
if (newUserDto is not null && !newUserDto.Canceled)
|
||||
{
|
||||
var userDto = (UserDto?)newUserDto.Data;
|
||||
if (userDto is null)
|
||||
{
|
||||
Snackbar.Add("The new user dialog did not return a user model.", Severity.Error);
|
||||
return;
|
||||
}
|
||||
if (userDto.Username is null)
|
||||
{
|
||||
Snackbar.Add("The user model returned by the dialog did not have a username set.");
|
||||
return;
|
||||
}
|
||||
if (userDto.Password is null)
|
||||
{
|
||||
Snackbar.Add("The user model returned by the dialog did not have a password.", Severity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var appUser = UserDto.ToApplicationUser(userDto);
|
||||
if (appUser.Email is null)
|
||||
{
|
||||
Snackbar.Add("The application user converted from the DTO did not have an email");
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationUser? existing = await UserManager.FindByEmailAsync(appUser.Email);
|
||||
if (existing is not null)
|
||||
{
|
||||
Snackbar.Add("A user with this email already exists!", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
appUser.EmailConfirmed = true; // Bypass email confirmation
|
||||
|
||||
IdentityResult result = await UserManager.CreateAsync(appUser, userDto.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
|
||||
IdentityResult roleResult = await UserManager.AddToRolesAsync(appUser, userDto.Roles);
|
||||
if (!roleResult.Succeeded)
|
||||
{
|
||||
Snackbar.Add("Failed to set roles on user!", Severity.Error);
|
||||
foreach (IdentityError error in roleResult.Errors)
|
||||
{
|
||||
Snackbar.Add(error.Description, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
Snackbar.Add("User created!", Severity.Success);
|
||||
await DataGrid.ReloadServerData();
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add($"Failed to create user with errors, check logs. {result.Errors.ToString()}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnEditClicked(UserDto row)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnDeleteClicked(UserDto row)
|
||||
{
|
||||
// Check if we are trying to delete the last Admin user
|
||||
// solution: https://stackoverflow.com/questions/20449008/count-the-number-of-users-in-a-role-in-aspnet-identity-not-membership
|
||||
var context = await ContextFactory.CreateDbContextAsync();
|
||||
IdentityRole adminRole = await context.Roles.FirstAsync(r => r.Name == UserRoles.Admin);
|
||||
Int32 countAdminUsers = await context.Set<ApplicationUser>().CountAsync();
|
||||
|
||||
if (countAdminUsers == 1)
|
||||
{
|
||||
Snackbar.Add("Cannot delete the only admin user!", Severity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
bool? confirmed = await DialogService.ShowMessageBox
|
||||
(
|
||||
new MessageBoxOptions(){
|
||||
Message=$"Are you sure you want to delete this user?",
|
||||
Title="Delete User?",
|
||||
CancelText="Cancel",
|
||||
YesText="Delete"
|
||||
});
|
||||
|
||||
if (confirmed is not null)
|
||||
{
|
||||
// Grab the user from the database, ASP.NET identity will only allow you to
|
||||
// delete the exact object from the database
|
||||
if (row.Id is null)
|
||||
{
|
||||
Snackbar.Add("The user row ID was null, cannot delete", Severity.Error);
|
||||
return;
|
||||
}
|
||||
ApplicationUser? appUser = await UserManager.FindByIdAsync(row.Id);
|
||||
if (appUser is null)
|
||||
{
|
||||
Snackbar.Add("User no longer in database, cannot find by ID.", Severity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
IdentityResult result = await UserManager.DeleteAsync(appUser);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await DataGrid.ReloadServerData();
|
||||
StateHasChanged();
|
||||
Snackbar.Add("User deleted!", Severity.Success);
|
||||
} else
|
||||
{
|
||||
Snackbar.Add("Call to DeleteAsync failed.", Severity.Error);
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
Snackbar.Add(error.Description, Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<GridData<UserDto>> ServerReload(GridState<UserDto> state)
|
||||
{
|
||||
var context = await ContextFactory.CreateDbContextAsync();
|
||||
|
||||
int totalItems = await context.Users.CountAsync();
|
||||
|
||||
|
||||
IEnumerable<UserDto> users = await context.Users
|
||||
.Skip(state.Page * state.PageSize)
|
||||
.Take(state.PageSize)
|
||||
.Select(user=>new UserDto
|
||||
{
|
||||
Id = user.Id,
|
||||
Username = user.UserName,
|
||||
Roles = (from userRole in context.UserRoles
|
||||
join role in context.Roles on userRole.RoleId equals role.Id
|
||||
where userRole.UserId == user.Id
|
||||
select role.Name).ToList()
|
||||
}).ToListAsync();
|
||||
|
||||
return new GridData<UserDto>()
|
||||
{
|
||||
TotalItems = totalItems,
|
||||
Items = users
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<List<ApplicationUser>> SelectedItems()
|
||||
{
|
||||
List<ApplicationUser> selectedUsers = [];
|
||||
foreach (UserDto row in DataGrid.SelectedItems)
|
||||
{
|
||||
await using var context = await ContextFactory.CreateDbContextAsync();
|
||||
|
||||
var user = await context.Users.Where(user => user.Id == row.Id).FirstAsync();
|
||||
if (user is null)
|
||||
{
|
||||
Snackbar.Add($"User with id {row.Id} no longer exists in the database.", Severity.Error);
|
||||
continue;
|
||||
}
|
||||
selectedUsers.Add(user);
|
||||
}
|
||||
|
||||
return selectedUsers;
|
||||
}
|
||||
|
||||
public async Task SetSelectedItemsAsync(IEnumerable<ApplicationUser> postsToSelect)
|
||||
{
|
||||
var context = await ContextFactory.CreateDbContextAsync();
|
||||
|
||||
var rowElementsToSelect = postsToSelect.Select(user=> new UserDto
|
||||
{
|
||||
Id = user.Id,
|
||||
Username = user.UserName,
|
||||
Roles = (from userRole in context.UserRoles
|
||||
join role in context.Roles on userRole.RoleId equals role.Id
|
||||
select role.Name).ToList()
|
||||
});
|
||||
|
||||
_selectedItems = new HashSet<UserDto>(rowElementsToSelect, _comparer);
|
||||
|
||||
_selectedItems = new HashSet<UserDto>();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void ClearSelected()
|
||||
{
|
||||
_selectedItems = new HashSet<UserDto>(_comparer);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user