iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
自我挑戰組

ASP.NET Core & Blazor系列 第 26

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角色指派給這個使用者,如此一來就完成了Admintest@gmail.com的指派,不過要測試是否成功的話,需要對頁面加入限制,還要新增一個使用者測試。
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>

最後新增一名使用者,名為user@gmail.com,以此使用者登入,會發現左邊的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


上一篇
Day25 建立角色功能
下一篇
Day27 建立使用者及Claim功能
系列文
ASP.NET Core & Blazor30

尚未有邦友留言

立即登入留言