UML图
权限类型
operator_rule 功能操作权限
menu_rule 菜单权限
page_item_rule 页面元素
file_rule 文件权限
表设计
ruleId 权限ID
operatorId 操作ID
menuId 菜单ID
pageItemId 页面元素ID
fileId 文件ID
权限表
/** model/Permissions.js */const Sequelize = require('sequelize');const defaultInit = require('./config/default')const Model = Sequelize.Model;const { Op } = Sequelize;class Permissions extends Model { }/*** 权限表*/module.exports = async (sequelize, force = false) => {Permissions.init({ruleName: {type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'rule_name',},// attributesruleId: {type: Sequelize.INTEGER,// 设置为 false 表示 not nullallowNull: false,field: 'rule_id',unique: true,},ruleType: {type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'rule_type',unique: true,},...defaultInit}, {charset: 'utf8',sequelize,/** 表名称 */tableName: 'permissions',/** 模型名称 */modelName: 'permissions',// options// 此属性约定是否自动创建,createdAt与updatedAttimestamps: false});return Permissions.sync({ force: true }).then(async () => {return {getAll (params) {const where = {};if (params && params.ruleType) {where.ruleType = params.ruleType}return Permissions.findAll({ where: { isDelete: { [Op.ne]: 1 }, ...where } })},createOperatorRule ({ruleId,ruleName,createdBy}) {return Permissions.create({ruleId,ruleName,ruleType: 'operator_rule',createdBy: createdBy,createdAt: new Date()})},createMenuRule ({ruleId,ruleName,createdBy}) {return Permissions.create({ruleId,ruleName,ruleType: 'menu_rule',createdBy: createdBy,createdAt: new Date()})},createPageItemRule ({ruleId,ruleName,createdBy}) {return Permissions.create({ruleId,ruleName,ruleType: 'page_item_rule',createdBy: createdBy,createdAt: new Date()})},createFileRule ({ruleId,ruleName,createdBy}) {return Permissions.create({ruleId,ruleName,ruleType: 'file_rule',createdBy: createdBy,createdAt: new Date()})}}})}
权限操作关联表
/** model/PermissionsRelative.js */const Sequelize = require('sequelize');const defaultInit = require('./config/default')const Model = Sequelize.Model;const { Op } = Sequelize;class PermissionsRelative extends Model { }/*** 权限表与操作表的关联表*/module.exports = async (sequelize, force = false) => {PermissionsRelative.init({// attributesruleId: {type: Sequelize.INTEGER,// 设置为 false 表示 not nullallowNull: false,field: 'rule_id',},operatorCode: { // 功能操作编码type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'operator_code',},...defaultInit}, {charset: 'utf8',sequelize,/** 表名称 */tableName: 'PermissionsRelative_operator_relation',/** 模型名称 */modelName: 'PermissionsRelative_operator_relation',// options// 此属性约定是否自动创建,createdAt与updatedAttimestamps: false});return PermissionsRelative.sync({ force: true }).then(async () => {return {getAll (params) {const where = {};if (params && params.ids) {where.ruleId = { [Op.in]: params.ids }}if (params && params.ruleType) {where.ruleType = params.ruleType}return PermissionsRelative.findAll({ where: { isDelete: { [Op.ne]: 1 }, ...where } })},create ({id,code,createdBy}) {return PermissionsRelative.create({ruleId: id,operatorCode: code,createdBy: createdBy,createdAt: new Date()})}}})}
功能操作表
/** model/FunctionOperator.js */const Sequelize = require('sequelize');const defaultInit = require('./config/default')const Model = Sequelize.Model;const { Op } = Sequelize;class FunctionOperator extends Model { }/*** 功能操作表** 查询路径的规则,表示在开始位置命中,或在中间位置命中* `${operatorId}-%` || `%-${operatorId}-%`*/const rules = {operatorName: 'root',operatorCode: 'root',parentCode: '-',treePath: '-',children: [{operatorName: '应用管理 all',operatorCode: 'application',children: [{operatorName: '应用管理 查看',operatorCode: 'applicationSelect',},{operatorName: '应用管理 新增',operatorCode: 'applicationCreate',},{operatorName: '应用管理 编辑',operatorCode: 'applicationUpdate',},{operatorName: '应用管理 删除',operatorCode: 'applicationDelete',}]},{operatorName: '页面管理 all',operatorCode: 'pages',children: [{operatorName: '页面管理 查看',operatorCode: 'pagesSelect',},{operatorName: '页面管理 新增',operatorCode: 'pagesCreate',},{operatorName: '页面管理 编辑',operatorCode: 'pagesUpdate',},{operatorName: '页面管理 删除',operatorCode: 'pagesDelete',}]},{operatorName: '发布 all',operatorCode: 'yidaWebPublish',children: [{operatorName: '日常发布',operatorCode: 'yidaWebPublishDev',},{operatorName: '预发发布',operatorCode: 'yidaWebPublishStaging',},{operatorName: '线上发布',operatorCode: 'yidaWebPublishProd',},]},]}module.exports = async (sequelize, force = false) => {FunctionOperator.init({// attributesoperatorName: { // 功能操作名称type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'operator_name',unique: true,},operatorCode: { // 功能操作编码type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'operator_code',unique: true,},parentCode: {type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'parent_code',},treePath: {type: Sequelize.STRING,// 设置为 false 表示 not nullallowNull: false,field: 'tree_path',},filterPath: { // 拦截Url前缀type: Sequelize.STRING,// 设置为 false 表示 not nullfield: 'filter_path',},method: { // 拦截 url 请求类型type: Sequelize.STRING,// 设置为 false 表示 not nullfield: 'filter_path',},...defaultInit}, {charset: 'utf8',sequelize,/** 表名称 */tableName: 'function_operator',/** 模型名称 */modelName: 'function_operator',// options// 此属性约定是否自动创建,createdAt与updatedAttimestamps: false});return FunctionOperator.sync({ force: true }).then(async () => {const data = await FunctionOperator.findAll({});const list = [];if (data.length === 0) { // 初始化数据const root = rules;root.createdAt = new Date();root.createdBy = '__system',list.push(root);const loop = (arr, parentCode, treePath) => {arr.forEach((item) => {item.createdAt = root.createdAt;item.createdBy = root.createdBy;item.parentCode = parentCodeitem.treePath = treePath + `-${item.operatorCode}`list.push(item)if (item.children) {loop(item.children,item.operatorCode,item.treePath)}delete item.children})}loop(root.children, root.operatorCode, root.operatorCode)delete root.children;await FunctionOperator.bulkCreate(list)}return {destroy (operatorCodes) {return FunctionOperator.destroy({ where: { operatorCode: { [Op.in]: operatorCodes } } }).then(res => {if (Array.isArray(res) && res.length) {return true}return false});},delete (operatorCodes) {const deletedAt = new Date()return FunctionOperator.update({deletedAt: deletedAt,isDelete: 1}, { where: { operatorCode: { [Op.in]: operatorCodes } }, }).then(res => {if (Array.isArray(res) && res.length) {return true}return false})},getAll: () => {return FunctionOperator.findAll({ where: { isDelete: { [Op.ne]: 1 } } })},update: ({updatedAt,updatedBy,operatorName,filterPath,method,}, operatorCode) => {return FunctionOperator.update({updatedAt,updatedBy,operatorName,filterPath,method,},{ where: { operatorCode: operatorCode } }).then(res => {if (Array.isArray(res) && res.length) {return true}return false})},create: ({createdBy,createdAt,operatorName,operatorCode,filterPath,parentCode,treePath,method}) => {return FunctionOperator.create({createdBy,createdAt,operatorName,operatorCode,filterPath,parentCode,treePath,method})}}})}
权限菜单关联表
权限页面元素关联表
权限文件关联表
查询设计
- 查询用户有哪些角色,查询出 roles (角色List)
- 利用 roles 查询出当前用户的所有权限 rules (权限List)
- 根据具体场景,利用 rules 去查对应 “权限类型”(【菜单,页面元素,文件,功能操作】)的对应权限
题目一:单独的功能权限设计
一、当前我有一个应用表,页面表,要设计出,控制应用表的,查看,编辑,新增,删除,发布的权限。
应用表 : appId,appName
页面表:appId,pageId,pageName
首先,先有应用 【查看,编辑,新增,删除,发布日常,发布线上】六个权限。
根据 应用表 和 功能操作表 设计出一张 “应用功能操作权限表”,
应用功能操作权限表:appId,operatorId,operatorName
用户查询角色,角色查询权限,权限根据“权限类型”去查相关操作(operatorList)。
再去查 “应用功能操作权限表” 看当前应用有没有操作权限。
题目二: 新增功能操作
一、新增一个“功能操作”时,要关联 “权限操作关联表”数据,并新增“权限表”一条数据。
插入一条“功能操作”的数据,插入一条“权限操作关联”的数据,插入一条“权限表”的数据
index.js 入口文件
// 应用管理const ApplicationInit = require('./application');// 页面管理const PagesInit = require('./page');// 发布管理const ApplicationVersionInit = require('./applicationVersion');// 全局 数据源 管理const ApplicationDataSource = require('./applicationDataSource');// 权限表const Permissions = require('./permissions');const PermissionsRelation = require('./permissionsRelation')// 功能表const FunctionOperator = require('./functionOperation');// page历史记录表const pagesSave = require('./pageSave')module.exports = async (sequelize) => {const model = {}const force = false;model.pagesSave = await pagesSave(sequelize, force)model.permissions = await Permissions(sequelize, force)model.PermissionsRelation = await PermissionsRelation(sequelize, force)model.functionOperator = await FunctionOperator(sequelize, force)model.applicationDataSource = await ApplicationDataSource(sequelize, force);model.application = await ApplicationInit(sequelize, force);model.pages = await PagesInit(sequelize, force);model.applicationVersion = await ApplicationVersionInit(sequelize, force);return model}
defaultInit
/** model/config/default.js */const Sequelize = require('sequelize');module.exports = {createdBy: {type: Sequelize.STRING,allowNull: false,field: 'created_by',},updatedBy: {type: Sequelize.STRING,field: 'updated_by'},deletedBy: {type: Sequelize.STRING,field: 'deleted_by'},createdAt: {type: Sequelize.DATE,allowNull: false,field: 'created_at'// allowNull defaults to true},updatedAt: {type: Sequelize.DATE,field: 'updated_at'// allowNull defaults to true},/** 删除时间 */deletedAt: {type: Sequelize.DATE,field: 'deleted_at'},/** 伪删除字段 伪删除字段 1 表示删除 */isDelete: {type: Sequelize.TINYINT,field: 'is_delete',defaultValue: 0}}
