Day26 指派角色给使用者

昨天角色的 CRUD 功能都完成了,接着就是要把角色指派给使用者了,先建立一个 ViewModel CustomUserRoleViewModel,这是用来呈现角色底下使用者的 ViewModel。

namespace BlazorServer.ViewModels
{
    public class CustomUserRoleViewModel
    {
        public string UserId { get; set; }
        public string UserName { get; set; }
        public bool IsSelected { get; set; }
    }
}

再於IRolesRepositoryRolesRepository加上编辑角色内使用者的功能,这里用了多载,第一个相当於 Get 取得画面初始资料,第二个则是 Post 送出修改後的资料。
IRolesRepository.cs

…
        Task<List<CustomUserRoleViewModel>> EditUsersInRoleAsync(string RoleId);
        Task<ResultViewModel> EditUsersInRoleAsync(List<CustomUserRoleViewModel> model, string RoleId);

RolesRepository.cs

…
        public async Task<List<CustomUserRoleViewModel>> EditUsersInRoleAsync(string RoleId)
        {
            var role = await _roleManager.FindByIdAsync(RoleId);
            var model = new List<CustomUserRoleViewModel>();

            foreach (var user in _userManager.Users)
            {
                var userRoleViewModel = new CustomUserRoleViewModel
                {
                    UserId = user.Id,
                    UserName = user.UserName
                };

                if (await _userManager.IsInRoleAsync(user, role.Name))
                {
                    userRoleViewModel.IsSelected = true;
                }
                else
                {
                    userRoleViewModel.IsSelected = false;
                }
                model.Add(userRoleViewModel);
            }
            return model;
        }

        public async Task<ResultViewModel> EditUsersInRoleAsync(List<CustomUserRoleViewModel> model, string RoleId)
        {
            var role = await _roleManager.FindByIdAsync(RoleId);
            foreach (var m in model)
            {
                var user = await _userManager.FindByIdAsync(m.UserId);
                IdentityResult result;
                if (m.IsSelected && !(await _userManager.IsInRoleAsync(user, role.Name)))
                {
                    result = await _userManager.AddToRoleAsync(user, role.Name);
                }
                else if (!m.IsSelected && await _userManager.IsInRoleAsync(user, role.Name))
                {
                    result = await _userManager.RemoveFromRoleAsync(user, role.Name);
                }
                else
                {
                    continue;
                }
                if (result.Succeeded)
                {
                    if (model.Count > 0)
                    {
                        continue;
                    }
                    else
                    {
                        return new ResultViewModel
                        {
                            Message = RoleId,
                            IsSuccess = true
                        };
                    }
                }
                else
                {
                    return new ResultViewModel
                    {
                        Message = RoleId,
                        IsSuccess = false
                    };
                }
            }
            return new ResultViewModel
            {
                Message = RoleId,
                IsSuccess = true
            };
        }

接着加上画面。
EditUsersInRole.razor.cs

using BlazorServer.Services;
using BlazorServer.Shared;
using BlazorServer.ViewModels;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorServer.Pages.RolesManagement
{
    public partial class EditUsersInRole
    {
        [Inject] protected IRolesRepository RolesRepository { get; set; }
        [Inject] protected NavigationManager NavigationManager { get; set; }
        [Inject] protected IJSRuntime js { get; set; }
        private JsInteropClasses jsClass;
        [Parameter]
        public string RoleId { get; set; }
        public List<CustomUserRoleViewModel> UserRoleViewModel { get; set; } = new List<CustomUserRoleViewModel>();
        protected override async Task OnInitializedAsync()
        {
            await loadData();
            jsClass = new(js);
        }
        private async Task loadData()
        {
            UserRoleViewModel = (await RolesRepository.EditUsersInRoleAsync(RoleId)).ToList();
        }


        public async Task HandleValidSubmit()
        {
            var result = await RolesRepository.EditUsersInRoleAsync(UserRoleViewModel, RoleId);

            if (result.IsSuccess)
            {
                NavigationManager.NavigateTo($"/RolesManagement/EditRole/{RoleId}");
            }
            else
            {
                await jsClass.Alert(result.Message);
            }
        }
        public void Cancel()
        {
            NavigationManager.NavigateTo($"/RolesManagement/EditRole/{RoleId}");
        }
    }
}

