Last active
April 3, 2025 20:12
-
-
Save sadukie/6ca0a8c3f1b935988d9dba5e8827b883 to your computer and use it in GitHub Desktop.
Role Membership Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.ComponentModel.DataAnnotations; | |
namespace BlazorAdmin.Models; | |
public class GetRoleMembershipRequest | |
{ | |
public GetRoleMembershipRequest(string name) | |
{ | |
Name = name; | |
} | |
[Required(ErrorMessage = "The Name field is required")] | |
public string Name { get; init; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
namespace BlazorAdmin.Models; | |
public class GetRoleMembershipResponse | |
{ | |
public string RoleId { get; set; } | |
public List<UserForMembership> RoleMembers { get; set; } = new List<UserForMembership>(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace BlazorAdmin.Models; | |
public class UserForMembership | |
{ | |
public string UserName { get; set; } | |
public string Id { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@inject ILogger<Delete> Logger | |
@inject IJSRuntime JSRuntime | |
@inject IRoleManagementService RoleManagementService | |
@inherits BlazorAdmin.Helpers.BlazorComponent | |
@namespace BlazorAdmin.Pages.RolePage | |
@using BlazorAdmin.Interfaces | |
@using BlazorAdmin.Models | |
@using Microsoft.AspNetCore.Identity | |
<div class="modal @_modalClass" tabindex="-1" role="dialog" style="display:@_modalDisplay"> | |
<div class="modal-dialog" role="document"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<h5 class="modal-title" id="exampleModalLabel">Role Membership Update</h5> | |
<button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="Close"> | |
<span aria-hidden="true">×</span> | |
</button> | |
</div> | |
<div class="modal-body"> | |
<div class="container"> | |
<div class="row"> | |
<p> | |
Are you sure you want to <strong class="text-danger">REMOVE</strong> @_userName from @_roleName? | |
</p> | |
</div> | |
</div> | |
</div> | |
<div class="modal-footer"> | |
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="Close">Cancel</button> | |
<button class="btn btn-danger" @onclick="() => DeleteClick()"> | |
Delete | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
@if (_showDeleteModal) | |
{ | |
<div class="modal-backdrop fade show"></div> | |
} | |
@code { | |
[Parameter] | |
public EventCallback<string> OnSaveClick { get; set; } | |
private string _modalDisplay = "none;"; | |
private string _modalClass = ""; | |
private bool _showDeleteModal = false; | |
private string _roleName = ""; | |
private string _roleId = ""; | |
private string _userId = ""; | |
private string _userName = ""; | |
private async Task DeleteClick() | |
{ | |
Logger.LogInformation("Removing User {userId} from Role {roleId}", _userId, _roleId); | |
await RoleManagementService.DeleteUserFromRole(_userId, _roleId); | |
Logger.LogInformation("Removed User {userId} from {roleId}", _userId, _roleId); | |
await OnSaveClick.InvokeAsync(null); | |
await Close(); | |
} | |
public async Task Open(string userId, string userName, string roleName, string roleId) | |
{ | |
_roleName = roleName; | |
_userName = userName; | |
_roleId = roleId; | |
_userId = userId; | |
await new Css(JSRuntime).HideBodyOverflow(); | |
_modalDisplay = "block;"; | |
_modalClass = "Show"; | |
_showDeleteModal = true; | |
StateHasChanged(); | |
} | |
private async Task Close() | |
{ | |
await new Css(JSRuntime).ShowBodyOverflow(); | |
_modalDisplay = "none"; | |
_modalClass = ""; | |
_showDeleteModal = false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading; | |
using System.Threading.Tasks; | |
using FastEndpoints; | |
using Microsoft.AspNetCore.Authentication.JwtBearer; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Http.HttpResults; | |
using Microsoft.AspNetCore.Identity; | |
using Microsoft.eShopWeb.Infrastructure.Identity; | |
namespace Microsoft.eShopWeb.PublicApi.RoleMembershipEndpoints; | |
public class DeleteUserFromRoleEndpoint(RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager) : Endpoint<DeleteUserFromRoleRequest, Results<NoContent, NotFound>> | |
{ | |
public override void Configure() | |
{ | |
Delete("api/roles/{RoleId}/members/{UserId}"); | |
Roles(BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS); | |
AuthSchemes(JwtBearerDefaults.AuthenticationScheme); | |
Description(d => | |
{ | |
d.Produces(StatusCodes.Status204NoContent); | |
d.Produces(StatusCodes.Status404NotFound); | |
d.WithTags("RoleManagementEndpoints"); | |
} | |
); | |
} | |
public override async Task<Results<NoContent, NotFound>> ExecuteAsync(DeleteUserFromRoleRequest request, CancellationToken ct) | |
{ | |
var userToUpdate = await userManager.FindByIdAsync(request.UserId); | |
if (userToUpdate is null) | |
{ | |
return TypedResults.NotFound(); | |
} | |
var roleToUpdate = await roleManager.FindByIdAsync(request.RoleId); | |
if (roleToUpdate is null || roleToUpdate.Name is null) | |
{ | |
return TypedResults.NotFound(); | |
} | |
await userManager.RemoveFromRoleAsync(userToUpdate, roleToUpdate.Name); | |
return TypedResults.NoContent(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Microsoft.eShopWeb.PublicApi.RoleMembershipEndpoints; | |
public class DeleteUserFromRoleRequest : BaseRequest | |
{ | |
public string UserId { get; init; } | |
public string RoleId { get; init; } | |
public DeleteUserFromRoleRequest(string userId, string roleId) | |
{ | |
UserId = userId; | |
RoleId = roleId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
using BlazorShared.Authorization; | |
using Microsoft.eShopWeb; | |
using Microsoft.eShopWeb.PublicApi.RoleManagementEndpoints; | |
using Microsoft.eShopWeb.PublicApi.RoleMembershipEndpoints; | |
using Microsoft.VisualStudio.TestTools.UnitTesting; | |
using PublicApiIntegrationTests.Helpers; | |
namespace PublicApiIntegrationTests.RoleMembershipEndpoints; | |
[TestClass] | |
public class DeleteUserFromRoleEndpointTest | |
{ | |
[TestMethod] | |
public async Task ReturnsNotFoundGivenValidRoleIdAndInvalidUserIdAndAdminUserToken() | |
{ | |
var client = HttpClientHelper.GetAdminClient(); | |
var validRoleId = await GetValidRoleId(client, Constants.Roles.ADMINISTRATORS); | |
var response = await client.DeleteAsync($"api/roles/{validRoleId}/members/0"); | |
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); | |
} | |
[TestMethod] | |
public async Task ReturnsNotFoundGivenInvalidRoleIdAndValidUserIdAndAdminUserToken() | |
{ | |
var client = HttpClientHelper.GetAdminClient(); | |
var roleList = await client.GetAsync($"/api/roles/{Constants.Roles.ADMINISTRATORS}/members"); | |
var roleMembersResponse = await roleList.Content.ReadAsStringAsync(); | |
var validUsers = roleMembersResponse.FromJson<GetRoleMembershipResponse>(); | |
var validUserId = validUsers!.RoleMembers.FirstOrDefault()!.Id; | |
var response = await client.DeleteAsync($"api/roles/0/members/{validUserId}"); | |
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); | |
} | |
[TestMethod] | |
public async Task ReturnsNoContentWhenDeletingUserFromRoleSuccessfully() | |
{ | |
var client = HttpClientHelper.GetAdminClient(); | |
var roleName = Constants.Roles.PRODUCT_MANAGERS; | |
var validRoleId = await GetValidRoleId(client, Constants.Roles.PRODUCT_MANAGERS); | |
var roleList = await client.GetAsync($"/api/roles/{roleName}/members"); | |
var roleMembersResponse = await roleList.Content.ReadAsStringAsync(); | |
var validUsers = roleMembersResponse.FromJson<GetRoleMembershipResponse>(); | |
var validUserId = validUsers!.RoleMembers.FirstOrDefault()!.Id; | |
var response = await client.DeleteAsync($"api/roles/{validRoleId}/members/{validUserId}"); | |
Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); | |
} | |
private async Task<string> GetValidRoleId(HttpClient client, string roleName) | |
{ | |
var validRoles = await client.GetAsync("/api/roles"); | |
validRoles.EnsureSuccessStatusCode(); | |
var validRolesCollection = await validRoles.Content.ReadAsStringAsync(); | |
var model = validRolesCollection.FromJson<RoleListResponse>(); | |
var selectedRole = model!.Roles.Where(x => x.Name == roleName).First(); | |
return selectedRole.Id; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Net.Http; | |
using System.Net.Http.Headers; | |
namespace PublicApiIntegrationTests.Helpers; | |
internal static class HttpClientHelper | |
{ | |
public static HttpClient GetAdminClient() | |
{ | |
return CreateClient(ApiTokenHelper.GetAdminUserToken()); | |
} | |
public static HttpClient GetProductManagerClient() | |
{ | |
return CreateClient(ApiTokenHelper.GetProductManagerUserToken()); | |
} | |
public static HttpClient GetNormalUserClient() | |
{ | |
return CreateClient(ApiTokenHelper.GetNormalUserToken()); | |
} | |
private static HttpClient CreateClient(string token) | |
{ | |
var client = ProgramTest.NewClient; | |
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); | |
return client; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public async Task<T> HttpDelete<T>(string uri) | |
where T : class | |
{ | |
var result = await _httpClient.DeleteAsync($"{_apiUrl}{uri}"); | |
if (!result.IsSuccessStatusCode) | |
{ | |
var exception = JsonSerializer.Deserialize<ErrorDetails>(await result.Content.ReadAsStringAsync(), new JsonSerializerOptions | |
{ | |
PropertyNameCaseInsensitive = true | |
}); | |
_toastService.ShowToast($"Error : {exception.Message}", ToastLevel.Error); | |
return null; | |
} | |
_toastService.ShowToast($"Deleted successfully!", ToastLevel.Success); | |
return await FromHttpResponseMessage<T>(result); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading.Tasks; | |
using BlazorAdmin.Models; | |
using Microsoft.AspNetCore.Identity; | |
namespace BlazorAdmin.Interfaces; | |
public interface IRoleManagementService | |
{ | |
Task<CreateRoleResponse> Create(CreateRoleRequest role); | |
Task<IdentityRole> Edit(IdentityRole role); | |
Task Delete(string id); | |
Task DeleteUserFromRole(string userId, string roleId); | |
Task<GetByIdRoleResponse> GetById(string id); | |
Task<GetRoleMembershipResponse> GetMembershipByName(string name); | |
Task<RoleListResponse> List(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading.Tasks; | |
using BlazorAdmin.Interfaces; | |
using BlazorAdmin.Models; | |
using Microsoft.AspNetCore.Identity; | |
using Microsoft.Extensions.Logging; | |
namespace BlazorAdmin.Services; | |
public class RoleManagementService(HttpService httpService, ILogger<RoleManagementService> logger) : IRoleManagementService | |
{ | |
public async Task<RoleListResponse> List(){ | |
logger.LogInformation("Fetching roles"); | |
var response = await httpService.HttpGet<RoleListResponse>($"roles"); | |
return response; | |
} | |
public async Task<CreateRoleResponse> Create(CreateRoleRequest newRole) | |
{ | |
var response = await httpService.HttpPost<CreateRoleResponse>($"roles", newRole); | |
return response; | |
} | |
public async Task<IdentityRole> Edit(IdentityRole role) | |
{ | |
return await httpService.HttpPut<IdentityRole>($"roles", role); | |
} | |
public async Task Delete(string id) | |
{ | |
await httpService.HttpDelete($"roles/{id}"); | |
} | |
public async Task<GetByIdRoleResponse> GetById(string id) | |
{ | |
var roleById = await httpService.HttpGet<GetByIdRoleResponse>($"roles/{id}"); | |
return roleById; | |
} | |
public async Task<GetRoleMembershipResponse> GetMembershipByName(string name) | |
{ | |
var roleMembershipByName = await httpService.HttpGet<GetRoleMembershipResponse>($"roles/{name}/members"); | |
return roleMembershipByName; | |
} | |
public async Task DeleteUserFromRole(string userId, string roleId) | |
{ | |
await httpService.HttpDelete($"roles/{roleId}/members/{userId}"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using FastEndpoints; | |
using Microsoft.AspNetCore.Authentication.JwtBearer; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Http.HttpResults; | |
using Microsoft.AspNetCore.Identity; | |
using Microsoft.eShopWeb.Infrastructure.Identity; | |
namespace Microsoft.eShopWeb.PublicApi.RoleMembershipEndpoints; | |
public class RoleMembershipGetByNameEndpoint(UserManager<ApplicationUser> userManager) : Endpoint<GetRoleMembershipRequest, Results<Ok<GetRoleMembershipResponse>, NotFound>> | |
{ | |
public override void Configure() | |
{ | |
Get("api/roles/{roleName}/members"); | |
Roles(BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS); | |
AuthSchemes(JwtBearerDefaults.AuthenticationScheme); | |
Description(d => | |
d.Produces<GetRoleMembershipResponse>() | |
.WithTags("RoleManagementEndpoints")); | |
} | |
public override async Task<Results<Ok<GetRoleMembershipResponse>, NotFound>> ExecuteAsync(GetRoleMembershipRequest request, CancellationToken ct) | |
{ | |
var response = new GetRoleMembershipResponse(request.CorrelationId()); | |
var members = await userManager.GetUsersInRoleAsync(request.RoleName); | |
if (members is null) | |
{ | |
return TypedResults.NotFound(); | |
} | |
response.RoleMembers = [.. members]; | |
return TypedResults.Ok(response); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Microsoft.eShopWeb.PublicApi.RoleMembershipEndpoints; | |
public class GetRoleMembershipRequest : BaseRequest | |
{ | |
public string RoleName { get; init; } | |
public GetRoleMembershipRequest(string name) | |
{ | |
RoleName = name; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Microsoft.eShopWeb.Infrastructure.Identity; | |
namespace Microsoft.eShopWeb.PublicApi.RoleMembershipEndpoints; | |
public class GetRoleMembershipResponse : BaseResponse | |
{ | |
public GetRoleMembershipResponse(Guid correlationId) : base(correlationId) | |
{ | |
} | |
public GetRoleMembershipResponse() | |
{ | |
} | |
public List<ApplicationUser> RoleMembers { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading.Tasks; | |
using BlazorShared.Authorization; | |
using Microsoft.eShopWeb; | |
using Microsoft.VisualStudio.TestTools.UnitTesting; | |
using PublicApiIntegrationTests.Helpers; | |
namespace PublicApiIntegrationTests.RoleMembershipEndpoints; | |
[TestClass] | |
public class RoleMembershipGetByNameEndpointTest | |
{ | |
[TestMethod] | |
public async Task ReturnsMembersWithValidRoleName() | |
{ | |
var client = HttpClientHelper.GetAdminClient(); | |
var roleList = await client.GetAsync($"/api/roles/{Constants.Roles.ADMINISTRATORS}/members"); | |
var roleMembersResponse = await roleList.Content.ReadAsStringAsync(); | |
var model = roleMembersResponse.FromJson<GetRoleMembershipResponse>(); | |
Assert.IsNotNull(model); | |
Assert.IsTrue(model.RoleMembers.Count > 0); | |
} | |
[TestMethod] | |
public async Task ReturnsEmptyListGivenInvalidName() | |
{ | |
var client = HttpClientHelper.GetAdminClient(); | |
var invalidName = "invalidName"; | |
var getInvalidRoleNameMembership = await client.GetAsync($"api/roles/{invalidName}/members"); | |
var response = await getInvalidRoleNameMembership.Content.ReadAsStringAsync(); | |
var model = response.FromJson<GetRoleMembershipResponse>(); | |
Assert.IsNotNull(model); | |
Assert.AreEqual(0, model.RoleMembers.Count); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@using BlazorAdmin.Interfaces | |
@using Microsoft.eShopWeb.Infrastructure.Identity | |
@inject ILogger<Details> Logger | |
@inject IJSRuntime JSRuntime | |
@inject IRoleManagementService RoleManagementService | |
@namespace BlazorAdmin.Pages.RolePage | |
<div class="modal @_modalClass" tabindex="-1" role="dialog" style="display:@_modalDisplay"> | |
<div class="modal-dialog" role="document"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<h5 class="modal-title" id="exampleModalLabel">@_roleName Role - Members</h5> | |
<button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="Close"> | |
<span aria-hidden="true">×</span> | |
</button> | |
</div> | |
<div class="modal-body"> | |
@if (_members == null) | |
{ | |
<Spinner></Spinner> | |
} | |
else | |
{ | |
@if (_members.Count == 0) | |
{ | |
<p>No members found.</p> | |
} | |
else | |
{ | |
<table class="table table-striped table-hover"> | |
<thead> | |
<tr> | |
<th>Name</th> | |
<th>Actions</th> | |
</tr> | |
</thead> | |
<tbody class="cursor-pointer"> | |
@foreach (var member in _members) | |
{ | |
<tr> | |
<td>@member.UserName</td> | |
<td> | |
@if (member.UserName != "[email protected]") | |
{ | |
<button @onclick="@(() => DeleteClick(member.Id,member.UserName))" @onclick:stopPropagation="true" class="btn btn-danger"> | |
Remove from Role | |
</button> | |
} | |
</td> | |
</tr> | |
} | |
</tbody> | |
</table> | |
} | |
} | |
</div> | |
</div> | |
</div> | |
</div> | |
<DeleteUserFromRole OnSaveClick="RefreshMembers" @ref="DeleteConfirmationComponent"></DeleteUserFromRole> | |
@if (_showDetailsModal) | |
{ | |
<div class="modal-backdrop fade show"></div> | |
} | |
@code { | |
private string _modalDisplay = "none;"; | |
private string _modalClass = ""; | |
private bool _showDetailsModal = false; | |
private string _roleName = ""; | |
private string _roleId = ""; | |
private List<ApplicationUser> _members = new List<ApplicationUser>(); | |
private DeleteUserFromRole DeleteConfirmationComponent { get; set; } | |
private async Task DeleteClick(string userId, string userName) | |
{ | |
Logger.LogInformation("Confirming to remove User {userId} from {roleId}",userId, _roleId); | |
await DeleteConfirmationComponent.Open(userId, userName, _roleName, _roleId); | |
} | |
public async Task Open(string roleId, string roleName) | |
{ | |
_roleName = roleName; | |
_roleId = roleId; | |
Logger.LogInformation("Now loading details... /Role/Details/{Id}", roleName, roleId); | |
_members = (await RoleManagementService.GetMembershipByName(roleName)).RoleMembers; | |
await ShowModal(); | |
StateHasChanged(); | |
} | |
public async Task Close() | |
{ | |
await CloseModal(); | |
} | |
private async Task ShowModal(){ | |
await new Css(JSRuntime).HideBodyOverflow(); | |
_modalDisplay = "block;"; | |
_modalClass = "Show"; | |
_showDetailsModal = true; | |
} | |
private async Task CloseModal(){ | |
await new Css(JSRuntime).ShowBodyOverflow(); | |
_modalDisplay = "none"; | |
_modalClass = ""; | |
_showDetailsModal = false; | |
} | |
private async Task RefreshMembers() | |
{ | |
Logger.LogInformation("Refreshing members after removing a user from a role"); | |
_members = (await RoleManagementService.GetMembershipByName(_roleName)).RoleMembers; | |
StateHasChanged(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@page "/roles" | |
@attribute [Authorize(Roles = BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS)] | |
@inherits BlazorAdmin.Helpers.BlazorComponent | |
@namespace BlazorAdmin.Pages.RolePage | |
<PageTitle>eShopOnWeb Admin: Manage Roles</PageTitle> | |
<h1>Manage Roles</h1> | |
@if (_roles == null) | |
{ | |
<Spinner></Spinner> | |
} | |
else | |
{ | |
<p class="esh-link-wrapper"> | |
<button class="btn btn-primary" @onclick="@(CreateClick)"> | |
Create New | |
</button> | |
</p> | |
<table class="table table-striped table-hover"> | |
<thead> | |
<tr> | |
<th>Name</th> | |
<th>Actions</th> | |
</tr> | |
</thead> | |
<tbody class="cursor-pointer"> | |
@foreach (var role in _roles){ | |
<tr> | |
<td>@role.Name</td> | |
<td> | |
<button @onclick="@(() => EditClick(role.Id))" @onclick:stopPropagation="true" class="btn btn-primary"> | |
Edit | |
</button> | |
<button @onclick="@(() => DetailsClick(role.Id,role.Name))" @onclick:stopPropagation="true" class="btn btn-success"> | |
Manage Members | |
</button> | |
<button @onclick="@(() => DeleteClick(role.Id))" @onclick:stopPropagation="true" class="btn btn-danger"> | |
Delete | |
</button> | |
</td> | |
</tr> | |
} | |
</tbody> | |
</table> | |
<Create OnSaveClick="ReloadRoles" @ref="CreateComponent"></Create> | |
<Delete OnSaveClick="ReloadRoles" @ref="DeleteComponent"></Delete> | |
<Edit OnSaveClick="ReloadRoles" @ref="EditComponent"></Edit> | |
<Details @ref="DetailsComponent"></Details> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Threading.Tasks; | |
using BlazorAdmin.Helpers; | |
using BlazorAdmin.Interfaces; | |
using Microsoft.AspNetCore.Identity; | |
namespace BlazorAdmin.Pages.RolePage; | |
public partial class List : BlazorComponent | |
{ | |
[Microsoft.AspNetCore.Components.Inject] | |
public IRoleManagementService RoleManagementService { get; set; } | |
private List<IdentityRole> _roles = []; | |
private Create CreateComponent { get; set; } | |
private Delete DeleteComponent { get; set; } | |
private Edit EditComponent { get; set; } | |
private Details DetailsComponent { get; set; } | |
protected override async Task OnAfterRenderAsync(bool firstRender) | |
{ | |
if (firstRender) | |
{ | |
var response = await RoleManagementService.List(); | |
_roles = response.Roles; | |
CallRequestRefresh(); | |
} | |
await base.OnAfterRenderAsync(firstRender); | |
} | |
private async void DetailsClick(string id, string name) | |
{ | |
await DetailsComponent.Open(id, name); | |
} | |
private async Task CreateClick() | |
{ | |
await CreateComponent.Open(); | |
} | |
private async Task EditClick(string id) | |
{ | |
await EditComponent.Open(id); | |
} | |
private async Task DeleteClick(string id) | |
{ | |
await DeleteComponent.Open(id); | |
} | |
private async Task ReloadRoles() | |
{ | |
var roleCall = await RoleManagementService.List(); | |
_roles = roleCall.Roles; | |
StateHasChanged(); | |
} | |
} |
Comments are disabled for this gist.