ABP框架入门学习(五)——权限配置

前面几篇已经说到模块的增删改查功能的实现,接下来咋们看看怎么实现系统的权限配置和实现

一、自定义权限名称

在项目TestApp.BookStore.Application.Contracts的Permissions文件下的BookStorePermissions类中,脚本如下:

namespace TestApp.BookStore.Permissions;

public static class BookStorePermissions
{
    public const string GroupName = "BookStore";

    //Add your own permission names. Example:
    //public const string MyPermission1 = GroupName + ".MyPermission1";
    public static class Books
    {
        public const string Default = GroupName + ".Books";
        public const string Create = Default + ".Create";
        public const string Edit = Default + ".Edit";
        public const string Delete = Default + ".Delete";
    }
}

二、权限定义

在项目TestApp.BookStore.Application.Contracts的Permissions文件下的BookStorePermissionDefinitionProvider类中,脚本如下:

using TestApp.BookStore.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;

namespace TestApp.BookStore.Permissions;

public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
    public override void Define(IPermissionDefinitionContext context)
    {
        var myGroup = context.AddGroup(BookStorePermissions.GroupName,L("Permission:BookStore"));
        //Define your own permissions here. Example:
        //myGroup.AddPermission(BookStorePermissions.MyPermission1, L("Permission:MyPermission1"));
        var booksPermission = myGroup.AddPermission( BookStorePermissions.Books.Default, L("Permission:Books"));
        booksPermission.AddChild(BookStorePermissions.Books.Create, L("Permission:Books.Create"));
        booksPermission.AddChild(BookStorePermissions.Books.Edit, L("Permission:Books.Edit"));
        booksPermission.AddChild(BookStorePermissions.Books.Delete, L("Permission:Books.Delete"));
    }

    private static LocalizableString L(string name)
    {
        return LocalizableString.Create<BookStoreResource>(name);
    }
}
  • 定义BookStorePermissions.Books.Default、Create、Edit、Delete时千万注意别写重复了,系统一运行就会报Permissions.Books重复定义错误
  • 这个类定义了一个 权限组 (在UI上分组权限, 下文会看到) 和 权限组中的4个权限. 而且, 创建编辑 和 删除 是 BookStorePermissions.Books.Default 权限的子权限. 仅当父权限被选择时, 子权限才能被选择

里面有用到本地化文本,所以又得配置一下本地化文本(TestApp.BookStore.Domain.Shared 项目的 Localization/BookStore 文件夹中的 en.json),新增脚本如下:

    "Permission:BookStore": "Book Store",
    "Permission:Books": "Book Management",
    "Permission:Books.Create": "Creating new books",
    "Permission:Books.Edit": "Editing the books",
    "Permission:Books.Delete": "Deleting the books"

此时就可以在权限页面(管理>身份认证管理>角色>操作>权限)看到所配置的权限目录,如下:

 

 

 此时就可以在系统配置自己的所需的权限,但是会发现一个问题,配置好了不会生效,那是因为我们只是实现的权限配置,还没有完整在增删改查的操作点使用对应的权限配置,具体操作如下

三、应用层和HTTP API设置权限策略

TestApp.BookStore.Application项目Books文件夹,打开 the BookAppService 类, 设置策略名称为上面定义的权限名称。脚本如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using TestApp.BookStore.Permissions;

namespace TestApp.BookStore.Books
{
    public class BookAppService :
        CrudAppService<
            Book, //The Book entity
            BookDto, //Used to show books
            Guid, //Primary key of the book entity
            PagedAndSortedResultRequestDto, //Used for paging/sorting
            CreateUpdateBookDto>, //Used to create/update a book
        IBookAppService
    {
        public BookAppService(IRepository<Book, Guid> repositoty)
            : base(repositoty)
        {
            GetPolicyName = BookStorePermissions.Books.Default;
            GetListPolicyName = BookStorePermissions.Books.Default;
            CreatePolicyName = BookStorePermissions.Books.Create;
            UpdatePolicyName = BookStorePermissions.Books.Edit;
            DeletePolicyName = BookStorePermissions.Books.Delete;
        }
    }
}
  • 加入代码到构造器. 基类中的 CrudAppService 自动在CRUD操作中使用这些权限. 这不仅实现了 应用服务 的安全性, 也实现了 HTTP API 安全性, 因为如前解释的, HTTP API 自动使用这些服务

