likes
comments
collection
share

企业管理平台的权限管理设计方案

作者站长头像
站长
· 阅读数 3

背景

企业在使用企业管理平台的时候为了保护企业数据、增强安全性、防止数据篡改等一系列原因,所以需要在企业管理平台中引入权限管理系统。

设计方案

权限类别

在企业管理平台中,权限通常分为菜单权限(页面权限)、功能权限(数据权限)两大类,两个类型的权限区别如下:

菜单权限(页面权限)

菜单权限是指拥有某个权限才可以查看某个菜单,包含这个菜单对应的页面;但是有的页面没有菜单,却需要权限控制,我也将这种类型定义为菜单权限。

功能权限(数据权限)

功能权限是指拥有某个权限才可以操作某个功能,或者查看某个数据,无论是功能还是数据,都是点对点的权限,所以我将这两种类型的权限也划分为一种权限。

权限角色

企业下的某一些员工,具有的权限完全一致,如果直接通过员工与权限关联,如果员工数量庞大,或者需要一些批量操作,那么相关的数据会变得庞大且难以维护,所以需要引入“权限角色”; 通过 员工 与 角色 关联,角色 与 权限 关联,从而实现更低成本的修改员工权限,节省数据库空间,并且操作更明了、高效。

企业 & 权限 & 角色 & 员工的关联关系

企业管理平台的权限管理设计方案 说明:

  1. 企业与员工和角色具有关联关系,通过企业可以查找员工和角色数据;
  2. 员工与角色互相具有关联关系,通过员工可以查找关联的角色数据,通过角色也可以查找关联的员工数据;
  3. 权限只和角色具有关联关系,通过角色可以查找菜单权限、和功能权限;

数据库设计

企业管理平台的权限管理设计方案 说明:

表名说明
company企业信息
employee员工信息,企业与员工为一对多关系,通过companyId 实现关联
role角色信息,说明同上
permission权限信息,说明同上,type 为权限类型,分为菜单权限和功能权限,code 用于语义化权限(不可以重复)
employeeAndRole员工和角色关联信息,员工和角色为多对多的关系,通过一张关联表,便于数据维护
roleAndPermission角色和权限关联信息,说明同上

示例代码

以下示例代码均为微信云开发云函数代码

企业新增 - company

// id 自动生成,不需要传入
const res = await db.collection('company').add({
  data: {
     name: data.name // 企业名称
 		 ...
  }
});

生成默认数据

  1. 新增企业后生成一个超级管理员员工,;
  2. 新增企业后生成多个默认角色;
  3. 菜单权限和功能权限由系统内置,用户不可以操作。

实际业务场景通常是在企业申请入驻审核通过后执行,示例如下

// 修改企业状态
// 此处当作企业审核通过
const res = await db.collection('company').update({
  data: {
    id: data.companyId // 企业id
    status: 1
 		 ...
  }
});
if(res.code !== 0) return {code: 'xxx', msg: '审核通过失败'};

// 创建默认员工
const resEmployee = await db.collection('employee').add({
  data: {
    companyId: data.companyId // 企业id
    name: '管理员' // 员工名称
    account: data.phoneNum // 用企业申请入住时填写的手机号作为默认账号
    password: '123456' // 生成默认密码,仅作为示例使用,实际场景别这样做
    ...
  }
});
if(resEmployee.code !== 0) return {code: 'xxx', msg: '创建员工失败'};

// 创建默认角色
const resRole = await db.collection('role').add({
  data: [
    {
        companyId: data.companyId // 企业id
        name: '管理员', // 角色名称
        code: 'admin' // 角色code
        ...
    }
  ]
});
if(resRole.code !== 0) return {code: 'xxx', msg: '创建角色失败'};

// 生成员工和角色的关联关系
const resEmployeeAndRole = await db.collection('employeeAndRole').add({
  data: [
    {
        employeeId: resEmployee?.data?.id, // 员工id
        roleId: resRole?.data?.id
        ...
    },
    ...
  ]
});
if(resEmployeeAndRole.code !== 0) return {code: 'xxx', msg: '创建生成员工和角色的关联关系失败'};

// 生成角色和权限的关联关系
const resRoleAndPermission = await db.collection('roleAndPermission').add({
  data: [
    {
      roleId: resRole?.data?.id
      permissionId: xxx // 权限id 由开发人员 or 运营人员管理,直接写入,具体方式结合自己的实现方式
    },
    ...
  ]
});
if(resEmployeeAndRole.code !== 0) return {code: 'xxx', msg: '创建生成员工和角色的关联关系失败'};

如何使用

上一步完成了数据准备,现在接入实际业务场景

登录场景

密码、验证码、扫码等登录方式最终都会拿到登录员工的信息,实现登录的方式不多赘述。直接按照账号校验通过的流程往下走,较为简单的步骤就略过了,如果确实有人有需要,请在评论区告诉我,我把相应的代码补上。

// 校验成功后会获取到当前登录员工id

// 根据员工id 查询员工信息
...
略过
...

// 根据员工信息中绑定的companyId 查询企业信息
...
略过
...

// 根据员工id 查询该员工关联的所有角色id
  const res = await db
  .collection('employeeAndRole')
  .where({
    employeeId: data.employeeId
  })
  .get();

if(res.code !== 0) return {code: 'xxx', msg: '获取角色失败‘};
  
// 将查询到角色id 存储到roleIds
const roleIds = res?.data?.map(item => item?.roleId);

// 根据roleIds 查询角色关联的权限信息
const resRoleAndPermission = await db
  .collection('roleAndPermission')
  .where({
    roleId: db.command.in(roleIds)
  })
  .get();

if(resRoleAndPermission.code !== 0) return {code: 'xxx', msg: '获取角色信息失败‘};

// 通过角色id 和 权限id 查找角色、权限的相信信息
...
略过
...

// 此时获取到了员工信息、员工关联的角色信息、以及员工关联角色的权限信息
// 将获取到的信息直接返回给登录接口,前端自行存储该数据进行后续的业务操作

修改员工权限场景

通常来说,上一步获取到的数据会通过如下结构返回给前端

const data = {
  userInfo: {
    name: 'xxx',
    role: ['xxx'],
    permission: ['xxxx']
  }
}

此时我们可以看到一个员工拥有的角色和权限信息,如果我们要修改员工的权限数据,只需按照如下方式进行修改数据

// 员工添加角色
const resEmployeeAndRole = await db.collection('employeeAndRole').add({
  data: [
    {
      employeeId: resEmployee?.data?.id, // 员工id
      roleId: resRole?.data?.id
    },
    ...
  ]
});
if(resEmployeeAndRole.code !== 0) return {code: 'xxx', msg: '添加角色失败'};

// 员工删除角色
// 先查找
const resEmployeeAndRoleGet = await db.collection('employeeAndRole')
  .where({
    data: [
      {
        employeeId: resEmployee?.data?.id, // 员工id
        roleId: resRole?.data?.id
      },
      ...
    ]
  })
  .get();
// 再删除
const resEmployeeAndRoleGet = await db.collection('employeeAndRole')
  	.doc(resEmployeeAndRoleGet?.id)
  .remove();

以上就完成了员工的角色添加和删除,所有的操作都通过关联关系表操作,不需要操作角色和员工的表,后期维护、迭代都较为灵活。

ps:欢迎讨论,提问题,方案不当之处,也请多指教。

ps:辛苦点个赞,能点个关注就更好了,您的关注、点赞、收藏是我继续创作的动力

转载自:https://juejin.cn/post/7296782121153069091
评论
请登录