mirror of
https://github.com/hs-web/hsweb-framework.git
synced 2026-05-17 11:47:26 +08:00
Merge remote-tracking branch 'origin/4.0.x' into 4.0.x
# Conflicts: # hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccess.java
This commit is contained in:
@@ -40,7 +40,7 @@ public class MyDataAccessHandler implements org.hswebframework.web.authorization
|
||||
@Override
|
||||
public boolean handle(DataAccessConfig access, MethodInterceptorParamContext context) {
|
||||
//被拦截的方法参数
|
||||
Map<String,Object> param= context.getParams();
|
||||
Map<String,Object> param= context.getNamedArguments();
|
||||
// 判断逻辑
|
||||
//...
|
||||
return true;
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.lang.annotation.*;
|
||||
*
|
||||
* @author zhouhao
|
||||
* @see DataAccessController
|
||||
* @see ResourceAction#dataAccess()
|
||||
* @since 3.0
|
||||
*/
|
||||
@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD})
|
||||
|
||||
@@ -21,27 +21,4 @@ public class AuthorizingContext {
|
||||
|
||||
private MethodInterceptorContext paramContext;
|
||||
|
||||
public AuthorizeDefinition getDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
public void setDefinition(AuthorizeDefinition definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public Authentication getAuthentication() {
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
public MethodInterceptorContext getParamContext() {
|
||||
return paramContext;
|
||||
}
|
||||
|
||||
public void setParamContext(MethodInterceptorContext paramContext) {
|
||||
this.paramContext = paramContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.hswebframework.web.authorization.basic.aop;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
@@ -11,10 +12,12 @@ import org.hswebframework.web.authorization.basic.handler.AuthorizingHandler;
|
||||
import org.hswebframework.web.authorization.define.*;
|
||||
import org.hswebframework.web.authorization.exception.UnAuthorizedException;
|
||||
import org.hswebframework.web.utils.AnnotationUtils;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -22,6 +25,10 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -51,81 +58,48 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
|
||||
this.autoParse = autoParse;
|
||||
}
|
||||
|
||||
protected Mono<?> handleReactive(AuthorizeDefinition definition, MethodInterceptorHolder holder, AuthorizingContext context, Mono<?> mono) {
|
||||
|
||||
return Authentication.currentReactive()
|
||||
.switchIfEmpty(Mono.error(new UnAuthorizedException()))
|
||||
.flatMap(auth -> {
|
||||
ResourcesDefinition resources = definition.getResources();
|
||||
|
||||
context.setAuthentication(auth);
|
||||
if (definition.getPhased() == Phased.before) {
|
||||
authorizingHandler.handRBAC(context);
|
||||
if (resources != null && resources.getPhased() == Phased.before) {
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
} else {
|
||||
return mono.doOnNext(res -> {
|
||||
context.setParamContext(holder.createParamContext(res));
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (resources != null && resources.getPhased() == Phased.before) {
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
return mono.doOnNext(res -> {
|
||||
context.setParamContext(holder.createParamContext(res));
|
||||
authorizingHandler.handRBAC(context);
|
||||
});
|
||||
} else {
|
||||
return mono.doOnNext(res -> {
|
||||
context.setParamContext(holder.createParamContext(res));
|
||||
authorizingHandler.handle(context);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
return mono;
|
||||
});
|
||||
}
|
||||
|
||||
protected Flux<?> handleReactive(AuthorizeDefinition definition, MethodInterceptorHolder holder, AuthorizingContext context, Flux<?> flux) {
|
||||
protected Publisher<?> handleReactive0(AuthorizeDefinition definition,
|
||||
MethodInterceptorHolder holder,
|
||||
AuthorizingContext context,
|
||||
Supplier<? extends Publisher<?>> invoker) {
|
||||
|
||||
return Authentication.currentReactive()
|
||||
.switchIfEmpty(Mono.error(new UnAuthorizedException()))
|
||||
.flatMapMany(auth -> {
|
||||
ResourcesDefinition resources = definition.getResources();
|
||||
|
||||
context.setAuthentication(auth);
|
||||
if (definition.getPhased() == Phased.before) {
|
||||
Function<Runnable, Publisher> afterRuner = runnable -> {
|
||||
MethodInterceptorContext interceptorContext = holder.createParamContext(invoker.get());
|
||||
runnable.run();
|
||||
return (Publisher<?>) interceptorContext.getInvokeResult();
|
||||
};
|
||||
if (context.getDefinition().getPhased() != Phased.after) {
|
||||
authorizingHandler.handRBAC(context);
|
||||
if (resources != null && resources.getPhased() == Phased.before) {
|
||||
if (context.getDefinition().getResources().getPhased() != Phased.after) {
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
return invoker.get();
|
||||
} else {
|
||||
return flux.doOnNext(res -> {
|
||||
context.setParamContext(holder.createParamContext(res));
|
||||
return afterRuner.apply(() -> authorizingHandler.handleDataAccess(context));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (context.getDefinition().getResources().getPhased() != Phased.after) {
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
return invoker.get();
|
||||
} else {
|
||||
return afterRuner.apply(() -> {
|
||||
authorizingHandler.handRBAC(context);
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
if (resources != null && resources.getPhased() == Phased.before) {
|
||||
authorizingHandler.handleDataAccess(context);
|
||||
return flux.doOnNext(res -> {
|
||||
context.setParamContext(holder.createParamContext(res));
|
||||
authorizingHandler.handRBAC(context);
|
||||
});
|
||||
} else {
|
||||
return flux.doOnNext(res -> {
|
||||
context.setParamContext(holder.createParamContext(res));
|
||||
authorizingHandler.handle(context);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
return flux;
|
||||
});
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private <T> T doProceed(MethodInvocation invocation) {
|
||||
return (T) invocation.proceed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
@@ -136,17 +110,20 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
|
||||
AuthorizeDefinition definition = aopMethodAuthorizeDefinitionParser.parse(methodInvocation.getThis().getClass(), methodInvocation.getMethod(), paramContext);
|
||||
Object result = null;
|
||||
boolean isControl = false;
|
||||
if (null != definition) {
|
||||
if (null != definition && !definition.isEmpty()) {
|
||||
AuthorizingContext context = new AuthorizingContext();
|
||||
context.setDefinition(definition);
|
||||
context.setParamContext(paramContext);
|
||||
|
||||
Class<?> returnType = methodInvocation.getMethod().getReturnType();
|
||||
//handle reactive method
|
||||
if (Mono.class.isAssignableFrom(returnType)) {
|
||||
return handleReactive(definition, holder, context, ((Mono<?>) methodInvocation.proceed()));
|
||||
} else if (Flux.class.isAssignableFrom(returnType)) {
|
||||
return handleReactive(definition, holder, context, ((Flux<?>) methodInvocation.proceed()));
|
||||
if (Publisher.class.isAssignableFrom(returnType)) {
|
||||
Publisher publisher = handleReactive0(definition, holder, context, () -> doProceed(methodInvocation));
|
||||
if (Mono.class.isAssignableFrom(returnType)) {
|
||||
return Mono.from(publisher);
|
||||
} else if (Flux.class.isAssignableFrom(returnType)) {
|
||||
return Flux.from(publisher);
|
||||
}
|
||||
}
|
||||
|
||||
Authentication authentication = Authentication.current().orElseThrow(UnAuthorizedException::new);
|
||||
@@ -224,7 +201,7 @@ public class AopAuthorizingController extends StaticMethodMatcherPointcutAdvisor
|
||||
log.info("publish AuthorizeDefinitionInitializedEvent,definition size:{}", definitions.size());
|
||||
eventPublisher.publishEvent(new AuthorizeDefinitionInitializedEvent(definitions));
|
||||
|
||||
// defaultParser.destroy();
|
||||
// defaultParser.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ public final class DefaultDataAccessController implements DataAccessController {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
this.parent = parent;
|
||||
|
||||
addHandler(new FieldFilterDataAccessHandler());
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@ import org.hswebframework.web.authorization.access.DataAccessHandler;
|
||||
import org.hswebframework.web.authorization.access.FieldFilterDataAccessConfig;
|
||||
import org.hswebframework.web.authorization.define.AuthorizingContext;
|
||||
import org.hswebframework.web.authorization.define.Phased;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -46,6 +49,22 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyUpdateParam(FieldFilterDataAccessConfig config, Object... parameter) {
|
||||
|
||||
for (Object data : parameter) {
|
||||
for (String field : config.getFields()) {
|
||||
try {
|
||||
//设置值为null,跳过修改
|
||||
BeanUtilsBean.getInstance()
|
||||
.getPropertyUtils()
|
||||
.setProperty(data, field, null);
|
||||
} catch (Exception e) {
|
||||
logger.warn("can't set {} null", field, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accesses 不可操作的字段
|
||||
* @param params 参数上下文
|
||||
@@ -54,52 +73,80 @@ public class FieldFilterDataAccessHandler implements DataAccessHandler {
|
||||
* @see org.apache.commons.beanutils.PropertyUtilsBean
|
||||
*/
|
||||
protected boolean doUpdateAccess(FieldFilterDataAccessConfig accesses, AuthorizingContext params) {
|
||||
Map<String, Object> paramsMap = params.getParamContext().getParams();
|
||||
|
||||
Object supportParam = paramsMap.size() == 1 ?
|
||||
paramsMap.values().iterator().next() :
|
||||
paramsMap.values().stream()
|
||||
// .filter(param -> (param instanceof Entity) || (param instanceof Model) || (param instanceof Map))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
if (null != supportParam) {
|
||||
for (String field : accesses.getFields()) {
|
||||
try {
|
||||
//设置值为null,跳过修改
|
||||
BeanUtilsBean.getInstance()
|
||||
.getPropertyUtils()
|
||||
.setProperty(supportParam, field, null);
|
||||
} catch (Exception e) {
|
||||
logger.warn("can't set {} null", field, e);
|
||||
}
|
||||
boolean reactive = params.getParamContext().handleReactiveArguments(publisher -> {
|
||||
if (publisher instanceof Mono) {
|
||||
return Mono.from(publisher)
|
||||
.doOnNext(data -> applyUpdateParam(accesses, data));
|
||||
|
||||
}
|
||||
} else {
|
||||
logger.warn("doUpdateAccess skip ,because can not found any support entity in param!");
|
||||
if (publisher instanceof Flux) {
|
||||
return Flux.from(publisher)
|
||||
.doOnNext(data -> applyUpdateParam(accesses, data));
|
||||
|
||||
}
|
||||
return publisher;
|
||||
});
|
||||
if (reactive) {
|
||||
return true;
|
||||
}
|
||||
|
||||
applyUpdateParam(accesses, params.getParamContext().getArguments());
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
protected void applyQueryParam(FieldFilterDataAccessConfig config, Object param) {
|
||||
if (param instanceof QueryParam) {
|
||||
Set<String> denyFields = config.getFields();
|
||||
((QueryParam) param).excludes(denyFields.toArray(new String[0]));
|
||||
return;
|
||||
}
|
||||
|
||||
Object r = InvokeResultUtils.convertRealResult(param);
|
||||
if (r instanceof Collection) {
|
||||
((Collection) r).forEach(o -> setObjectPropertyNull(o, config.getFields()));
|
||||
} else {
|
||||
setObjectPropertyNull(r, config.getFields());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
protected boolean doQueryAccess(FieldFilterDataAccessConfig access, AuthorizingContext context) {
|
||||
if (context.getDefinition().getResources().getPhased() == Phased.before) {
|
||||
QueryParam entity = context.getParamContext().getParams()
|
||||
.values().stream()
|
||||
.filter(QueryParam.class::isInstance)
|
||||
.map(QueryParam.class::cast)
|
||||
.findAny().orElse(null);
|
||||
if (entity == null) {
|
||||
logger.warn("try validate query access, but query entity is null or not instance of org.hswebframework.web.commons.entity.Entity");
|
||||
|
||||
boolean reactive = context
|
||||
.getParamContext()
|
||||
.handleReactiveArguments(publisher -> {
|
||||
if (publisher instanceof Mono) {
|
||||
return Mono.from(publisher)
|
||||
.doOnNext(param -> {
|
||||
applyQueryParam(access, param);
|
||||
});
|
||||
}
|
||||
return publisher;
|
||||
});
|
||||
|
||||
if (reactive) {
|
||||
return true;
|
||||
}
|
||||
Set<String> denyFields = access.getFields();
|
||||
entity.excludes(denyFields.toArray(new String[denyFields.size()]));
|
||||
} else {
|
||||
Object result = InvokeResultUtils.convertRealResult(context.getParamContext().getInvokeResult());
|
||||
if (result instanceof Collection) {
|
||||
((Collection) result).forEach(o -> setObjectPropertyNull(o, access.getFields()));
|
||||
} else {
|
||||
setObjectPropertyNull(result, access.getFields());
|
||||
|
||||
for (Object argument : context.getParamContext().getArguments()) {
|
||||
applyQueryParam(access, argument);
|
||||
}
|
||||
} else {
|
||||
if (context.getParamContext().getInvokeResult() instanceof Publisher) {
|
||||
context.getParamContext().setInvokeResult(
|
||||
Flux.from((Publisher<?>) context.getParamContext().getInvokeResult())
|
||||
.doOnNext(result -> {
|
||||
applyQueryParam(access, result);
|
||||
})
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
applyQueryParam(access, context.getParamContext().getInvokeResult());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package org.hswebframework.web.authorization.basic.aop;
|
||||
|
||||
import org.hswebframework.ezorm.core.param.Param;
|
||||
import org.hswebframework.ezorm.core.param.QueryParam;
|
||||
import org.hswebframework.web.authorization.Authentication;
|
||||
import org.hswebframework.web.authorization.ReactiveAuthenticationHolder;
|
||||
import org.hswebframework.web.authorization.ReactiveAuthenticationSupplier;
|
||||
import org.hswebframework.web.authorization.User;
|
||||
import org.hswebframework.web.authorization.basic.handler.access.FieldFilterDataAccessHandler;
|
||||
import org.hswebframework.web.authorization.basic.web.ReactiveUserTokenParser;
|
||||
import org.hswebframework.web.authorization.exception.AccessDenyException;
|
||||
import org.hswebframework.web.authorization.exception.UnAuthorizedException;
|
||||
import org.hswebframework.web.authorization.simple.SimpleAuthentication;
|
||||
import org.hswebframework.web.authorization.simple.SimpleFieldFilterDataAccessConfig;
|
||||
import org.hswebframework.web.authorization.simple.SimplePermission;
|
||||
import org.hswebframework.web.authorization.simple.SimpleUser;
|
||||
import org.hswebframework.web.authorization.token.ParsedToken;
|
||||
@@ -25,6 +29,7 @@ import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -69,4 +74,43 @@ public class AopAuthorizingControllerTest {
|
||||
.expectNext("403")
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFiledDeny(){
|
||||
SimpleAuthentication authentication = new SimpleAuthentication();
|
||||
|
||||
SimpleFieldFilterDataAccessConfig config=new SimpleFieldFilterDataAccessConfig();
|
||||
config.setAction("query");
|
||||
config.setFields(new HashSet<>(Arrays.asList("name")));
|
||||
|
||||
authentication.setUser(SimpleUser.builder().id("test").username("test").build());
|
||||
authentication.setPermissions(Arrays.asList(SimplePermission.builder()
|
||||
.actions(Collections.singleton("query"))
|
||||
.dataAccesses(Collections.singleton(config))
|
||||
.id("test").build()));
|
||||
|
||||
ReactiveAuthenticationHolder.addSupplier(new ReactiveAuthenticationSupplier() {
|
||||
@Override
|
||||
public Mono<Authentication> get(String userId) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Authentication> get() {
|
||||
return Mono.just(authentication);
|
||||
}
|
||||
});
|
||||
|
||||
testController.queryUser(new QueryParam())
|
||||
.map(Param::getExcludes)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextMatches(f->f.contains("name"))
|
||||
.verifyComplete();
|
||||
|
||||
testController.queryUser(Mono.just(new QueryParam()))
|
||||
.map(Param::getExcludes)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextMatches(f->f.contains("name"))
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.hswebframework.web.authorization.basic.aop;
|
||||
|
||||
import org.hswebframework.ezorm.core.param.QueryParam;
|
||||
import org.hswebframework.web.authorization.Authentication;
|
||||
import org.hswebframework.web.authorization.User;
|
||||
import org.hswebframework.web.authorization.annotation.Authorize;
|
||||
import org.hswebframework.web.authorization.annotation.QueryAction;
|
||||
import org.hswebframework.web.authorization.annotation.Resource;
|
||||
import org.hswebframework.web.authorization.access.DataAccessConfig;
|
||||
import org.hswebframework.web.authorization.annotation.*;
|
||||
import org.hswebframework.web.authorization.define.Phased;
|
||||
import org.hswebframework.web.authorization.exception.UnAuthorizedException;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -27,4 +27,16 @@ public class TestController {
|
||||
.switchIfEmpty(Mono.error(new UnAuthorizedException()))
|
||||
.map(Authentication::getUser);
|
||||
}
|
||||
|
||||
@QueryAction(dataAccess = @DataAccess(type = @DataAccessType(id= DataAccessConfig.DefaultType.DENY_FIELDS,name = "禁止访问字段")))
|
||||
public Mono<QueryParam> queryUser(QueryParam queryParam) {
|
||||
return Mono.just(queryParam);
|
||||
}
|
||||
|
||||
@QueryAction(dataAccess = @DataAccess(type = @DataAccessType(id= DataAccessConfig.DefaultType.DENY_FIELDS,name = "禁止访问字段")))
|
||||
public Mono<QueryParam> queryUser(Mono<QueryParam> queryParam) {
|
||||
return queryParam;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,11 +18,14 @@
|
||||
|
||||
package org.hswebframework.web.aop;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* AOP拦截到方法的参数上下文,用于获取当前进行操作的方法的各种参数信息,如:当前所在类实例,参数集合,注解
|
||||
@@ -55,7 +58,7 @@ public interface MethodInterceptorContext extends Serializable {
|
||||
* @param <T> 参数泛型
|
||||
* @return Optional
|
||||
*/
|
||||
<T> Optional<T> getParameter(String name);
|
||||
<T> Optional<T> getArgument(String name);
|
||||
|
||||
/**
|
||||
* 获取当前操作方法或实例上指定类型的泛型,如果方法上未获取到,则获取实例类上的注解。实例类上未获取到,则返回null
|
||||
@@ -70,9 +73,16 @@ public interface MethodInterceptorContext extends Serializable {
|
||||
* 获取全部参数
|
||||
*
|
||||
* @return 参数集合
|
||||
* @see this#getParameter(String)
|
||||
* @see this#getArgument(String)
|
||||
*/
|
||||
Map<String, Object> getParams();
|
||||
Map<String, Object> getNamedArguments();
|
||||
|
||||
Object[] getArguments();
|
||||
|
||||
boolean handleReactiveArguments(Function<Publisher<?>, Publisher<?>> handler);
|
||||
|
||||
Object getInvokeResult();
|
||||
|
||||
void setInvokeResult(Object result);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,22 +18,29 @@
|
||||
|
||||
package org.hswebframework.web.aop;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.hswebframework.web.utils.AnnotationUtils;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author zhouhao
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class MethodInterceptorHolder {
|
||||
/**
|
||||
* 参数名称获取器,用于获取方法参数的名称
|
||||
@@ -48,9 +55,12 @@ public class MethodInterceptorHolder {
|
||||
for (int i = 0, len = args.length; i < len; i++) {
|
||||
argMap.put((argNames == null || argNames[i] == null) ? "arg" + i : argNames[i], args[i]);
|
||||
}
|
||||
|
||||
return new MethodInterceptorHolder(id,
|
||||
invocation.getMethod(),
|
||||
invocation.getThis(), argMap);
|
||||
invocation.getThis(),
|
||||
args,
|
||||
argMap);
|
||||
}
|
||||
|
||||
private String id;
|
||||
@@ -59,34 +69,10 @@ public class MethodInterceptorHolder {
|
||||
|
||||
private Object target;
|
||||
|
||||
private Map<String, Object> args;
|
||||
private Object[] arguments;
|
||||
|
||||
public MethodInterceptorHolder(String id, Method method, Object target, Map<String, Object> args) {
|
||||
Objects.requireNonNull(id);
|
||||
Objects.requireNonNull(method);
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(args);
|
||||
this.id = id;
|
||||
this.method = method;
|
||||
this.target = target;
|
||||
this.args = args;
|
||||
}
|
||||
private Map<String, Object> namedArguments;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public Object getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public Map<String, Object> getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public <T extends Annotation> T findMethodAnnotation(Class<T> annClass) {
|
||||
return AnnotationUtils.findMethodAnnotation(annClass, method, annClass);
|
||||
@@ -107,6 +93,30 @@ public class MethodInterceptorHolder {
|
||||
public MethodInterceptorContext createParamContext(Object invokeResult) {
|
||||
return new MethodInterceptorContext() {
|
||||
private static final long serialVersionUID = -4102787561601219273L;
|
||||
private Object result = invokeResult;
|
||||
|
||||
@Override
|
||||
public Object[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public boolean handleReactiveArguments(Function<Publisher<?>, Publisher<?>> handler) {
|
||||
boolean handled = false;
|
||||
Object[] args = getArguments();
|
||||
if (args == null || args.length == 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object arg = args[i];
|
||||
if (arg instanceof Publisher) {
|
||||
args[i] = handler.apply(((Mono) arg));
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getTarget() {
|
||||
@@ -119,11 +129,11 @@ public class MethodInterceptorHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Optional<T> getParameter(String name) {
|
||||
if (args == null) {
|
||||
public <T> Optional<T> getArgument(String name) {
|
||||
if (namedArguments == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.ofNullable((T) args.get(name));
|
||||
return Optional.ofNullable((T) namedArguments.get(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,13 +142,18 @@ public class MethodInterceptorHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getParams() {
|
||||
return getArgs();
|
||||
public Map<String, Object> getNamedArguments() {
|
||||
return MethodInterceptorHolder.this.getNamedArguments();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getInvokeResult() {
|
||||
return invokeResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvokeResult(Object result) {
|
||||
this.result = result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.hswebframework.web.datasource.strategy.AnnotationDataSourceSwitchStrategyMatcher.*;
|
||||
|
||||
@@ -112,7 +111,7 @@ public class AopDataSourceSwitcherAutoConfiguration {
|
||||
String id = strategy.getDataSourceId();
|
||||
if (StringUtils.hasText(id)) {
|
||||
if (id.contains("${")) {
|
||||
id = ExpressionUtils.analytical(id, context.getParams(), "spel");
|
||||
id = ExpressionUtils.analytical(id, context.getNamedArguments(), "spel");
|
||||
}
|
||||
if (!DataSourceHolder.existing(id)) {
|
||||
if (strategy.isFallbackDefault()) {
|
||||
|
||||
@@ -90,7 +90,7 @@ public class AopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor {
|
||||
info.setAction(define.getAction());
|
||||
info.setDescribe(define.getDescribe());
|
||||
}
|
||||
info.setParameters(holder.getArgs());
|
||||
info.setParameters(holder.getNamedArguments());
|
||||
info.setTarget(holder.getTarget().getClass());
|
||||
info.setMethod(holder.getMethod());
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>hsweb-system-organizational</artifactId>
|
||||
<groupId>org.hswebframework.web</groupId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hsweb-system-organizational-authorization</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hswebframework.web</groupId>
|
||||
<artifactId>hsweb-authorization-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.hswebframework.web.organizational;
|
||||
|
||||
public interface DepartmentAttachEntity {
|
||||
|
||||
String getDepartmentId();
|
||||
|
||||
void setDepartmentId(String positionId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.hswebframework.web.organizational;
|
||||
|
||||
|
||||
public interface DistrictAttachEntity {
|
||||
|
||||
String getDistrictId();
|
||||
|
||||
void serDistrictId(String districtId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.hswebframework.web.organizational;
|
||||
|
||||
|
||||
public interface OrganizationAttachEntity {
|
||||
|
||||
String getOrgId();
|
||||
|
||||
void serOrgId(String orgId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.hswebframework.web.organizational;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.hswebframework.web.authorization.DimensionType;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum OrganizationDimension implements DimensionType {
|
||||
|
||||
district("行政区"),
|
||||
organization("机构"),
|
||||
department("部门"),
|
||||
position("岗位"),
|
||||
person("人员"),
|
||||
|
||||
;
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.hswebframework.web.organizational;
|
||||
|
||||
public interface PositionAttachEntity {
|
||||
|
||||
String getPositionId();
|
||||
|
||||
void setPositionId(String positionId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.hswebframework.web.organizational.annotation;
|
||||
|
||||
import org.hswebframework.web.authorization.annotation.DataAccessType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @see org.hswebframework.web.organizational.DistrictAttachEntity
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@DataAccessType(id = "district", name = "行政区划")
|
||||
public @interface DistrictDataAccess {
|
||||
|
||||
}
|
||||
19
hsweb-system/hsweb-system-organizational/pom.xml
Normal file
19
hsweb-system/hsweb-system-organizational/pom.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>hsweb-system</artifactId>
|
||||
<groupId>org.hswebframework.web</groupId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hsweb-system-organizational</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>hsweb-system-organizational-authorization</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -15,6 +15,7 @@
|
||||
<module>hsweb-system-authorization</module>
|
||||
<module>hsweb-system-file</module>
|
||||
<module>hsweb-system-dictionary</module>
|
||||
<module>hsweb-system-organizational</module>
|
||||
</modules>
|
||||
<artifactId>hsweb-system</artifactId>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user