四、Razor页面授权

TestApp.BookStore.Web项目打开 BookStoreWebModule 在 ConfigureServices 方法中加入以下代码:

        Configure<RazorPagesOptions>(options =>
        {
            options.Conventions.AuthorizePage("/Books/Index", BookStorePermissions.Books.Default);
            options.Conventions.AuthorizePage("/Books/CreateModal", BookStorePermissions.Books.Create);
            options.Conventions.AuthorizePage("/Books/EditModal", BookStorePermissions.Books.Edit);
        });

 

五、菜单(List)/新建(Create)/编辑(Edit)/删除(Delete)操作点使用权限配置

  •   菜单(List)
    •     TestApp.BookStore.Web项目Menus文件夹BookStoreMenuContributor类,将原来的BookStore菜单脚本:
        context.Menu.AddItem(
            new ApplicationMenuItem(
                    "BooksStore",
                    l["Menu:BookStore"],
                    icon: "fa fa-book"
                ).AddItem(
                    new ApplicationMenuItem(
                        "BooksStore.Books",
                        l["Menu:Books"],
                        url: "/Books"
                    )
                )
            );

          修改为(就是加上权限配置判断):  

 var bookStoreMenu = new ApplicationMenuItem(
             "BooksStore",
             l["Menu:BookStore"],
             icon: "fa fa-book"
            );
        context.Menu.AddItem(bookStoreMenu);

        //CHECK the PERMISSION
        if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
        {
            bookStoreMenu.AddItem(new ApplicationMenuItem(
             "BooksStore.Books",
             l["Menu:Books"],
             url: "/Books"
             ));
        }

 

  •   新建(Create)
    •   打开 Pages/Books/Index.cshtml 文件将之前的New book按钮脚本,修改为:     
@if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create))
                {
                        <abp-button id="NewBookButton"
                            text="@L["NewBook"].Value"
                            icon="plus"
                            button-type="Primary"/>
                }

        最终Index.cshtml脚本如下:

@page
@using TestApp.BookStore.Localization
@using TestApp.BookStore.Web.Pages.Books
@using TestApp.BookStore.Permissions
@using Microsoft.Extensions.Localization
@using Microsoft.AspNetCore.Authorization
@model TestApp.BookStore.Web.Pages.Books.IndexModel
@inject IStringLocalizer<BookStoreResource> L
@inject IAuthorizationService AuthorizationService
@section scripts
{
    <abp-script src="/Pages/Books/Index.js"/>
}

<abp-card>
    <abp-card-header>
        <abp-row>
            <abp-column size-md="_6">
                <abp-card-title>@L["Books"]</abp-card-title>
            </abp-column>
            <abp-column size-md="_6" class="text-right">
                @if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create))
                {
                        <abp-button id="NewBookButton"
                            text="@L["NewBook"].Value"
                            icon="plus"
                            button-type="Primary"/>
                }

            </abp-column>
        </abp-row>
    </abp-card-header>
    <abp-card-body>
        <abp-table striped-rows="true" id="BooksTable"></abp-table>
    </abp-card-body>
