feat:租户隔离策略
This commit is contained in:
parent
b9f9cb2612
commit
a88776119c
@ -30,7 +30,7 @@ public class TreeQo<T extends Domain> extends NameLikeQo<T> {
|
||||
CriteriaBuilder<T> builder = super.criteriaBuilder().with("depth");
|
||||
if (BooleanUtils.isTrue(recursive)) {
|
||||
builder.with("parentId", "parentIds", Criteria::is)
|
||||
.with("parentIds", "parentIds", Criteria::is);
|
||||
.with("parentIds", "parentIds", CriteriaBuilder.Builders.IN);
|
||||
} else {
|
||||
builder.with("parentId").with("parentIds", "parentId", CriteriaBuilder.Builders.IN);
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ package com.flyfish.framework.logging.advice;
|
||||
|
||||
import com.flyfish.framework.logging.service.LogContext;
|
||||
import com.flyfish.framework.logging.service.LogManager;
|
||||
import com.flyfish.framework.utils.UserUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@ -58,7 +58,7 @@ public class LogAdvice {
|
||||
context.setError(throwable);
|
||||
throw throwable;
|
||||
} finally {
|
||||
if (!reactive && context.isValid()) {
|
||||
if (context.isValid() && !reactive) {
|
||||
context.setResult(result);
|
||||
logManager.tryLog(context.end());
|
||||
}
|
||||
@ -73,19 +73,33 @@ public class LogAdvice {
|
||||
* @param context 上下文
|
||||
*/
|
||||
private Object handleResult(Object result, LogContext context) {
|
||||
if (!context.isValid()) {
|
||||
return result;
|
||||
}
|
||||
Runnable runnable = () -> {
|
||||
if (context.isValid()) {
|
||||
logManager.tryLog(context.end());
|
||||
}
|
||||
};
|
||||
if (result instanceof Mono) {
|
||||
return ((Mono<?>) result)
|
||||
Mono<String> user = ReactiveSecurityContextHolder.getContext()
|
||||
.map(UserUtils::extractUserName);
|
||||
return Mono.zip(user, (Mono<?>) result)
|
||||
.map(value -> {
|
||||
context.setUser(value.getT1());
|
||||
return value.getT2();
|
||||
})
|
||||
.doOnSuccess(context::setResult)
|
||||
.doOnError(context::setError)
|
||||
.doOnTerminate(runnable);
|
||||
} else if (result instanceof Flux) {
|
||||
return ((Flux<?>) result)
|
||||
.collectList()
|
||||
Mono<String> user = ReactiveSecurityContextHolder.getContext()
|
||||
.map(UserUtils::extractUserName);
|
||||
return Mono.zip(user, ((Flux<?>) result).collectList())
|
||||
.map(value -> {
|
||||
context.setUser(value.getT1());
|
||||
return value.getT2();
|
||||
})
|
||||
.doOnSuccess(context::setResult)
|
||||
.doOnError(context::setError)
|
||||
.doOnTerminate(runnable)
|
||||
@ -95,31 +109,4 @@ public class LogAdvice {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings("all")
|
||||
private static class LogSubscriber implements Subscriber<Object> {
|
||||
|
||||
private final LogContext context;
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Subscription s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(Object o) {
|
||||
context.setResult(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
context.setError(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
context.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ public class LogContext {
|
||||
}
|
||||
|
||||
public LogContext end() {
|
||||
this.user = UserContext.sharedContext().map(UserContext::currentUser).map(Domain::getName).orElse("未知");
|
||||
this.user = UserContext.sharedContext().map(UserContext::currentUser).map(Domain::getName).orElse(this.user);
|
||||
this.endTime = System.currentTimeMillis();
|
||||
return this;
|
||||
}
|
||||
|
@ -1,10 +1,18 @@
|
||||
package com.flyfish.framework.controller;
|
||||
|
||||
import com.flyfish.framework.bean.Result;
|
||||
import com.flyfish.framework.controller.reactive.ReactiveTreeController;
|
||||
import com.flyfish.framework.domain.AdminUserDetails;
|
||||
import com.flyfish.framework.domain.DepartmentQo;
|
||||
import com.flyfish.framework.domain.po.Department;
|
||||
import com.flyfish.framework.utils.UserUtils;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部分或者校区controller
|
||||
@ -13,4 +21,20 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequestMapping("/departments")
|
||||
public class DepartmentController extends ReactiveTreeController<Department, DepartmentQo> {
|
||||
|
||||
/**
|
||||
* 获取有权限的tree
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("authorized-tree")
|
||||
public Mono<Result<List<Department>>> getAuthorizedTree() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(UserUtils::extractUserDetails)
|
||||
.flatMap(detail -> {
|
||||
AdminUserDetails details = (AdminUserDetails) detail;
|
||||
return reactiveService.getByIds(details.getAuthorityCodes()).collectList();
|
||||
})
|
||||
.map(this::makeTree)
|
||||
.map(Result::accept);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class DepartmentService extends BaseReactiveServiceImpl<Department> {
|
||||
* @return 结果
|
||||
*/
|
||||
public Mono<List<String>> getSubCodes(List<String> parents) {
|
||||
Query query = Query.query(Criteria.where("parentId").in(parents));
|
||||
Query query = Query.query(Criteria.where("parentIds").in(parents));
|
||||
query.fields().include("_id");
|
||||
return reactiveMongoOperations.find(query, Department.class).map(Department::getId).collectList();
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public class UserDetailsConverter {
|
||||
if (CollectionUtils.isNotEmpty(user.getDepartments())) {
|
||||
val departs = user.getDepartments().stream().map(Department::getId)
|
||||
.collect(Collectors.toList());
|
||||
userDetail.setAuthorityCodes(ListUtils.union(departs, userDetail.getAuthorityCodes()));
|
||||
return departmentService.getSubCodes(departs)
|
||||
.map(codes -> {
|
||||
if (CollectionUtils.isNotEmpty(codes)) {
|
||||
|
@ -8,7 +8,6 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -51,18 +50,26 @@ public abstract class ReactiveTreeController<T extends TreeDomain<T>, Q extends
|
||||
// 第一步,查询全部,并根据条件筛选
|
||||
return reactiveService.getList(qo)
|
||||
.collectList()
|
||||
.flatMap(filtered -> {
|
||||
.map(this::makeTree)
|
||||
.map(Result::accept);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个tree
|
||||
*
|
||||
* @param filtered 过滤后的节点
|
||||
* @return 结果
|
||||
*/
|
||||
protected List<T> makeTree(List<T> filtered) {
|
||||
// 第二步,根据父id组成map
|
||||
Map<String, List<T>> group = filtered.stream()
|
||||
.collect(Collectors.groupingBy(p -> StringUtils.defaultIfBlank(p.getParentId(), "")));
|
||||
// 第三步,筛选一级树深度
|
||||
return Flux.fromIterable(filtered)
|
||||
List<T> roots = filtered.stream()
|
||||
.filter(item -> null != item && TreeDomain.ROOT.equals(item.getParentId()))
|
||||
.collectList()
|
||||
.collect(Collectors.toList());
|
||||
// 第四步,根据父id的map填充根tree
|
||||
.map(topList -> applyChildren(topList, group));
|
||||
})
|
||||
.map(Result::accept);
|
||||
return applyChildren(roots, group);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user