039模块记录(数据)的权限设计(4)
下面显示一下上几节讲的数据权限的具体例子,这些都是我在开发过程中用于测试的数据。首先加入二个权限的数据,代码如下:
// 加入几个模拟的的全局条件
UserGlobalFilter globalFilter = new UserGlobalFilter();
globalFilter.setBaseModule(SystemAndLoginInfoService.getModuleWithName("Orders"));<span style="white-space:pre"> // 基准模块
globalFilter.setFilterModule(SystemAndLoginInfoService.getModuleWithName("Province")); // 加入权限的模块
globalFilter.setFieldAhead("tf_Customer.tf_City.tf_Province"); // 从基准模块到加入权限的模块的路径
List<String> ids = new ArrayList<String>();
ids.add("06");
ids.add("07");
ids.add("08");<span style="white-space:pre"> // 限定的三个值
globalFilter.setKeys(ids);
userSession.getUserGlobalFilters().add(globalFilter);
UserGlobalFilter globalFilter2 = new UserGlobalFilter();
globalFilter2.setBaseModule(SystemAndLoginInfoService.getModuleWithName("Customer"));// 基准模块
globalFilter2.setFilterModule(SystemAndLoginInfoService.getModuleWithName("Rate"));// 加入权限的模块
globalFilter2.setFieldAhead("tf_Rate");// 路径
List<String> ids2 = new ArrayList<String>();
ids2.add("10");
globalFilter2.setKeys(ids2);
userSession.getUserGlobalFilters().add(globalFilter2);<span style="white-space:pre"> // 模块的权限放在用户session中
在上面加入了二个权限的设置,第一个是加在“订单”模块的父模块“省份”之上的,其路径为:客户单位--市--省,第二是加在“客户”的“等级“模块之上,其路径为tf_Rate,这二个同件同时满足。生成的“订单”查询语句如下:
SELECT
(SELECT
COUNT(*)
FROM
_Attachment
WHERE
tf_moduleId = '6040'
AND tf_moduleIdValue = _this.tf_ordersId) AS `tf_attachmentCount`,// 附件张数
GETATTACHMENTNAMES('6040', _this.tf_ordersId) AS `tf_attachmentTooltip`, //附件tooltip
_this.tf_ordersId AS `tf_ordersId`,
_this.tf_ordersNumber AS `tf_ordersNumber`,
(DATE_FORMAT(_this.tf_date, '%Y年%m月')) AS `tf_yearmonth`, // 自定义的计算字段
_this.tf_finished AS `tf_finished`,
_this.tf_remark AS `tf_remark`,
_this_14.tf_cityId AS `tf_FromCity.tf_cityId`,<span style="white-space:pre"> </span>//始发地市id
_this_14.tf_name AS `tf_FromCity.tf_name`,<span style="white-space:pre"> </span>//始发地市名称<span style="white-space:pre"> </span>
_this_12.tf_salesmanId AS `tf_Salesman.tf_salesmanId`,<span style="white-space:pre"> </span>//销售人员id
_this_12.tf_name AS `tf_Salesman.tf_name`,<span style="white-space:pre"> </span>//销售人员名称
_this_13.tf_storageId AS `tf_Storage.tf_storageId`,<span style="white-space:pre"> </span>//商品仓库id
_this_13.tf_name AS `tf_Storage.tf_name`,<span style="white-space:pre"> </span>//商品仓库名称
_this_11.tf_customerId AS `tf_Customer.tf_customerId`,<span style="white-space:pre"> </span>//客户id
_this_11.tf_name AS `tf_Customer.tf_name`,<span style="white-space:pre"> </span>//客户名称
<span style="white-space:pre"> </span>//以上8个字段是当前模块的直接父模块,必须要加入。
//下面的字段都是对于当前基准模块的附加字段,这些字段可以直接显示在grid中或者form中。<pre name="code" class="sql"> (IF(_this_14_21.tf_gdp > 1000,
'gdp大于1000',
'gdp小于1000')) AS `tf_FromCity.tf_Province.tf_calcGDPmap`,<span style="white-space:pre"> </span>//父模块的计算字段
_this_14_21.tf_shortname AS `tf_FromCity.tf_Province.tf_shortname`,<span style="white-space:pre"> </span>//始发地省的简称
_this_14_21.tf_provinceId AS `tf_FromCity.tf_Province.tf_provinceId`, //始地地省id
_this_14_21.tf_name AS `tf_FromCity.tf_Province.tf_name`, //始发地省名称
_this_13_21_31.tf_provinceId AS `tf_Storage.tf_City.tf_Province.tf_provinceId`, //仓库所在省份id
_this_13_21_31.tf_name AS `tf_Storage.tf_City.tf_Province.tf_name` //仓库所在省份名称
FROM
`Orders` AS _this
LEFT OUTER JOIN
`City` `_this_14` ON `_this_14`.tf_cityId = `_this`.tf_fromCityId<span style="white-space:pre"> </span>// 始发地市
LEFT OUTER JOIN
`Province` `_this_14_21` ON `_this_14_21`.tf_provinceId = `_this_14`.tf_provinceId //始发地省
LEFT OUTER JOIN
`Salesman` `_this_12` ON `_this_12`.tf_salesmanId = `_this`.tf_salesmanId // 销售员
LEFT OUTER JOIN
`Storage` `_this_13` ON `_this_13`.tf_storageId = `_this`.tf_storageId // 仓库
LEFT OUTER JOIN
`City` `_this_13_21` ON `_this_13_21`.tf_cityId = `_this_13`.tf_cityId //仓库所在市
LEFT OUTER JOIN
`Province` `_this_13_21_31` ON `_this_13_21_31`.tf_provinceId = `_this_13_21`.tf_provinceId // 仓库所在省
LEFT OUTER JOIN
`Customer` `_this_11` ON `_this_11`.tf_customerId = `_this`.tf_customerId // 客户单位
LEFT OUTER JOIN
`City` `_this_11_21` ON `_this_11_21`.tf_cityId = `_this_11`.tf_cityId //客户单位所在市
LEFT OUTER JOIN
`Province` `_this_11_21_31` ON `_this_11_21_31`.tf_provinceId = `_this_11_21`.tf_provinceId //客户单位所在省
LEFT OUTER JOIN
`Rate` `_this_11_23` ON `_this_11_23`.tf_rateId = `_this_11`.tf_rateId //客户单位等级
LEFT OUTER JOIN
`City` `_this_15` ON `_this_15`.tf_cityId = `_this`.tf_toCityId //目的地市
WHERE
(_this_11_21_31.tf_provinceId IN ('06' , '07', '08'))<span style="white-space:pre"> </span>//加在客户单位的省上面的条件
AND (_this_11_23.tf_rateId IN ('10')) //加在客户单位的等级上面的条件
在上面的sql语中,只加入了必要的表,这些表中有的是有需要的字段,有的有附加字段,还有的是有限定的条件。所有不需要加入的表都不加入。这些sql语句应该是动态生成的,每次请求都有可能是不一样的。例如如果在查询或导航中,需要限定 “目的地省”,那么就又要在from中加入目的地省的模块。但是字段的部分还是不变的。
下面来看一下延展性,在查询订单明细的时候,会是如下的语句:
SELECT
_this.tf_ordersDetailId AS `tf_ordersDetailId`,
_this.tf_name AS `tf_name`,
_this.tf_number AS `tf_number`,
_this.tf_unitPrice AS `tf_unitPrice`,
_this.tf_subtotalPrice AS `tf_subtotalPrice`,
_this.tf_remark AS `tf_remark`,
_this_12.tf_productId AS `tf_Product.tf_productId`,<span style="white-space:pre"> </span>//商品id
_this_12.tf_name AS `tf_Product.tf_name`,<span style="white-space:pre"> </span>//商品名称
_this_11.tf_ordersId AS `tf_Orders.tf_ordersId`,<span style="white-space:pre"> </span>//订单id
_this_11.tf_ordersNumber AS `tf_Orders.tf_ordersNumber`<span style="white-space:pre"> </span>//订单名称
FROM
`OrdersDetail` AS _this
LEFT OUTER JOIN
`Product` `_this_12` ON `_this_12`.tf_productId = `_this`.tf_productId<span style="white-space:pre"> </span>//商品
LEFT OUTER JOIN
`Orders` `_this_11` ON `_this_11`.tf_ordersId = `_this`.tf_ordersId<span style="white-space:pre"> </span>//订单
LEFT OUTER JOIN
`Customer` `_this_11_21` ON `_this_11_21`.tf_customerId = `_this_11`.tf_customerId<span style="white-space:pre"> </span>//客户
LEFT OUTER JOIN
`City` `_this_11_21_31` ON `_this_11_21_31`.tf_cityId = `_this_11_21`.tf_cityId<span style="white-space:pre"> </span>//客户市
LEFT OUTER JOIN
`Province` `_this_11_21_31_41` ON `_this_11_21_31_41`.tf_provinceId = `_this_11_21_31`.tf_provinceId //客户省
LEFT OUTER JOIN
`Rate` `_this_11_21_33` ON `_this_11_21_33`.tf_rateId = `_this_11_21`.tf_rateId<span style="white-space:pre"> </span>//客户等级
WHERE
(_this_11_21_31_41.tf_provinceId IN ('06' , '07', '08')) //附加在订单上的权限
AND (_this_11_21_33.tf_rateId IN ('10'))<span style="white-space:pre"> </span><span style="font-family: Arial, Helvetica, sans-serif;">//附加在订单上的权限</span>
在上面的sql语句中,由于没有加入附加字段,因此加入到form子句中的父模块会比较小,只加了必须的模块。
下面看一下查询客户的语句:
SELECT
_this.tf_customerId AS `tf_customerId`,
_this.tf_name AS `tf_name`,
_this.tf_address AS `tf_address`,
_this.tf_linkman AS `tf_linkman`,
_this.tf_linkmanTel AS `tf_linkmanTel`,
_this.tf_taxId AS `tf_taxId`,
_this.tf_remark AS `tf_remark`,
_this_12.tf_tradeId AS `tf_Trade.tf_tradeId`,
_this_12.tf_name AS `tf_Trade.tf_name`,
_this_11.tf_cityId AS `tf_City.tf_cityId`,
_this_11.tf_name AS `tf_City.tf_name`,
_this_13.tf_rateId AS `tf_Rate.tf_rateId`,
_this_13.tf_name AS `tf_Rate.tf_name`
FROM
`Customer` AS _this
LEFT OUTER JOIN
`Trade` `_this_12` ON `_this_12`.tf_tradeId = `_this`.tf_tradeId
LEFT OUTER JOIN
`City` `_this_11` ON `_this_11`.tf_cityId = `_this`.tf_cityId
LEFT OUTER JOIN
`Rate` `_this_13` ON `_this_13`.tf_rateId = `_this`.tf_rateId
WHERE
(_this_13.tf_rateId IN ('10'))
在这个语句中,只有限定了客户是金牌客户这个条件,并没有加入三个省份。因为这三个省份是加在基准模块是“订单”上的。如果将第一个条件的基准模块改为“客户”那么也会加入省份的限定条件。而这时订单也会继承客户的限定条件。
在取得模块数据之前,先要编译一下满足当前条件记录数。在取得记录数的时候,只要加入有权限的父模块就行了。有附加字段的都不要加入。如要统计当前权限下的所有可以看到的订单个数:
select count(*)
from
`Orders` as _this
left outer join `Customer` `_this_11` on `_this_11`.tf_customerId = `_this`.tf_customerId
left outer join `City` `_this_11_21` on `_this_11_21`.tf_cityId = `_this_11`.tf_cityId
left outer join `Province` `_this_11_21_31` on `_this_11_21_31`.tf_provinceId = `_this_11_21`.tf_provinceId
left outer join `Rate` `_this_11_23` on `_this_11_23`.tf_rateId = `_this_11`.tf_rateId
where
(_this_11_21_31.tf_provinceId in ('06' , '07' , '08'))
and
(_this_11_23.tf_rateId in ('10'))
以上即为本系统中关于模块记录权限的主要设计思想和实现的方法。我现在也正在想更加完善的方法,如果有建议或意见请跟贴回复,谢谢。