</abp-card>
    •   加入 @inject IAuthorizationService AuthorizationService 以访问授权服务.
    •        使用 @if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create)) 检查图书创建权限, 条件显示 新建图书 按钮.

    •   
  • 编辑(Edit)
    • 打开 Pages/Books/Index.js文件将之前的Edit按钮脚本,修改为:
{
                                    text: l('Edit'),
                                    visible: abp.auth.isGranted('BookStore.Books.Edit'), //CHECK for the PERMISSION
                                    action: function (data) {
                                        editModal.open({ id: data.record.id });
                                    }
                                },

 

  • 删除(Delete)
    • 打开 Pages/Books/Index.js文件将之前的Delete按钮脚本,修改为:
{
                                    text: l('Delete'),
                                    visible: abp.auth.isGranted('BookStore.Books.Delete'), //CHECK for the PERMISSION
                                    confirmMessage: function (data) {
                                        return l(
                                            'BookDeletionConfirmationMessage',
                                            data.record.name
                                        );
                                    },
                                    action: function (data) {
                                        testApp.bookStore.books.book
                                            .delete(data.record.id)
                                            .then(function () {
                                                abp.notify.info(
                                                    l('SuccessfullyDeleted')
                                                );
                                                dataTable.ajax.reload();
                                            });
                                    }
                                }

最终js脚本如下:

$(function () {
    var l = abp.localization.getResource('BookStore');

    //获取列表
    var dataTable = $('#BooksTable').DataTable(
        abp.libs.datatables.normalizeConfiguration({
            serverSide: true,
            paging: true,
            order: [[1, "asc"]],
            searching: false,
            scrollX: true,
            ajax: abp.libs.datatables.createAjax(testApp.bookStore.books.book.getList),
            columnDefs: [
                {
                    title: l('Actions'),
                    rowAction: {
                        items:
                            [
                                {
                                    text: l('Edit'),
                                    visible: abp.auth.isGranted('BookStore.Books.Edit'), //CHECK for the PERMISSION
                                    action: function (data) {
                                        editModal.open({ id: data.record.id });
                                    }
                                },
                                {
                                    text: l('Delete'),
                                    visible: abp.auth.isGranted('BookStore.Books.Delete'), //CHECK for the PERMISSION
                                    confirmMessage: function (data) {
                                        return l(
                                            'BookDeletionConfirmationMessage',
                                            data.record.name
                                        );
                                    },
                                    action: function (data) {
                                        testApp.bookStore.books.book
                                            .delete(data.record.id)
                                            .then(function () {
                                                abp.notify.info(
                                                    l('SuccessfullyDeleted')
                                                );
                                                dataTable.ajax.reload();
                                            });
                                    }
                                }
                            ]
                    }
                },
                {
                    title: l('Name'),
                    data: "name"
                },
                {
                    title: l('Type'),
                    data: "type",
                    render: function (data) {
                        return l('Enum:BookType:' + data);
                    }
                },
                {
                    title: l('PublishDate'),
                    data: "publishDate",
                    render: function (data) {
                        return luxon
                            .DateTime
                            .fromISO(data, {
                                locale: abp.localization.currentCulture.name
                            }).toLocaleString();
                    }
                },
                {
                    title: l('Price'),
                    data: "price"
                },
                {
                    title: l('CreationTime'), data: "creationTime",
                    render: function (data) {
                        return luxon
                            .DateTime
                            .fromISO(data, {
                                locale: abp.localization.currentCulture.name
                            }).toLocaleString(luxon.DateTime.DATETIME_SHORT);
                    }
                }
            ]
        })
    );

    //新增操作
    var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal');

    createModal.onResult(function () {
        dataTable.ajax.reload();
    });

    $('#NewBookButton').click(function (e) {
        e.preventDefault();
        createModal.open();
    });

    //修改操作(columnDefs新增Actions操作列)
    var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal');
    editModal.onResult(function () {
        dataTable.ajax.reload();
    });

})

 

在此配置权限,测试勾选Creating new books,则Book列表就有New book按钮,其他操作也是如此。本文测试截图admin无删除操作,附截图如下:

 

 

 

 以上就是本项目模板权限配置的内容,在此记录为了加深印象同时方便后者参考学习!



 

posted @ 2022-03-03 10:51  HI_Hub_MI  阅读(1077)  评论(0编辑  收藏  举报