036模块记录(数据)的权限设计与实现(1)
最近正在更新权限系统,主要是模块记录数据的权限如何方便的自定义设计。这几天刚把底层的一些东西弄好,把实现过程写一下供大家参考,顺便也自己做个备忘录。
在前面二章中写了一下模块关联关系的一些内容,模块记录权限的设计也是以模块的关联关系为基础。下面我们再按照上面的模块结构图来进行设计权限。在这个模拟的订单系统中,主要处理的模块是订单和订单明细。以订单为基准的模块关联关系图如下:
在上图中,订单有各种父模块和子模块。我们要设计的权限就是为了限定订单的记录数据。如系统中有如下各种权限的设置:
1、某客户单位专员只管理着指定的二个单位的订单;
2、有一个客户单位专员,分管着三个省的客户,他只能看到这三个省的订单;
3、客户等级分为金、银、铜牌客户,另一个金牌客户专员,只能看到所有金牌客户单位的订单;
4、还有一个员工的操作权限为上述二个权限的交集,分管着三个省的金牌客户;
5、每个市的仓库管理员可以看到该市商品仓库的订单;
6、某个订单发货员只要看到未发货的订单;
7、大订单管理员只要查看总金额大于100万的订单;
下面来分析一下各个用户权限的设置:
第1个客户单位专员,管着二个单位,比如说这二个单位的编码是1,2,客户单位的id字段为tf_customerId, 那么在生成订单数据的时候,需要在where子句中加入 Customer.tf_customerId in (1,2)这个条件,由于订单的客户单位只有一次,所以这个条件加入没什么问题。
第2个客户专员,分管着三个省,比如说三个省的代码为 06,07,08,省份的id字段为tf_provinceId,那么需要把权限加在省上,在select客户的语句中肯定要在 where子句中要加上 Province.tf_provinceId in ('06','07','08')。这个权限的加入就会比上一个有些麻烦了,因为在上图中订单的父模块“省份”一共有四个,需要有一个路径来确定是哪一个省份,这个路径就是 客户单位--市--省。因此在这个select 语句中就要加入这三个父模块。语句可能如下面的描述。
select 订单.*
from 订单
left outter join 客户单位 on 订单.客户单位id = 客户单位.客户单位id
left outter join 市 on 客户单位.市id = 市.市id
left outter join 省 on 市.省id = 省.省id
where 省.tf_customerId in ('06','07','08')
第3个金牌客户专员与上面一个类似,查询语句如下
select 订单.*
from 订单
left outter join 客户单位 on 订单.客户单位id = 客户单位.客户单位id
left outter join 等级 on 客户单位.等级id = 等级.等级id
where 等级.等级Id in (1)
第4个用户的权限为二面二个的交集,查询语句如下
select 订单.*
from 订单
left outter join 客户单位 on 订单.客户单位id = 客户单位.客户单位id
left outter join 市 on 客户单位.市id = 市.市id
left outter join 省 on 市.省id = 省.省id
left outter join 等级 on 客户单位.等级id = 等级.等级id
where 省.tf_customerId in (06','07','08') and 等级.等级Id in (1)
第5个用户的权限为市 0601 下面的仓库的订单,在指定了市以后,还要指定订单到市的路径为:商品仓库--市
select 订单.*
from 订单
left outter join 商品仓库 on 订单.商品仓库id = 商品仓库.商品仓库id
left outter join 市 on 商品仓库.市id = 市.市id
where 市.市id in ('0601')
前面5个权限都是加在父模块的主键之上的,权限也可以加在其他字段上,可以是某个表达式。比如说 "省份GPD > 1000亿" 可以作为一个限定条件,或者说 订单的“状态” 可以作为一个限定条件。
第6个是要把权限加在一个非主键字段上。可以在where中加上条件 订单.状态 = '未发货'。
第7个条件可以将一个聚合的字段作为限定条件。查询语句可以如下:
select 订单.*
from 订单
where (select sum(订单明细.金额) from 订单明细 where 订单id = 订单.订单id) > 1000000
在一个需要权限的系统中,如果权限的设置不是自定义和自动生成sql语句的话,那么对于每个用户权限都要自己手工写上述的查询语句,这将会对权限扩充和维护带来麻烦。因此在我的系统中,可以将上述的权限用具体的规则描述之后,在生成查询语句的时候可以自动加入该用户每个模块记录的限定条件。
还有一个非常重要的就是权限的延展性,在给订单限定了某个条件之后,如果要查询订单的子模块,比如说订单明细,那么这些条件会自动加到子模块上面。另外在进行聚合查询的时候也要把相应的权限全部加进去。
如果有二个父模块那么其权限是其子集,也就是and 。至于能不能使用并集(or)正在考虑之中。就象上述第4个权限是某三个省的金牌客户。如果要加入权限“某三个省或者是金牌客户”则现在暂时不支持,如果有这样的需求,需要想其他办法,例如给客户模块加一个新的字段,然后在这个主面加入权限。