Skip to content

一步步实现微服务权限管理系统(12)

前言

  • 前端参考了很多框架,可谓百花齐放,但很多封装过剩,不利于学习和应用,最终我选择了 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin)
  • 后端我将使用 go-zero 来带领大家一步步实现一个权限管理系统
  • 本系列项目存放在 purezeroadmin 中,每一部分我都将打tag,并保证每个tag能正常运行。请多点赞和评论。
  • 后面示例均为 purezeroadmin 项目为例,你们可以根据需要自建工程来进行试验。均采用vscode进行试验。
  • go-zero 常用命令我将放入其对应的 makefile 文件中。

本节概述

  • 前端角色管理相关逻辑修改
  • 后端增加相应数据和接口

前端修改

src/views/system/role/utils/hook.tsx

  • 状态值改为数字
const form = reactive({
    name: "",
    code: "",
    status: 1
});
  • 页码和页大小作为参数传递
async function onSearch() {
    loading.value = true;
    const { data } = await getRoleList({
        ...toRaw(form),
        page: pagination.currentPage,
        pageSize: pagination.pageSize
    });
    dataList.value = data.list;
    pagination.total = data.total;

    setTimeout(() => {
        loading.value = false;
    }, 500);
}

src/views/system/role/index.vue状态值改为数字

<el-option label="已启用" :value="1" />
<el-option label="已停用" :value="0" />

src/api/system.ts 获取角色菜单改为 get 方式

/** 获取角色管理-权限-菜单权限 */
export const getRoleMenu = (data?: object) => {
  return http.request<Result>("get", "/api/role-menu", { data });
};

后端修改

user-api/api/user.api 改动

增加 /api/role /api/role-menu /api/role-menu-ids 3个路由,用于查询角色,查询角色菜单,查询角色菜单所有id

type (
    UserRoleReq {
        Name     string `json:"name,optional"`
        Code     string `json:"code,optional"`
        Status   *int64 `json:"status,optional"`
        Page     int64  `json:"page,default=1"`
        PageSize int64  `json:"pageSize,default=10"`
    }
    UserRoleData {
        Id         int64  `json:"id"`
        Code       string `json:"code"`
        Name       string `json:"name"`
        Status     int64  `json:"status"`
        Remark     string `json:"remark"`
        CreateTime int64  `json:"createTime"`
        UpdateTime int64  `json:"updateTime"`
    }
    UserRoleResp {
        List  []*UserRoleData `json:"list"`
        Total int64           `json:"total"`
    }
)

@server (
    jwt: Auth // 开启 jwt 认证
)
service user-api {
    @doc "获取路由"
    @handler userRole
    post /api/role (UserRoleReq) returns ([]*UserRoleResp)
}

type (
    UserRoleMenuReq  {}
    UserRoleMenu {
        ParentId int64  `json:"parentId"`
        Id       int64  `json:"id"`
        MenuType int64  `json:"menuType"`
        Title    string `json:"title"`
    }
)

@server (
    jwt: Auth // 开启 jwt 认证
)
service user-api {
    @doc "获取菜单"
    @handler userMenu
    get /api/role-menu (UserRoleMenuReq) returns ([]*UserRoleMenu)
}

type (
    UserRoleMenuIDReq {
        Id int64 `json:"id"`
    }
)

@server (
    jwt: Auth // 开启 jwt 认证
)
service user-api {
    @doc "获取菜单详情"
    @handler userMenuID
    post /api/role-menu-ids (UserRoleMenuIDReq) returns ([]int64)
}

models文件夹修改

  • user-api/models/tbrolemodel.go增加根据状态值筛选
TbRoleModel interface {
    tbRoleModel
    withSession(session sqlx.Session) TbRoleModel
    FindAll(ctx context.Context) ([]*TbRole, error)
    FindList(ctx context.Context, name, code string, status *int64, page, pageSize int64) ([]*TbRole, int64, error)
}

...

func (m *customTbRoleModel) FindList(ctx context.Context, name, code string, status *int64, page, pageSize int64) ([]*TbRole, int64, error) {
    base := ""
    needAnd := false
    if name != "" {
        base += fmt.Sprintf("name = '%s'", name)
        needAnd = true
    }
    if code != "" {
        if needAnd {
            base += " and "
        }
        base += fmt.Sprintf("code = '%s'", code)
    }
    if status != nil {
        if needAnd {
            base += " and "
        }
        base += fmt.Sprintf("status = %v", *status)
    }
    if base != "" {
        base = " where " + base
    }

    var total int64
    err := m.conn.QueryRowCtx(ctx, &total, "select count(*) from tb_role"+base)
    if err != nil {
        return nil, 0, err
    }
    var list []*TbRole
    err = m.conn.QueryRowsCtx(ctx, &list, fmt.Sprintf("select * from tb_role%s limit ?,?", base), (page-1)*pageSize, pageSize)
    return list, total, err
}
  • user-api/models/tbroutermodel.go 增加获取所有路由