EditUsersInRole.razor

@attribute [Authorize]

<EditForm Model="UserRoleViewModel" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div class="card">
        <div class="card-header">
            <h2>从角色新增或移除使用者</h2>
        </div>
        <div class="card-body">
            @foreach (var user in UserRoleViewModel)
            {
                <div class="form-check m-1">
                    <label class="form-check-label">
                        <InputCheckbox @bind-Value="@user.IsSelected"></InputCheckbox>
                        @user.UserName
                    </label>
                </div>
            }
        </div>
        <div class="card-footer">
            <button type="submit" class="btn btn-primary">更新</button>
            <button type="button" class="btn btn-danger" @onclick="@Cancel">取消</button>
        </div>
    </div>
</EditForm>

EditRole.razor.cs新增一个方法,通往EditUsersInRole.razor,可以编辑角色底下使用者。

        public void EditUsersInRole()
        {
            NavigationManager.NavigateTo($"/RolesManagement/EditUsersInRole/{RoleId}");
        }

EditRole.razor加上一个按钮呼叫该方法。

            <button type="button" class="btn btn-info" @onclick="EditUsersInRole">新增或移除该角色底下的使用者</button>

https://ithelp.ithome.com.tw/upload/images/20210926/20140893zuaw09Ohu9.png

启动网页进入编辑角色下使用者页面,可以看到目前只有一个使用者,将Admin角色指派给这个使用者,如此一来就完成了Admin[email protected]的指派,不过要测试是否成功的话,需要对页面加入限制,还要新增一个使用者测试。
https://ithelp.ithome.com.tw/upload/images/20210926/20140893j6V6TFSXfn.png

先将每个 razor component 的@attribute [Authorize]改成@attribute [Authorize(Roles = "Admin")],表示要看到这页面的人必须有 Role Admin

再去NavMenu.razor,於原本的<AuthorizeView>上方加入下面这段程序,同理要看到通往Roles连结的人必须有 Role Admin,再把原本<AuthorizeView>Roles连结删除。

        <AuthorizeView Roles="Admin">
            <Authorized>
                <li class="nav-item px-3">
                    <NavLink class="nav-link" href="RolesManagement/RolesList" Match="NavLinkMatch.All">
                        <span class="bi bi-kanban-fill h4 p-2 mb-0" aria-hidden="true"></span> Roles
                    </NavLink>
                </li>
            </Authorized>
        </AuthorizeView>

最後新增一名使用者,名为[email protected],以此使用者登入,会发现左边的Roles不见了,手动输入网址也会提示没有权限,这就是最基本的角色(Role)授权,如果系统很简单只要用角色划分权限,这样就能满足需求了。
https://ithelp.ithome.com.tw/upload/images/20210926/20140893TuZdOCNhK4.png
https://ithelp.ithome.com.tw/upload/images/20210926/201408932xUYmWmlg5.png

Ref:Add or remove users from role in asp net core


<<:  Day 12:145. Binary Tree Postorder Traversal

>>:  Day 11 Flask 快速开始

(ISC)² 亚洲会员统计

原始出处:(ISC)² Member Counts in Asia ...

Day 2 - 如何运用sail快速建置Laravel 8.0

观看Laravel 8.0的官方文件教学,可以看到一个新的东西就是我们这次要介绍的Sail,用起来非...

【Day16】[资料结构]-二元搜寻树Binary Search Tree-实作

二元搜寻树(Binary Search Tree)建立的方法 insert: 新增元素进入树中 de...

Day 13 : PHP - 当阵列中有两个重复的key值,该如何将它们的value全部印出?

如标题,这篇想和大家聊聊「重复key」的问题 因为当你用print_r去印出有重复key的阵列时,它...

[Golang] Goroutine Concurrency多执行绪浅谈

Goroutine Golang 中多执行绪称为" Goroutine" ,在其...