diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/UserAttachEntity.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/UserAttachEntity.java new file mode 100644 index 000000000..c3e3f4b65 --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/access/UserAttachEntity.java @@ -0,0 +1,20 @@ +package org.hswebframework.web.authorization.access; + + +/** + * 和user关联的实体 + * + * @author zhouhao + * @since 3.0.6 + */ +public interface UserAttachEntity { + String userId = "userId"; + + String getUserId(); + + void setUserId(String userId); + + default String getUserIdProperty() { + return userId; + } +} diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresDataAccess.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresDataAccess.java index ab87fd8ae..1f763f708 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresDataAccess.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresDataAccess.java @@ -43,7 +43,6 @@ public @interface RequiresDataAccess { /** * @return permission id ,如果为空将继承 {@link Authorize#permission()} * @see Permission#getId() - * */ String permission() default ""; @@ -82,4 +81,9 @@ public @interface RequiresDataAccess { */ boolean ignore() default false; + /** + * @return 进行控制的实体类类型 + * @since 3.0.6 + */ + Class entityType() default Void.class; } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java index 817de7a94..3b297e35f 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java @@ -4,7 +4,6 @@ package org.hswebframework.web.authorization.define; import java.io.Serializable; /** - * * @author zhouhao * @see org.hswebframework.web.authorization.annotation.RequiresDataAccess */ @@ -14,6 +13,8 @@ public interface DataAccessDefinition extends Serializable { String getIdParameterName(); + Class getEntityType(); + Phased getPhased(); } diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java index c66f83a38..06dfd1cc2 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java @@ -101,6 +101,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition { } actions.addAll(Arrays.asList(dataAccess.action())); DefaultDataAccessDefinition definition = new DefaultDataAccessDefinition(); + definition.setEntityType(dataAccess.entityType()); definition.setPhased(dataAccess.phased()); if (!"".equals(dataAccess.controllerBeanName())) { definition.setController(dataAccess.controllerBeanName()); @@ -108,7 +109,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition { definition.setController(dataAccess.getClass().getName()); } dataAccessDefinition = definition; - dataAccessControl=true; + dataAccessControl = true; } diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultDataAccessDefinition.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultDataAccessDefinition.java index c7c7f9422..a0482cb48 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultDataAccessDefinition.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultDataAccessDefinition.java @@ -18,7 +18,9 @@ public class DefaultDataAccessDefinition implements DataAccessDefinition { private String controller; - private String idParameterName="id"; + private String idParameterName = "id"; + + private Class entityType; private Phased phased; } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java index 0b05d6348..b972e424c 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/entity/authorization/DataAccessEntity.java @@ -1,11 +1,19 @@ package org.hswebframework.web.entity.authorization; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import org.hswebframework.web.commons.entity.CloneableEntity; /** * @author zhouhao */ +@Getter +@Setter +@EqualsAndHashCode public class DataAccessEntity implements CloneableEntity { + private static final long serialVersionUID = 2198771924746804915L; + private String action; private String describe; @@ -14,38 +22,6 @@ public class DataAccessEntity implements CloneableEntity { private String config; - public String getAction() { - return this.action; - } - - public void setAction(String action) { - this.action = action; - } - - public String getDescribe() { - return this.describe; - } - - public void setDescribe(String describe) { - this.describe = describe; - } - - public String getType() { - return this.type; - } - - public void setType(String type) { - this.type = type; - } - - public String getConfig() { - return this.config; - } - - public void setConfig(String config) { - this.config = config; - } - @Override public DataAccessEntity clone() { DataAccessEntity target = new DataAccessEntity(); diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/PersonEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/PersonEntity.java index ab489f5f5..dbe703806 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/PersonEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/PersonEntity.java @@ -16,15 +16,17 @@ */ package org.hswebframework.web.entity.organizational; +import org.hswebframework.web.authorization.access.UserAttachEntity; import org.hswebframework.web.commons.entity.GenericEntity; import org.hswebframework.web.commons.entity.RecordCreationEntity; +import org.hswebframework.web.organizational.authorization.access.PersonAttachEntity; /** * 人员 实体 * * @author hsweb-generator-online */ -public interface PersonEntity extends GenericEntity { +public interface PersonEntity extends GenericEntity, PersonAttachEntity, UserAttachEntity { /*------------------------------------------ | 属性名常量 | =========================================*/ @@ -141,4 +143,18 @@ public interface PersonEntity extends GenericEntity { */ void setRemark(String remark); + @Override + default String getPersonId() { + return getId(); + } + + @Override + default void setPersonId(String personId) { + setId(personId); + } + + @Override + default String getPersonIdProperty() { + return "id"; + } } \ No newline at end of file diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java index 2b973a465..832926ea6 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java @@ -1,8 +1,8 @@ package org.hswebframework.web.organizational.authorization.simple; -import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import org.hswebframework.web.authorization.simple.AbstractDataAccessConfig; import java.util.Set; @@ -13,7 +13,7 @@ import java.util.Set; */ @Getter @Setter -@EqualsAndHashCode(callSuper = true) +@ToString public class ScopeByUserDataAccessConfig extends AbstractDataAccessConfig { private static final long serialVersionUID = 6678003761927318688L; @@ -30,4 +30,15 @@ public class ScopeByUserDataAccessConfig extends AbstractDataAccessConfig { public String getType() { return "SCOPE_BY_USER"; } + + @Override + public int hashCode() { + return (toString() + getAction()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof ScopeByUserDataAccessConfig && obj.hashCode() == hashCode(); + } + } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java index 58e59a0f7..885f976e7 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java @@ -3,25 +3,28 @@ package org.hswebframework.web.organizational.authorization.simple.handler; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.hswebframework.ezorm.core.dsl.Query; import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.authorization.Permission; +import org.hswebframework.web.authorization.User; import org.hswebframework.web.authorization.access.DataAccessConfig; import org.hswebframework.web.authorization.access.DataAccessHandler; +import org.hswebframework.web.authorization.access.UserAttachEntity; import org.hswebframework.web.authorization.define.AuthorizingContext; import org.hswebframework.web.authorization.define.Phased; import org.hswebframework.web.authorization.exception.AccessDenyException; import org.hswebframework.web.authorization.exception.UnAuthorizedException; import org.hswebframework.web.bean.FastBeanCopier; import org.hswebframework.web.commons.entity.Entity; +import org.hswebframework.web.commons.entity.PagerResult; import org.hswebframework.web.commons.entity.RecordCreationEntity; import org.hswebframework.web.commons.entity.factory.EntityFactory; import org.hswebframework.web.commons.entity.param.QueryParamEntity; import org.hswebframework.web.controller.QueryController; import org.hswebframework.web.controller.message.ResponseMessage; import org.hswebframework.web.organizational.authorization.PersonnelAuthentication; -import org.hswebframework.web.organizational.authorization.PersonnelAuthenticationHolder; import org.hswebframework.web.organizational.authorization.access.*; import org.hswebframework.web.organizational.authorization.simple.ScopeByUserDataAccessConfig; import org.hswebframework.web.service.QueryService; @@ -30,6 +33,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -66,14 +70,19 @@ public class ScopeByUserHandler implements DataAccessHandler { } protected boolean doUpdateAccess(ScopeByUserDataAccessConfig config, AuthorizingContext context) { - //获取注解 + //获取id参数 Object id = context.getParamContext() .getParameter(context.getDefinition().getDataAccessDefinition().getIdParameterName()) .orElse(null); if (id == null) { return true; } - PersonnelAuthentication authentication = PersonnelAuthentication.current().orElseThrow(UnAuthorizedException::new); + PersonnelAuthentication authentication = PersonnelAuthentication + .current().orElse(null); + if (authentication == null) { + log.warn("当前用户没有关联人员信息!"); + return false; + } ScopeInfo scopeInfo = getScope(config, authentication); if (scopeInfo.isEmpty()) { return false; @@ -101,10 +110,10 @@ public class ScopeByUserHandler implements DataAccessHandler { Object entity = queryService.selectByPk(id); if (null != entity) { String targetId = controllerCache.targetIdGetter.apply(entity); - log.debug("执行数据权限控制,scope:{},target:{}", scopeInfo.scope, targetId); if (targetId == null) { return true; } + log.debug("执行数据权限控制,范围:{},结果:{}", scopeInfo.scope, targetId); return scopeInfo.allScope.contains(controllerCache.targetIdGetter.apply(entity)); } } else { @@ -114,8 +123,9 @@ public class ScopeByUserHandler implements DataAccessHandler { } + @SneakyThrows private ScopeInfo getScope(ScopeByUserDataAccessConfig config, PersonnelAuthentication authentication) { - String termType = null; + String termType = null, personTermType = "in"; Set scope = null, allScope = null; ScopeInfo scopeInfo = new ScopeInfo(); if (authentication == null) { @@ -124,43 +134,65 @@ public class ScopeByUserHandler implements DataAccessHandler { Consumer> consumer; switch (config.getScopeType()) { + case "OWN_PERSON": + termType = "in"; + scope = Collections.singleton(authentication.getPersonnel().getId()); + allScope = scope; + break; + case "OWN_USER": + termType = "in"; + scope = Collections.singleton(Authentication + .current() + .map(Authentication::getUser) + .map(User::getId) + .orElseThrow(AccessDenyException::new)); + allScope = scope; + break; case DataAccessType.ORG_SCOPE: termType = "user-in-org"; + personTermType = "person-in-org"; scope = authentication.getRootOrgId(); allScope = config.isChildren() ? authentication.getAllOrgId() : scope; break; case DataAccessType.DEPARTMENT_SCOPE: termType = "user-in-department"; + personTermType = "person-in-department"; scope = authentication.getRootDepartmentId(); allScope = config.isChildren() ? authentication.getAllDepartmentId() : scope; break; case DataAccessType.POSITION_SCOPE: termType = "user-in-position"; + personTermType = "person-in-position"; scope = authentication.getRootPositionId(); allScope = config.isChildren() ? authentication.getAllPositionId() : scope; break; case DataAccessType.DISTRICT_SCOPE: termType = "user-in-dist"; + personTermType = "person-in-dist"; scope = authentication.getRootDistrictId(); allScope = config.isChildren() ? authentication.getAllDistrictId() : scope; break; case "CUSTOM_SCOPE_ORG": termType = "user-in-org"; + personTermType = "person-in-org"; scope = config.getScope(); allScope = scope; break; case "CUSTOM_SCOPE_POSITION": termType = "user-in-position"; + personTermType = "person-in-position"; scope = config.getScope(); allScope = scope; break; case "CUSTOM_SCOPE_DEPT": termType = "user-in-department"; + personTermType = "person-in-department"; scope = config.getScope(); allScope = scope; break; case "CUSTOM_SCOPE_DIST": termType = "user-in-dist"; + personTermType = "person-in-dist"; scope = config.getScope(); allScope = scope; break; @@ -174,7 +206,12 @@ public class ScopeByUserHandler implements DataAccessHandler { scopeInfo.allScope = new ArrayList<>(allScope); scopeInfo.termType = termType; if (config.isChildren()) { - scopeInfo.termType = termType + termType.concat("-child"); + if (!termType.equals("in")) { + scopeInfo.termType = termType.concat("-child"); + } + if (!personTermType.equals("in")) { + scopeInfo.personTermType = personTermType.concat("-child"); + } } return scopeInfo; @@ -182,6 +219,7 @@ public class ScopeByUserHandler implements DataAccessHandler { class ScopeInfo { String termType; + String personTermType; List scope; List allScope; @@ -194,11 +232,33 @@ public class ScopeByUserHandler implements DataAccessHandler { } static Function defaultTargetIdGetter = entity -> { - Map userInfo = FastBeanCopier.copy(entity, new HashMap<>(), - FastBeanCopier.include("creatorId")); - return userInfo.get("creatorId"); + Map userInfo = FastBeanCopier.copy(entity, new HashMap<>(), FastBeanCopier.include("creatorId", "userId")); + return userInfo.getOrDefault("userId", userInfo.get("creatorId")); }; + protected Function createTargetIdGetter(Class entityClass, String... properties) { + String useProperty = null; + for (String property : properties) { + Field field = ReflectionUtils.findField(entityClass, property); + if (field != null) { + useProperty = property; + } + } + if (useProperty == null) { + log.warn("类[{}]中未包含字段[{}],可能无法进行数据权限控制.", entityClass, Arrays.asList(properties)); + } + return entity -> { + Map userInfo = FastBeanCopier.copy(entity, new HashMap<>(), FastBeanCopier.include(properties)); + for (String property : properties) { + String value = userInfo.get(property); + if (value != null) { + return value; + } + } + return null; + }; + } + static BiConsumer, ScopeInfo> defaultQueryConsumer = (query, scopeInfo) -> { query.and("creatorId", scopeInfo.termType, scopeInfo.scope); }; @@ -237,59 +297,91 @@ public class ScopeByUserHandler implements DataAccessHandler { class CacheKey { private String className; + private String method; + private boolean children; private String type; + + private boolean queryController; } static Map cacheMap = new ConcurrentHashMap<>(); private ControllerCache getControllerCache(ScopeByUserDataAccessConfig config, AuthorizingContext context) { + Class controller = ClassUtils.getUserClass(context.getParamContext().getTarget().getClass()); CacheKey cacheKey = new CacheKey(); cacheKey.children = config.isChildren(); - cacheKey.className = ClassUtils.getUserClass(context.getParamContext().getTarget().getClass()).getName(); + cacheKey.className = controller.getName(); + cacheKey.method = context.getParamContext().getMethod().toString(); cacheKey.type = config.getScopeType(); + cacheKey.queryController = context.getParamContext().getTarget() instanceof QueryController; + Class dataAccessEntityType = context.getDefinition().getDataAccessDefinition().getEntityType(); + return cacheMap.computeIfAbsent(cacheKey, key -> { ControllerCache controllerCache = new ControllerCache(); - if (context.getParamContext().getTarget() instanceof QueryController) { - boolean children = config.isChildren(); - Class controller = ClassUtils.getUserClass(context.getParamContext().getTarget().getClass()); - Class entityClass = org.hswebframework.utils.ClassUtils.getGenericType(controller, 0); - if (OrgAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("ORG")) { - controllerCache.targetIdGetter = createGetter(OrgAttachEntity.class, OrgAttachEntity::getOrgId); + Class entityClass = dataAccessEntityType; + if (entityClass == Void.class) { + if (cacheKey.queryController) { + entityClass = org.hswebframework.utils.ClassUtils.getGenericType(controller, 0); + } + } + boolean children = cacheKey.isChildren(); + //控制机构 + if (cacheKey.getType().contains("ORG") && OrgAttachEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, OrgAttachEntity::getOrgIdProperty); + controllerCache.targetIdGetter = createGetter(OrgAttachEntity.class, OrgAttachEntity::getOrgId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(property, children ? "org-child-in" : "in", scopeInfo.scope); + }; + //部门 + } else if (cacheKey.getType().contains("DEPT") && DepartmentAttachEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, DepartmentAttachEntity::getDepartmentIdProperty); + controllerCache.targetIdGetter = createGetter(DepartmentAttachEntity.class, DepartmentAttachEntity::getDepartmentId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(property, children ? "org-child-in" : "in", scopeInfo.scope); + }; + //岗位 + } else if (cacheKey.getType().contains("POS") && PositionAttachEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, PositionAttachEntity::getPositionIdProperty); + controllerCache.targetIdGetter = createGetter(PositionAttachEntity.class, PositionAttachEntity::getPositionId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(property, children ? "pos-child-in" : "in", scopeInfo.scope); + }; + //行政区划 + } else if (cacheKey.getType().contains("DIST") && DistrictAttachEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, DistrictAttachEntity::getDistrictIdProperty); + controllerCache.targetIdGetter = createGetter(DistrictAttachEntity.class, DistrictAttachEntity::getDistrictId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(property, children ? "dist-child-in" : "in", scopeInfo.scope); + }; + //人员 + } else if (cacheKey.getType().contains("PERSON") && PersonAttachEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, PersonAttachEntity::getPersonIdProperty); + controllerCache.targetIdGetter = createGetter(PersonAttachEntity.class, PersonAttachEntity::getPersonId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(property, scopeInfo.termType, scopeInfo.scope); + }; + //根据用户控制 + } else { + if (UserAttachEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, UserAttachEntity::getUserIdProperty); + controllerCache.targetIdGetter = createGetter(UserAttachEntity.class, UserAttachEntity::getUserId); controllerCache.queryConsumer = (query, scopeInfo) -> { - query.and(getControlProperty(entityClass, OrgAttachEntity::getOrgIdProperty), children ? "org-child-in" : "in", scopeInfo.scope); - }; - } else if (DepartmentAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("DEPT")) { - controllerCache.targetIdGetter = createGetter(DepartmentAttachEntity.class, DepartmentAttachEntity::getDepartmentId); - controllerCache.queryConsumer = (query, scopeInfo) -> { - query.and(getControlProperty(entityClass, DepartmentAttachEntity::getDepartmentIdProperty), children ? "dept-child-in" : "in", scopeInfo.scope); - }; - } else if (PositionAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("POS")) { - controllerCache.targetIdGetter = createGetter(PositionAttachEntity.class, PositionAttachEntity::getPositionId); - controllerCache.queryConsumer = (query, scopeInfo) -> { - query.and(getControlProperty(entityClass, PositionAttachEntity::getPositionIdProperty), children ? "pos-child-in" : "in", scopeInfo.scope); - }; - } else if (DistrictAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("DIST")) { - controllerCache.targetIdGetter = createGetter(DistrictAttachEntity.class, DistrictAttachEntity::getDistrictId); - controllerCache.queryConsumer = (query, scopeInfo) -> { - query.and(getControlProperty(entityClass, DistrictAttachEntity::getDistrictIdProperty), children ? "dist-child-in" : "in", scopeInfo.scope); + query.and(property, scopeInfo.termType, scopeInfo.scope); }; } else if (RecordCreationEntity.class.isAssignableFrom(entityClass)) { + String property = getControlProperty(entityClass, RecordCreationEntity::getCreatorIdProperty); controllerCache.targetIdGetter = createGetter(RecordCreationEntity.class, RecordCreationEntity::getCreatorId); controllerCache.queryConsumer = (query, scopeInfo) -> { - query.and(getControlProperty(entityClass, RecordCreationEntity::getCreatorIdProperty), scopeInfo.termType, scopeInfo.scope); + query.and(property, scopeInfo.termType, scopeInfo.scope); }; } else { - String userIdField = getUserField(entityClass); - controllerCache.targetIdGetter = entity -> { - Map userInfo = FastBeanCopier.copy(entity, new HashMap<>(), - FastBeanCopier.include(userIdField)); - return userInfo.get(userIdField); - }; + String property = getUserField(entityClass); + controllerCache.targetIdGetter = createTargetIdGetter(entityClass, property); controllerCache.queryConsumer = (query, scopeInfo) -> { - query.and(userIdField, scopeInfo.termType, scopeInfo.scope); + query.and(property, scopeInfo.termType, scopeInfo.scope); }; } } @@ -313,18 +405,24 @@ public class ScopeByUserHandler implements DataAccessHandler { if (result == null) { return true; } - if (result instanceof ResponseEntity) { - result = ((ResponseEntity) result).getBody(); + result = getRealResult(result); + Predicate predicate = (o) -> { + String value = controllerCache.targetIdGetter.apply(o); + if (value == null) { + return true; + } + log.debug("执行数据权限控制[{}],scope:{},target:{}", config.getScopeTypeName(), scopeInfo.scope, value); + return scopeInfo.allScope.contains(value); + }; + if (result instanceof Collection) { + Collection res = ((Collection) result); + if (res.isEmpty()) { + return true; + } + return res.stream().allMatch(predicate); + } else { + return predicate.test(result); } - if (result instanceof ResponseMessage) { - result = ((ResponseMessage) result).getResult(); - } - String value = controllerCache.targetIdGetter.apply(result); - log.debug("执行数据权限控制[{}],scope:{},target:{}", config.getScopeTypeName(), scopeInfo.scope, value); - if (value == null) { - return true; - } - return scopeInfo.allScope.contains(value); } Entity entity = context.getParamContext() @@ -339,9 +437,11 @@ public class ScopeByUserHandler implements DataAccessHandler { if (entity instanceof QueryParamEntity) { QueryParamEntity param = ((QueryParamEntity) entity); param.toNestQuery(query -> { - log.debug("执行查询数据权限控制[{}],scope:{}", config.getScopeTypeName(), scopeInfo.scope); + log.debug("执行查询数据权限控制[{}],范围:{}", config.getScopeTypeName(), scopeInfo.scope); controllerCache.queryConsumer.accept(query, scopeInfo); }); + } else { + log.warn("方法[{}]未使用动态查询参数[QueryParamEntity],无法进行数据权限控制!", context.getParamContext().getMethod()); } return true; } @@ -354,4 +454,17 @@ public class ScopeByUserHandler implements DataAccessHandler { return "creatorId"; } + + protected Object getRealResult(Object result) { + if (result instanceof ResponseEntity) { + result = ((ResponseEntity) result).getBody(); + } + if (result instanceof ResponseMessage) { + result = ((ResponseMessage) result).getResult(); + } + if (result instanceof PagerResult) { + result = ((PagerResult) result).getData(); + } + return result; + } }