...
func (m *customTbRouterModel) FindAll(ctx context.Context) ([]*TbRouter, error) {
    var resp []*TbRouter
    err := m.conn.QueryRowsCtx(ctx, &resp, "select * from tb_router")
    return resp, err
}

user-api/helper/helper.go 增加

func GetAuthsInfos(ctx context.Context, svcCtx *svc.ServiceContext) (tbUser *models.TbUser, mTbRole map[int64]*models.TbRole, err error) {
    userID, err := GetUserIDFromContext(ctx)
    if err != nil {
        return nil, nil, err
    }

    tbUser, err = svcCtx.TbUserModel.FindOne(ctx, userID)
    if err != nil {
        return nil, nil, err
    }

    mTbRole = make(map[int64]*models.TbRole)

    if tbUser.Username == "admin" {
        tbRoles, err := svcCtx.TbRoleModel.FindAll(ctx)
        if err != nil {
            return nil, nil, err
        }

        for _, tbRole := range tbRoles {
            mTbRole[tbRole.Id] = tbRole
        }
        return tbUser, mTbRole, nil
    }

    roles, err := jsonutil.ToArray[string](tbUser.Roles)
    if err != nil {
        return nil, nil, err
    }

    for _, role := range roles {
        tbRole, err := svcCtx.TbRoleModel.FindOneByCode(ctx, role)
        if err != nil {
            return nil, nil, err
        }

        mTbRole[tbRole.Id] = tbRole
    }

    return tbUser, mTbRole, nil
}

logic修改

  • user-api/internal/logic/usermenuidlogic.go 根据角色ID获取菜单ID
func (l *UserMenuIDLogic) UserMenuID(req *types.UserRoleMenuIDReq) (resp []int64, err error) {
    _, mTbRole, err := helper.GetAuthsInfos(l.ctx, l.svcCtx)
    if err != nil {
        return nil, err
    }

    tbRole, ok := mTbRole[req.Id]
    if !ok {
        return nil, errors.New("无对应校色权限")
    }

    rolePermissions, err := jsonutil.ToArray[string](tbRole.Permissions)
    if err != nil {
        return nil, err
    }

    routers, err := l.svcCtx.TbRouterModel.FindAll(l.ctx)
    if err != nil {
        return nil, err
    }

    for _, router := range routers {
        if !helper.RouterPass(l.svcCtx, router, []string{tbRole.Code}, rolePermissions) {
            continue
        }
        resp = append(resp, router.Id)
    }

    return resp, nil
}
  • user-api/internal/logic/userrolelogic.go 获取角色数据
func (l *UserRoleLogic) UserRole(req *types.UserRoleReq) (resp *types.UserRoleResp, err error) {
    list, total, err := l.svcCtx.TbRoleModel.FindList(l.ctx, req.Name, req.Code, req.Status, req.Page, req.PageSize)
    if err != nil {
        return nil, err
    }

    resp = &types.UserRoleResp{
        List:  make([]*types.UserRoleData, len(list)),
        Total: total,
    }

    for i, tbRole := range list {
        resp.List[i] = &types.UserRoleData{
            Id:         tbRole.Id,
            Code:       tbRole.Code,
            Name:       tbRole.Name,
            Status:     tbRole.Status,
            Remark:     tbRole.Remark,
            CreateTime: tbRole.CreateTs,
            UpdateTime: tbRole.UpdateTs,
        }
    }

    return resp, nil
}
  • user-api/internal/logic/usermenulogic.go 获取角色菜单数据
func (l *UserMenuLogic) UserMenu(req *types.UserRoleMenuReq) (resp []*types.UserRoleMenu, err error) {
    userID, err := helper.GetUserIDFromContext(l.ctx)
    if err != nil {
        return nil, err
    }

    tbUser, err := l.svcCtx.TbUserModel.FindOne(l.ctx, userID)
    if err != nil {
        return nil, err
    }

    roles, permissions, err := helper.GetAuths(l.ctx, l.svcCtx, tbUser)
    if err != nil {
        return nil, err
    }

    err = l.GetMenuByParentID(0, roles, permissions, &resp)
    if err != nil {
        return nil, err
    }
    return resp, nil
}

func (l *UserMenuLogic) GetMenuByParentID(parentID int64, roles, permissions []string, roleMenus *[]*types.UserRoleMenu) (err error) {
    routers, err := l.svcCtx.TbRouterModel.FindAllFromParentID(l.ctx, parentID)
    if err != nil {
        return err
    }

    for _, v := range routers {
        if pass := helper.RouterPass(l.svcCtx, v, roles, permissions); pass {
            *roleMenus = append(*roleMenus, &types.UserRoleMenu{
                ParentId: v.ParentId,
                Id:       v.Id,
                MenuType: v.MenuType,
                Title:    v.MetaTitle,
            })
            err = l.GetMenuByParentID(v.Id, roles, permissions, roleMenus)
            if err != nil {
                return err
            }
        }
    }

    return nil
}

测试

  • 前端测试,可发现权限页面出现
  • 权限获取正常

tag版本

purezeroadmin 项目下

git checkout v1.11.0

接下来

权限编辑

Comments