背景

目前系统的权限体系存储了权限,权限组,角色之间的关联关系,如下图所示,

Image

目前的数据结构如下,

type PermissionGroup struct {
  ID       uint64 `gorm:"primarykey"`           // 数据库ID
  AppID    uint64 `gorm:"uniqueIndex:idx_permission_groups_name"`
  Name     string `gorm:"not null;uniqueIndex:idx_permission_groups_name" yaml:"name"`
  Title    string `yaml:"title"`
  ParentID uint64 // 父权限ID

  PermissionGroupPermission []*PermissionGroupPermission `gorm:"foreignKey:GroupName;references:Name"`
}

type PermissionGroupPermission struct {
  ID            uint64 `gorm:"primarykey"`           // 数据库ID
  AppID         uint64 `gorm:"uniqueIndex:idx_group_permissions"`
  GroupName     string `gorm:"uniqueIndex:idx_group_permissions"`
  PermissionKey string `gorm:"uniqueIndex:idx_group_permissions"`

  PermissionGroup *PermissionGroup `gorm:"foreignkey:Name;references:GroupName"`
  Permission      *Permission      `gorm:"foreignkey:UniqueKey;references:PermissionKey"`
}

type Permission struct {
  ID        uint64 `gorm:"primarykey"`           // 数据库ID
  Name      string `gorm:"not null;uniqueIndex:idx_permissions_name" yaml:"name"`
  Action    string `gorm:"uniqueIndex:idx_permissions_name" yaml:"action"`
  UniqueKey string `gorm:"uniqueIndex:idx_unique_key" yaml:"unique_key"`
  Title     string `yaml:"title"`
}

其实存在了一些问题,

  1. 没有必要存储 permissions, permission_group_permissions, permission_groups
  2. 无法调整菜单顺序
  3. 无法指定菜单依赖

方案

  1. 减少对于 permissions, permission_group_permissions, permission_groups 的数据存储
  2. 整份权限元数据以配置的方式进行加载
  3. 权限组增加依赖字段

如下图所示,

Image

效果如下,

  1. 直接返回给前端树形结构,方便使用
  2. 权限组 key 自行保证唯一
  3. 服务端只需要保存权限组 key
  4. 权限组层级可以统一配置公共路由
  5. 通过读取权限组配置可以随时调整顺序
  6. 可以指定权限组依赖关系

数据结构如下,

type PermissionGroup struct {
	Name        string             `yaml:"name"`
	Title       string             `yaml:"title"`
	Needs       []string           `yaml:"needs"`
	Groups      []*PermissionGroup `yaml:"groups"`
	Permissions []struct {
		Method string `yaml:"method"`
		Path   string `yaml:"path"`
	} `yaml:"permissions"`
}
- name: "operation-report"
  title: "运营报表"
  groups:
    - name: "overview-data"
      title: "概览数据"
      groups:
        - name: "overview-day"
          title: "查看日概览"
          permissions:
            - method: GET
              path: overview-new
        - name: "edit-overview"
          title: "编辑概览看板"
          needs:
            - overview-day
          permissions:
            - method: PUT
              path: edit-overview