From cf20178cfbe157ba9d894c84279c81f7e27287fe Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 21 Dec 2018 18:13:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ultAopMethodAuthorizeDefinitionParser.java | 4 +- .../DefaultBasicAuthorizeDefinition.java | 1 + .../commons/entity/RecordCreationEntity.java | 4 + .../organizational/OrganizationalEntity.java | 10 +- .../entity/organizational/PersonEntity.java | 7 +- ...ationalAuthorizationAutoConfiguration.java | 12 + .../access/DepartmentAttachEntity.java | 4 + .../access/DistrictAttachEntity.java | 4 + .../authorization/access/OrgAttachEntity.java | 4 + .../access/PersonAttachEntity.java | 4 + .../access/PositionAttachEntity.java | 4 + .../simple/ScopeByUserDataAccessConfig.java | 30 ++ .../ScopeByUserDataAccessConfigConvert.java | 35 ++ .../AbstractScopeDataAccessHandler.java | 27 +- .../simple/handler/CustomScopeHandler.java | 2 - .../simple/handler/ScopeByUserHandler.java | 342 ++++++++++++++++++ .../organizational/PersonController.java | 3 +- 17 files changed, 474 insertions(+), 23 deletions(-) create mode 100644 hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java create mode 100644 hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfigConvert.java create mode 100644 hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java index 9c39262e5..97b86ecbe 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java @@ -100,15 +100,13 @@ public class DefaultAopMethodAuthorizeDefinitionParser implements AopMethodAutho authorizeDefinition.put(expression); - if (methodAuth != null) { - authorizeDefinition.put(methodAuth.dataAccess()); - } authorizeDefinition.put(classDataAccess); authorizeDefinition.put(methodDataAccess); if (authorizeDefinition.getPermissionDescription().length == 0) { if (classAuth != null) { + authorizeDefinition.put(classAuth.dataAccess()); String[] desc = classAuth.description(); if (desc.length > 0) { authorizeDefinition.setPermissionDescription(desc); 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 7666e63f2..c66f83a38 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 @@ -82,6 +82,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition { } message = authorize.message(); phased = authorize.phased(); + put(authorize.dataAccess()); } public void put(RequiresExpression expression) { diff --git a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/RecordCreationEntity.java b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/RecordCreationEntity.java index 91798460f..68e816f90 100644 --- a/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/RecordCreationEntity.java +++ b/hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/RecordCreationEntity.java @@ -23,4 +23,8 @@ public interface RecordCreationEntity extends Entity { default void setCreateTimeNow() { setCreateTime(System.currentTimeMillis()); } + + default String getCreatorIdProperty() { + return creatorId; + } } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/OrganizationalEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/OrganizationalEntity.java index 1577843aa..1e4bc45a5 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/OrganizationalEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/OrganizationalEntity.java @@ -1,18 +1,18 @@ /* * Copyright 2016 http://www.hswebframework.org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ package org.hswebframework.web.entity.organizational; @@ -125,4 +125,8 @@ public interface OrganizationalEntity extends TreeSortSupportEntity, Dis default void setOrgId(String orgId) { setId(orgId); } + + default String getOrgIdProperty() { + return "id"; + } } \ No newline at end of file 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 afe657301..7a9666855 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 @@ -1,22 +1,23 @@ /* * Copyright 2016 http://www.hswebframework.org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ package org.hswebframework.web.entity.organizational; import org.hswebframework.web.commons.entity.GenericEntity; +import org.hswebframework.web.commons.entity.RecordCreationEntity; /** * 人员 实体 diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/OrganizationalAuthorizationAutoConfiguration.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/OrganizationalAuthorizationAutoConfiguration.java index b29d7507d..9828f3134 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/OrganizationalAuthorizationAutoConfiguration.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/OrganizationalAuthorizationAutoConfiguration.java @@ -65,6 +65,18 @@ public class OrganizationalAuthorizationAutoConfiguration implements BeanPostPro return new CustomScopeDataAccessConfigConvert(); } + @Bean + @ConditionalOnMissingBean(ScopeByUserDataAccessConfigConvert.class) + public ScopeByUserDataAccessConfigConvert scopeByUserDataAccessConfigConvert() { + return new ScopeByUserDataAccessConfigConvert(); + } + + @Bean + @ConditionalOnMissingBean(ScopeByUserHandler.class) + public ScopeByUserHandler scopeByUserHandler() { + return new ScopeByUserHandler(); + } + @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DepartmentAttachEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DepartmentAttachEntity.java index 7ed22578d..7b7dcdb29 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DepartmentAttachEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DepartmentAttachEntity.java @@ -21,4 +21,8 @@ public interface DepartmentAttachEntity extends Entity { String getDepartmentId(); void setDepartmentId(String departmentId); + + default String getDepartmentIdProperty() { + return departmentId; + } } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DistrictAttachEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DistrictAttachEntity.java index 9a577903a..294556439 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DistrictAttachEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DistrictAttachEntity.java @@ -11,4 +11,8 @@ public interface DistrictAttachEntity extends Entity { String getDistrictId(); void setDistrictId(String districtId); + + default String getDistrictIdProperty() { + return districtId; + } } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/OrgAttachEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/OrgAttachEntity.java index 7919d1fd4..f0bc6b180 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/OrgAttachEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/OrgAttachEntity.java @@ -14,4 +14,8 @@ public interface OrgAttachEntity extends Entity { String getOrgId(); void setOrgId(String orgId); + + default String getOrgIdProperty() { + return orgId; + } } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PersonAttachEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PersonAttachEntity.java index 3784007ba..c3c13987a 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PersonAttachEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PersonAttachEntity.java @@ -12,4 +12,8 @@ public interface PersonAttachEntity extends Entity { String getPersonId(); void setPersonId(String personId); + + default String getPersonIdProperty() { + return personId; + } } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PositionAttachEntity.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PositionAttachEntity.java index 07e649482..1c671e5a4 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PositionAttachEntity.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PositionAttachEntity.java @@ -11,4 +11,8 @@ public interface PositionAttachEntity extends Entity { String getPositionId(); void setPositionId(String positionId); + + default String getPositionIdProperty() { + return positionId; + } } 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 new file mode 100644 index 000000000..64dca75ab --- /dev/null +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java @@ -0,0 +1,30 @@ +package org.hswebframework.web.organizational.authorization.simple; + +import lombok.Getter; +import lombok.Setter; +import org.hswebframework.web.authorization.simple.AbstractDataAccessConfig; + +import java.util.List; +import java.util.Set; + +/** + * @author zhouhao + * @since 3.0.5 + */ +@Getter +@Setter +public class ScopeByUserDataAccessConfig extends AbstractDataAccessConfig { + + private static final long serialVersionUID = 6678003761927318688L; + + private String scopeType; + + private Set scope; + + private boolean children; + + @Override + public String getType() { + return "SCOPE_BY_USER"; + } +} diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfigConvert.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfigConvert.java new file mode 100644 index 000000000..24188c62a --- /dev/null +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfigConvert.java @@ -0,0 +1,35 @@ +package org.hswebframework.web.organizational.authorization.simple; + +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; +import org.hswebframework.web.authorization.access.DataAccessConfig; +import org.hswebframework.web.authorization.simple.AbstractDataAccessConfig; +import org.hswebframework.web.authorization.simple.builder.DataAccessConfigConvert; +import org.springframework.util.StringUtils; + +import java.util.List; + +/** + * @author zhouhao + * @since 3.0.5 + */ +@Getter +@Setter +public class ScopeByUserDataAccessConfigConvert implements DataAccessConfigConvert { + + @Override + public boolean isSupport(String type, String action, String config) { + return "SCOPE_BY_USER".equalsIgnoreCase(type); + } + + @Override + public DataAccessConfig convert(String type, String action, String config) { + if (StringUtils.isEmpty(config)) { + config = "{}"; + } + ScopeByUserDataAccessConfig dataAccessConfig = JSON.parseObject(config, ScopeByUserDataAccessConfig.class); + dataAccessConfig.setAction(action); + return dataAccessConfig; + } +} diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/AbstractScopeDataAccessHandler.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/AbstractScopeDataAccessHandler.java index 7dbf5d534..a5c118ff2 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/AbstractScopeDataAccessHandler.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/AbstractScopeDataAccessHandler.java @@ -84,11 +84,10 @@ public abstract class AbstractScopeDataAccessHandler implements DataAccessHan logger.warn("existing many scope :{} , try use config.", scope); } if (scope != null) { - String finalScopeId = scope; context.getParamContext().getParams().values().stream() .filter(getEntityClass()::isInstance) .map(getEntityClass()::cast) - .forEach(entity -> applyScopeProperty(entity, finalScopeId)); + .forEach(entity -> applyScopeProperty(entity, scope)); } else { logger.warn("scope is null!"); } @@ -153,18 +152,24 @@ public abstract class AbstractScopeDataAccessHandler implements DataAccessHan if (logger.isDebugEnabled()) { logger.debug("try rebuild query param ..."); } - QueryParamEntity queryParamEntity = ((QueryParamEntity) entity); + //重构查询条件 //如: 旧的条件为 where name =? or name = ? //重构后为: where org_id in(?,?) and (name = ? or name = ?) - List oldParam = queryParamEntity.getTerms(); - //清空旧的查询条件 - queryParamEntity.setTerms(new ArrayList<>()); - //添加一个查询条件 - queryParamEntity - .addTerm(createQueryTerm(scope, context)) - //客户端提交的参数 作为嵌套参数 - .nest().setTerms(oldParam); + QueryParamEntity queryParamEntity = ((QueryParamEntity) entity); + queryParamEntity.toNestQuery(query-> query.accept(createQueryTerm(scope, context))); + +// //重构查询条件 +// //如: 旧的条件为 where name =? or name = ? +// //重构后为: where org_id in(?,?) and (name = ? or name = ?) +// List oldParam = queryParamEntity.getTerms(); +// //清空旧的查询条件 +// queryParamEntity.setTerms(new ArrayList<>()); +// //添加一个查询条件 +// queryParamEntity +// .addTerm(createQueryTerm(scope, context)) +// //客户端提交的参数 作为嵌套参数 +// .nest().setTerms(oldParam); } else { logger.warn("try validate query access,but entity not support, QueryParamEntity support now!"); } diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/CustomScopeHandler.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/CustomScopeHandler.java index ca729e609..34d9bf601 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/CustomScopeHandler.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/CustomScopeHandler.java @@ -12,8 +12,6 @@ import java.util.HashSet; import java.util.List; /** - * TODO 完成注释 - * * @author zhouhao */ public class CustomScopeHandler implements DataAccessHandler { 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 new file mode 100644 index 000000000..eadf353b3 --- /dev/null +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java @@ -0,0 +1,342 @@ +package org.hswebframework.web.organizational.authorization.simple.handler; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +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.access.DataAccessConfig; +import org.hswebframework.web.authorization.access.DataAccessHandler; +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.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; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.*; + +/** + * @author zhouhao + * @since 3.0.5 + */ +@Slf4j +@SuppressWarnings("all") +public class ScopeByUserHandler implements DataAccessHandler { + + @Autowired + private EntityFactory entityFactory; + + @Override + public boolean isSupport(DataAccessConfig access) { + return access instanceof ScopeByUserDataAccessConfig; + } + + @Override + public boolean handle(DataAccessConfig access, AuthorizingContext context) { + ScopeByUserDataAccessConfig scope = ((ScopeByUserDataAccessConfig) access); + switch (access.getAction()) { + case Permission.ACTION_QUERY: + case Permission.ACTION_GET: + return doQueryAccess(scope, context); + case Permission.ACTION_ADD: + case Permission.ACTION_UPDATE: + default: + return doUpdateAccess(scope, context); + } + } + + protected boolean doUpdateAccess(ScopeByUserDataAccessConfig config, AuthorizingContext context) { + //获取注解 + Object id = context.getParamContext() + .getParameter(context.getDefinition().getDataAccessDefinition().getIdParameterName()) + .orElse(null); + if (id == null) { + return true; + } + PersonnelAuthentication authentication = PersonnelAuthentication.current().orElseThrow(UnAuthorizedException::new); + ScopeInfo scopeInfo = getScope(config, authentication); + if (scopeInfo.isEmpty()) { + return false; + } + Object controller = context.getParamContext().getTarget(); + QueryService queryService = null; + + if (controller instanceof QueryController) { + queryService = ((QueryController) controller).getService(); + } else { + Method getService = ReflectionUtils.findMethod(controller.getClass(), "getService"); + if (getService != null) { + try { + Object service = ReflectionUtils.invokeMethod(getService, controller); + if (service instanceof QueryService) { + queryService = ((QueryService) service); + } + } catch (Exception ignore) { + + } + } + } + if (queryService != null) { + ControllerCache controllerCache = getControllerCache(config, context); + 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; + } + return scopeInfo.scope.contains(controllerCache.targetIdGetter.apply(entity)); + } + } else { + log.warn("Controller没有实现任何通用CURD功能,无法进行数据权限控制!"); + } + return true; + + } + + private ScopeInfo getScope(ScopeByUserDataAccessConfig config, PersonnelAuthentication authentication) { + String termType = null; + Set scope = null; + ScopeInfo scopeInfo = new ScopeInfo(); + if (authentication == null) { + return scopeInfo; + } + Consumer> consumer; + + switch (config.getScopeType()) { + case DataAccessType.ORG_SCOPE: + termType = "user-in-org"; + scope = authentication.getRootOrgId(); + break; + case DataAccessType.DEPARTMENT_SCOPE: + termType = "user-in-department"; + scope = authentication.getRootDepartmentId(); + break; + case DataAccessType.POSITION_SCOPE: + termType = "user-in-position"; + break; + case DataAccessType.DISTRICT_SCOPE: + termType = "user-in-dist"; + scope = authentication.getRootDistrictId(); + break; + case "CUSTOM_SCOPE_ORG": + termType = "user-in-org"; + scope = config.getScope(); + break; + case "CUSTOM_SCOPE_DEPT": + termType = "user-in-department"; + scope = config.getScope(); + break; + case "CUSTOM_SCOPE_DIST": + termType = "user-in-dist"; + scope = config.getScope(); + break; + default: + log.warn("不支持的数据权限范围:{}", config.getScopeType()); + } + if (termType == null) { + return scopeInfo; + } + scopeInfo.scope = scope; + scopeInfo.termType = termType; + if (config.isChildren()) { + scopeInfo.termType = termType + termType.concat("-child"); + } + return scopeInfo; + + } + + class ScopeInfo { + String termType; + + Set scope; + + Consumer> notUserConsumer; + + public boolean isEmpty() { + return termType == null || scope == null || scope.isEmpty(); + } + } + + static Function defaultTargetIdGetter = entity -> { + Map userInfo = FastBeanCopier.copy(entity, new HashMap<>(), + FastBeanCopier.include("creatorId")); + return userInfo.get("creatorId"); + }; + + static BiConsumer, ScopeInfo> defaultQueryConsumer = (query, scopeInfo) -> { + query.and("creatorId", scopeInfo.termType, scopeInfo.scope); + }; + static Function> defaultScopeGetter = context -> { + return Collections.singleton(context.getAuthentication().getUser().getId()); + }; + + private Function createGetter(Class type, Function getter) { + return entity -> { + if (type.isInstance(entity)) { + return getter.apply(((E) entity)); + } + return defaultTargetIdGetter.apply(entity); + }; + } + + static Map cache = new ConcurrentHashMap<>(); + + protected String getControlProperty(Class type, Function function) { + return cache.computeIfAbsent(type, t -> { + return function.apply((T) entityFactory.newInstance(type)); + }); + } + + class ControllerCache { + Function targetIdGetter = defaultTargetIdGetter; + + BiConsumer, ScopeInfo> queryConsumer = defaultQueryConsumer; + + Function> scopeGetter = defaultScopeGetter; + } + + @EqualsAndHashCode + @Getter + @Setter + class CacheKey { + private String className; + + private boolean children; + + private String type; + } + + static Map cacheMap = new ConcurrentHashMap<>(); + + + private ControllerCache getControllerCache(ScopeByUserDataAccessConfig config, AuthorizingContext context) { + CacheKey cacheKey = new CacheKey(); + cacheKey.children = config.isChildren(); + cacheKey.className = ClassUtils.getUserClass(context.getParamContext().getTarget().getClass()).getName(); + cacheKey.type = config.getScopeType(); + 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 (RecordCreationEntity.class.isAssignableFrom(entityClass)) { + controllerCache.targetIdGetter = createGetter(RecordCreationEntity.class, RecordCreationEntity::getCreatorId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(getControlProperty(entityClass, RecordCreationEntity::getCreatorIdProperty), scopeInfo.termType, scopeInfo.scope); + }; + } else if (OrgAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("ORG")) { + controllerCache.targetIdGetter = createGetter(OrgAttachEntity.class, OrgAttachEntity::getOrgId); + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(getControlProperty(entityClass, OrgAttachEntity::getOrgIdProperty), children ? "org-child-in" : "org-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" : "dept-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" : "pos-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" : "dist-in", scopeInfo.scope); + }; + } else { + String userIdField = getUserField(entityClass); + controllerCache.targetIdGetter = entity -> { + Map userInfo = FastBeanCopier.copy(entity, new HashMap<>(), + FastBeanCopier.include(userIdField)); + return userInfo.get(userIdField); + }; + controllerCache.queryConsumer = (query, scopeInfo) -> { + query.and(userIdField, scopeInfo.termType, scopeInfo.scope); + }; + } + } + return controllerCache; + }); + } + + protected boolean doQueryAccess(ScopeByUserDataAccessConfig config, AuthorizingContext context) { + PersonnelAuthentication authentication = PersonnelAuthentication + .current() + .orElseThrow(AccessDenyException::new); + ScopeInfo scopeInfo = getScope(config, authentication); + if (scopeInfo.isEmpty()) { + return false; + } + ControllerCache controllerCache = getControllerCache(config, context); + + //如果是执行后 + if (context.getDefinition().getDataAccessDefinition().getPhased() == Phased.after) { + Object result = context.getParamContext().getInvokeResult(); + if (result == null) { + return true; + } + if (result instanceof ResponseEntity) { + result = ((ResponseEntity) result).getBody(); + } + if (result instanceof ResponseMessage) { + result = ((ResponseMessage) result).getResult(); + } + String value = controllerCache.targetIdGetter.apply(result); + log.debug("执行数据权限控制,scope:{},target:{}", scopeInfo.scope, value); + if (value == null) { + return true; + } + return scopeInfo.scope.contains(value); + } + + Entity entity = context.getParamContext() + .getParams() + .values() + .stream() + .filter(Entity.class::isInstance) + .map(Entity.class::cast) + .findAny() + .orElse(null); + + if (entity instanceof QueryParamEntity) { + QueryParamEntity param = ((QueryParamEntity) entity); + param.toNestQuery(query -> { + log.debug("执行查询数据权限控制,scope:{}", scopeInfo.scope); + controllerCache.queryConsumer.accept(query, scopeInfo); + }); + } + return true; + } + + public String getUserField(Class type) { + + if (ReflectionUtils.findField(type, "userId") != null) { + return "userId"; + } + + return "creatorId"; + } +} diff --git a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/PersonController.java b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/PersonController.java index 9bccc8429..8e18957d3 100644 --- a/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/PersonController.java +++ b/hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/PersonController.java @@ -22,6 +22,7 @@ import io.swagger.annotations.ApiOperation; import org.hswebframework.web.NotFoundException; import org.hswebframework.web.authorization.Permission; import org.hswebframework.web.authorization.annotation.Authorize; +import org.hswebframework.web.authorization.annotation.RequiresDataAccess; import org.hswebframework.web.commons.entity.PagerResult; import org.hswebframework.web.commons.entity.param.QueryParamEntity; import org.hswebframework.web.controller.SimpleGenericEntityController; @@ -43,7 +44,7 @@ import java.util.List; */ @RestController @RequestMapping("${hsweb.web.mappings.person:person}") -@Authorize(permission = "person",description = "人员管理") +@Authorize(permission = "person",description = "人员管理",dataAccess = @RequiresDataAccess) @Api(value = "人员管理",tags = "组织架构-人员管理") public class PersonController implements SimpleGenericEntityController {