feat:完整实现权限隔离
This commit is contained in:
parent
0a0b63e480
commit
38f90de292
@ -3,19 +3,22 @@ package com.flyfish.framework.builder;
|
||||
import com.flyfish.framework.context.DateContext;
|
||||
import com.flyfish.framework.domain.base.Domain;
|
||||
import com.flyfish.framework.domain.base.Qo;
|
||||
import com.mongodb.BasicDBList;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -25,12 +28,11 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public final class CriteriaBuilder<T extends Domain> {
|
||||
|
||||
private final Map<String, BiFunction<Criteria, Object, Criteria>> functionMap = new HashMap<>();
|
||||
private final Map<String, String> keyMapper = new HashMap<>();
|
||||
private final List<Supplier<Criteria>> criterias = new ArrayList<>();
|
||||
private Qo<T> qo;
|
||||
|
||||
private Map<String, BiFunction<Criteria, Object, Criteria>> functionMap = new HashMap<>();
|
||||
|
||||
private Map<String, String> keyMapper = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 构造器,接受一个qo
|
||||
*
|
||||
@ -44,6 +46,20 @@ public final class CriteriaBuilder<T extends Domain> {
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建criteria列表
|
||||
*
|
||||
* @param criteria 多个查询
|
||||
* @return 结果
|
||||
*/
|
||||
public static BasicDBList createCriteriaList(Criteria... criteria) {
|
||||
BasicDBList bsonList = new BasicDBList();
|
||||
for (Criteria c : criteria) {
|
||||
bsonList.add(c.getCriteriaObject());
|
||||
}
|
||||
return bsonList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加策略
|
||||
*
|
||||
@ -81,6 +97,17 @@ public final class CriteriaBuilder<T extends Domain> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加自定义条件
|
||||
*
|
||||
* @param function 函数
|
||||
* @return 结果
|
||||
*/
|
||||
public CriteriaBuilder<T> with(Supplier<Criteria> function) {
|
||||
this.criterias.add(function);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入规则
|
||||
*
|
||||
@ -94,11 +121,11 @@ public final class CriteriaBuilder<T extends Domain> {
|
||||
}
|
||||
|
||||
public Criteria build() {
|
||||
if (!CollectionUtils.isEmpty(functionMap)) {
|
||||
if (!MapUtils.isEmpty(functionMap)) {
|
||||
// 键集合
|
||||
Set<String> keySet = functionMap.keySet();
|
||||
// 建立查询器
|
||||
Criteria[] criteria = Arrays.stream(BeanUtils.getPropertyDescriptors(qo.getClass()))
|
||||
List<Criteria> criteria = Arrays.stream(BeanUtils.getPropertyDescriptors(qo.getClass()))
|
||||
.filter(propertyDescriptor -> keySet.contains(propertyDescriptor.getName()))
|
||||
.map(propertyDescriptor -> {
|
||||
try {
|
||||
@ -117,7 +144,13 @@ public final class CriteriaBuilder<T extends Domain> {
|
||||
return null;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(Criteria[]::new);
|
||||
.collect(Collectors.toList());
|
||||
// 添加自定义criteria
|
||||
if (CollectionUtils.isNotEmpty(criterias)) {
|
||||
for (Supplier<Criteria> builder : criterias) {
|
||||
criteria.add(builder.get());
|
||||
}
|
||||
}
|
||||
return combine(criteria);
|
||||
}
|
||||
return null;
|
||||
@ -165,12 +198,12 @@ public final class CriteriaBuilder<T extends Domain> {
|
||||
* @param criteria 结果
|
||||
* @return 返回
|
||||
*/
|
||||
private Criteria combine(Criteria[] criteria) {
|
||||
if (criteria.length == 0) {
|
||||
private Criteria combine(List<Criteria> criteria) {
|
||||
if (criteria.size() == 0) {
|
||||
return new Criteria();
|
||||
}
|
||||
if (criteria.length == 1) {
|
||||
return criteria[0];
|
||||
if (criteria.size() == 1) {
|
||||
return criteria.get(0);
|
||||
}
|
||||
return new Criteria().andOperator(criteria);
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package com.flyfish.framework.context;
|
||||
|
||||
import com.flyfish.framework.domain.base.IUser;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 异步的用户上下文
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
public class ReactiveUserContext {
|
||||
|
||||
/**
|
||||
* 当前用户
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public static Mono<IUser> currentUser() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(ctx -> (IUser) ctx.getAuthentication().getPrincipal());
|
||||
}
|
||||
}
|
@ -15,4 +15,8 @@ public abstract class AuthorizedDomain extends AuditDomain {
|
||||
// 作用域id,一般是部门。用户存储时插入
|
||||
@Property(readonly = true)
|
||||
private String authorizeId;
|
||||
|
||||
// 是否已发布,已发布的内容,谁都不能修改
|
||||
@Property(readonly = true)
|
||||
private Boolean published = false;
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ package com.flyfish.framework.domain.authorized;
|
||||
import com.flyfish.framework.builder.CriteriaBuilder;
|
||||
import com.flyfish.framework.domain.base.NameLikeQo;
|
||||
import com.flyfish.framework.domain.po.Department;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -19,12 +20,15 @@ import java.util.Set;
|
||||
@Setter
|
||||
public abstract class AuthorizedQo<T extends AuthorizedDomain> extends NameLikeQo<T> {
|
||||
|
||||
// 是否已发布
|
||||
private Boolean published;
|
||||
|
||||
/**
|
||||
* 获取可见的权限ids
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public Set<String> getAuthorizedIds() {
|
||||
private Set<String> authorizeIds() {
|
||||
if (user instanceof AuthorizedUserDetails) {
|
||||
return ((AuthorizedUserDetails) user).getAuthorityCodes();
|
||||
}
|
||||
@ -33,6 +37,17 @@ public abstract class AuthorizedQo<T extends AuthorizedDomain> extends NameLikeQ
|
||||
|
||||
@Override
|
||||
public CriteriaBuilder<T> criteriaBuilder() {
|
||||
return super.criteriaBuilder().with("authorizedIds", "authorizeId", CriteriaBuilder.Builders.IN);
|
||||
if (user.getType() == UserType.SUPER_ADMIN) {
|
||||
return super.criteriaBuilder().with("published");
|
||||
}
|
||||
return super.criteriaBuilder()
|
||||
.with(() -> Criteria.where("$or").is(
|
||||
CriteriaBuilder.createCriteriaList(
|
||||
Criteria.where("authorizeId").in(authorizeIds()),
|
||||
Criteria.where("creatorId").is(user.getId())
|
||||
.and("authorizeId").in(((AuthorizedUserDetails) user).getVisibleDeparts())
|
||||
)
|
||||
))
|
||||
.with("published");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.flyfish.framework.domain.authorized;
|
||||
|
||||
import com.flyfish.framework.domain.base.Vo;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 授权的vo,需要返回权限标识
|
||||
*
|
||||
* @param <T> 泛型
|
||||
*/
|
||||
@Data
|
||||
public abstract class AuthorizedVo<T extends AuthorizedDomain> implements Vo<T> {
|
||||
|
||||
// 是否是只读数据
|
||||
protected Boolean readonly;
|
||||
}
|
@ -130,6 +130,6 @@ public class BaseQo<T extends Domain> implements Qo<T> {
|
||||
|
||||
@Override
|
||||
public Sort sorts() {
|
||||
return Sort.by(Sort.Order.desc("createTime"));
|
||||
return Sort.by(Sort.Order.desc("modifyTime"));
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.flyfish.framework.domain.base;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.flyfish.framework.annotations.Generation;
|
||||
import com.flyfish.framework.annotations.Property;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
@ -51,7 +50,7 @@ public abstract class Domain implements Po, Named, Serializable {
|
||||
@Transient
|
||||
@JsonIgnore
|
||||
@Property(readonly = true)
|
||||
private User currentUser;
|
||||
private IUser currentUser;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
@ -83,7 +83,8 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleReact
|
||||
return Mono.justOrEmpty(QueryBuildUtils.getQuery(query))
|
||||
.flatMapMany(querying -> mongoOperations.find(querying,
|
||||
entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName()));
|
||||
entityInformation.getCollectionName()))
|
||||
.doOnNext(t -> t.setCurrentUser(query.getUser()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,6 +118,7 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleReact
|
||||
return Mono.justOrEmpty(QueryBuildUtils.getQuery(query))
|
||||
.flatMap(querying -> mongoOperations.find(querying.with(pageable),
|
||||
entityInformation.getJavaType(), entityInformation.getCollectionName())
|
||||
.doOnNext(t -> t.setCurrentUser(query.getUser()))
|
||||
.collectList()
|
||||
.flatMap(list -> ReactivePageableExecutionUtils.getPage(list, pageable, this.count(query))))
|
||||
.defaultIfEmpty(Page.empty());
|
||||
|
@ -0,0 +1,88 @@
|
||||
package com.flyfish.framework.utils;
|
||||
|
||||
import com.flyfish.framework.domain.authorized.AuthorizedDomain;
|
||||
import com.flyfish.framework.domain.authorized.AuthorizedVo;
|
||||
import com.flyfish.framework.domain.base.IUser;
|
||||
import com.flyfish.framework.domain.po.Department;
|
||||
import com.flyfish.framework.domain.po.Role;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.data.util.CastUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 部门工具类
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
public final class DepartUtils {
|
||||
|
||||
/**
|
||||
* 合并部门,有包含关系的部门将被合并
|
||||
*
|
||||
* @param departments 部门
|
||||
* @return 结果
|
||||
*/
|
||||
public static Set<String> mergeDeparts(List<Department> departments) {
|
||||
if (CollectionUtils.isEmpty(departments)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> departs = departments.stream().map(Department::getId)
|
||||
.collect(Collectors.toSet());
|
||||
List<String> removing = new ArrayList<>();
|
||||
for (Department department : departments) {
|
||||
if (CollectionUtils.containsAny(department.getParentIds(), departs)) {
|
||||
removing.add(department.getId());
|
||||
}
|
||||
}
|
||||
removing.forEach(departs::remove);
|
||||
return departs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 包装权限,必须调用
|
||||
*
|
||||
* @param item 内容
|
||||
* @return 结果
|
||||
*/
|
||||
public static <T> T wrapAuthority(T item, AuthorizedDomain po) {
|
||||
if (item instanceof AuthorizedVo) {
|
||||
AuthorizedVo<?> vo = CastUtils.cast(item);
|
||||
// 已发布的内容,谁都不能修改
|
||||
if (BooleanUtils.isTrue(po.getPublished())) {
|
||||
vo.setReadonly(true);
|
||||
} else {
|
||||
vo.setReadonly(false);
|
||||
// 获取当前用户
|
||||
IUser user = po.getCurrentUser();
|
||||
if (user.getType() != UserType.SUPER_ADMIN) {
|
||||
// 用户所属部门
|
||||
Set<String> userDeparts = DepartUtils.mergeDeparts(user.getDepartments());
|
||||
// 实体归属部门
|
||||
String currentDepart = po.getAuthorizeId();
|
||||
// 用户权限合集
|
||||
Set<Role.Authority> authorities = user.getRoles().stream()
|
||||
.flatMap(role -> null == role.getAuthorities() ? Stream.empty() : role.getAuthorities().stream())
|
||||
.collect(Collectors.toSet());
|
||||
// 取出权限,便于判定
|
||||
boolean admin = authorities.contains(Role.Authority.ADMIN);
|
||||
boolean edit = authorities.contains(Role.Authority.EDIT);
|
||||
boolean editChildren = authorities.contains(Role.Authority.EDIT_CHILDREN);
|
||||
// 开始判定只读情况,管理员权限或者创建者,均具有读写权限
|
||||
if (!admin && !po.getCreatorId().equals(user.getId())) {
|
||||
vo.setReadonly(!edit && userDeparts.contains(currentDepart) ||
|
||||
!editChildren && !userDeparts.contains(currentDepart));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.flyfish.framework.config.audit;
|
||||
|
||||
import com.flyfish.framework.auditor.ReactiveBeanPoster;
|
||||
import com.flyfish.framework.domain.po.Role;
|
||||
import com.flyfish.framework.service.UserDetailsConverter;
|
||||
import com.flyfish.framework.utils.ReactiveRedisOperations;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 角色bean后置处理
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RoleBeanPoster implements ReactiveBeanPoster<Role> {
|
||||
|
||||
private final ReactiveRedisOperations reactiveRedisOperations;
|
||||
private final UserDetailsConverter userDetailsConverter;
|
||||
|
||||
/**
|
||||
* 对入库的实体进行审查,并执行额外功能
|
||||
*
|
||||
* @param data 原数据
|
||||
*/
|
||||
@Override
|
||||
public Mono<Role> post(Role data) {
|
||||
// 更新缓存
|
||||
return reactiveRedisOperations.del(reactiveRedisOperations.getKeys("user-*")).thenReturn(data);
|
||||
}
|
||||
}
|
@ -5,11 +5,14 @@ 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.enums.UserType;
|
||||
import com.flyfish.framework.utils.UserUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
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.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -31,10 +34,17 @@ public class DepartmentController extends ReactiveTreeController<Department, Dep
|
||||
public Mono<Result<List<Department>>> getAuthorizedTree() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(UserUtils::extractUserDetails)
|
||||
.flatMap(detail -> {
|
||||
.flatMapMany(detail -> {
|
||||
AdminUserDetails details = (AdminUserDetails) detail;
|
||||
return reactiveService.getByIds(new ArrayList<>(details.getVisibleDeparts())).collectList();
|
||||
if (details.getType() == UserType.SUPER_ADMIN) {
|
||||
return reactiveService.getAll();
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(details.getVisibleDeparts())) {
|
||||
return reactiveService.getByIds(new ArrayList<>(details.getVisibleDeparts()));
|
||||
}
|
||||
return Flux.empty();
|
||||
})
|
||||
.collectList()
|
||||
.map(this::makeTree)
|
||||
.map(Result::accept);
|
||||
}
|
||||
|
@ -1,11 +1,19 @@
|
||||
package com.flyfish.framework.service;
|
||||
|
||||
import com.flyfish.framework.domain.AdminUserDetails;
|
||||
import com.flyfish.framework.domain.DepartmentQo;
|
||||
import com.flyfish.framework.domain.authorized.AuthorizedUserDetails;
|
||||
import com.flyfish.framework.domain.base.Qo;
|
||||
import com.flyfish.framework.domain.po.Department;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import com.flyfish.framework.service.impl.BaseReactiveServiceImpl;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -34,4 +42,39 @@ public class DepartmentService extends BaseReactiveServiceImpl<Department> {
|
||||
query.fields().include("_id");
|
||||
return reactiveMongoOperations.find(query, Department.class).map(Department::getId).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param query 查询
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Flux<Department> getList(Qo<Department> query) {
|
||||
if (query instanceof DepartmentQo) {
|
||||
DepartmentQo qo = (DepartmentQo) query;
|
||||
// 如果是非管理员
|
||||
if (qo.getUser().getType() != UserType.SUPER_ADMIN) {
|
||||
// 使用列表内的部门作为条件
|
||||
AdminUserDetails userDetails = (AdminUserDetails) query.getUser();
|
||||
// 查询根节点下的节点
|
||||
if (Department.ROOT.equals(qo.getParentId())) {
|
||||
qo.setParentId(null);
|
||||
qo.setIds(userDetails.getVisibleDeparts());
|
||||
// 不递归,指定深度,保证单层
|
||||
if (BooleanUtils.isNotTrue(qo.getRecursive())) {
|
||||
// 指定深度
|
||||
int maxDepth = userDetails.getDepartments().stream().max((a, b) -> a.getDepth() - b.getDepth())
|
||||
.map(Department::getDepth)
|
||||
.orElse(0);
|
||||
qo.setDepth(maxDepth);
|
||||
}
|
||||
}
|
||||
if (null == qo.getParentId() && CollectionUtils.isEmpty(qo.getParentIds())) {
|
||||
qo.setIds(userDetails.getVisibleDeparts());
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getList(query);
|
||||
}
|
||||
}
|
||||
|
@ -6,18 +6,16 @@ import com.flyfish.framework.domain.po.Department;
|
||||
import com.flyfish.framework.domain.po.Role;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import com.flyfish.framework.utils.CopyUtils;
|
||||
import com.flyfish.framework.utils.DepartUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.collections4.SetUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@ -51,16 +49,11 @@ public class UserDetailsConverter {
|
||||
*/
|
||||
private Mono<UserDetails> judgeDeparts(IUser user, AdminUserDetails userDetails) {
|
||||
// 整合数据权限
|
||||
Set<Role.Authority> authorities = user.getRoles().stream().reduce(new HashSet<>(), (result, item) -> {
|
||||
// 管理员拥有完全控制权限
|
||||
if (BooleanUtils.isTrue(item.getAdmin())) {
|
||||
result.add(Role.Authority.ADMIN);
|
||||
}
|
||||
result.addAll(item.getAuthorities());
|
||||
return result;
|
||||
}, (a, b) -> a);
|
||||
Set<Role.Authority> authorities = user.getRoles().stream()
|
||||
.flatMap(role -> null == role.getAuthorities() ? Stream.empty() : role.getAuthorities().stream())
|
||||
.collect(Collectors.toSet());
|
||||
// 根据权限组装查询条件
|
||||
Set<String> departs = mergeDeparts(user.getDepartments());
|
||||
Set<String> departs = DepartUtils.mergeDeparts(user.getDepartments());
|
||||
// 查询所有子部门id
|
||||
return departmentService.getSubCodes(departs)
|
||||
.map(codes -> {
|
||||
@ -80,30 +73,25 @@ public class UserDetailsConverter {
|
||||
}
|
||||
// 最终设置权限
|
||||
if (CollectionUtils.isNotEmpty(all)) {
|
||||
userDetails.setAuthorityCodes(SetUtils.union(all, userDetails.getAuthorityCodes()));
|
||||
userDetails.setAuthorityCodes(union(all, userDetails.getAuthorityCodes()));
|
||||
}
|
||||
userDetails.setVisibleDeparts(SetUtils.union(codes, departs));
|
||||
userDetails.setVisibleDeparts(union(codes, departs));
|
||||
return userDetails;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并部门,有包含关系的部门将被合并
|
||||
* 链接两个set
|
||||
*
|
||||
* @param departments 部门
|
||||
* @param a 第一个
|
||||
* @param b 第二个
|
||||
* @return 结果
|
||||
*/
|
||||
private Set<String> mergeDeparts(List<Department> departments) {
|
||||
Set<String> departs = departments.stream().map(Department::getId)
|
||||
.collect(Collectors.toSet());
|
||||
List<String> removing = new ArrayList<>();
|
||||
for (Department department : departments) {
|
||||
if (CollectionUtils.containsAny(department.getParentIds(), departs)) {
|
||||
removing.add(department.getId());
|
||||
}
|
||||
}
|
||||
removing.forEach(departs::remove);
|
||||
return departs;
|
||||
private Set<String> union(Set<String> a, Set<String> b) {
|
||||
Set<String> result = new HashSet<>();
|
||||
result.addAll(a);
|
||||
result.addAll(b);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,19 @@
|
||||
package com.flyfish.framework.service;
|
||||
|
||||
import com.flyfish.framework.domain.UserQo;
|
||||
import com.flyfish.framework.domain.authorized.AuthorizedUserDetails;
|
||||
import com.flyfish.framework.domain.base.Qo;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import com.flyfish.framework.enums.UserType;
|
||||
import com.flyfish.framework.repository.UserRepository;
|
||||
import com.flyfish.framework.service.impl.BaseReactiveServiceImpl;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 异步用户service
|
||||
*
|
||||
@ -25,4 +33,22 @@ public class UserService extends BaseReactiveServiceImpl<User> implements UserFi
|
||||
return ((UserRepository) repository).findByUsername(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询,这里使用作用域查询
|
||||
*
|
||||
* @param query 查询实体
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Mono<Page<User>> getPageList(Qo<User> query) {
|
||||
// 非超级管理员,永远返回作用域的部门人员
|
||||
if (query.getUser().getType() != UserType.SUPER_ADMIN) {
|
||||
AuthorizedUserDetails userDetails = (AuthorizedUserDetails) query.getUser();
|
||||
UserQo qo = (UserQo) query;
|
||||
if (CollectionUtils.isEmpty(qo.getDepartments())) {
|
||||
qo.setDepartments(new ArrayList<>(userDetails.getVisibleDeparts()));
|
||||
}
|
||||
}
|
||||
return super.getPageList(query);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.flyfish.framework.controller.reactive;
|
||||
|
||||
import com.flyfish.framework.bean.Result;
|
||||
import com.flyfish.framework.configuration.annotations.PagedQuery;
|
||||
import com.flyfish.framework.domain.tree.RootTreeNode;
|
||||
import com.flyfish.framework.domain.tree.TreeDomain;
|
||||
import com.flyfish.framework.domain.tree.TreeQo;
|
||||
@ -45,7 +46,7 @@ public abstract class ReactiveTreeController<T extends TreeDomain<T>, Q extends
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("tree")
|
||||
public Mono<Result<List<T>>> getTree(Q qo) {
|
||||
public Mono<Result<List<T>>> getTree(@PagedQuery Q qo) {
|
||||
qo.setRecursive(true);
|
||||
// 第一步,查询全部,并根据条件筛选
|
||||
return reactiveService.getList(qo)
|
||||
|
@ -73,6 +73,16 @@ public class ReactiveRedisOperations {
|
||||
return Mono.just(0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
*
|
||||
* @param key 可以传一个值 或多个
|
||||
*/
|
||||
public Mono<Long> del(Flux<String> key) {
|
||||
return redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
|
||||
// ============================String=============================
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user