feat:完整实现权限隔离

This commit is contained in:
wangyu 2022-01-03 01:19:44 +08:00
parent 0a0b63e480
commit 38f90de292
16 changed files with 341 additions and 50 deletions

View File

@ -3,19 +3,22 @@ package com.flyfish.framework.builder;
import com.flyfish.framework.context.DateContext; import com.flyfish.framework.context.DateContext;
import com.flyfish.framework.domain.base.Domain; import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.domain.base.Qo; import com.flyfish.framework.domain.base.Qo;
import com.mongodb.BasicDBList;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.ClassUtils;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.*;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -25,12 +28,11 @@ import java.util.stream.Collectors;
*/ */
public final class CriteriaBuilder<T extends Domain> { 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 Qo<T> qo;
private Map<String, BiFunction<Criteria, Object, Criteria>> functionMap = new HashMap<>();
private Map<String, String> keyMapper = new HashMap<>();
/** /**
* 构造器接受一个qo * 构造器接受一个qo
* *
@ -44,6 +46,20 @@ public final class CriteriaBuilder<T extends Domain> {
return builder; 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; 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() { public Criteria build() {
if (!CollectionUtils.isEmpty(functionMap)) { if (!MapUtils.isEmpty(functionMap)) {
// 键集合 // 键集合
Set<String> keySet = functionMap.keySet(); 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())) .filter(propertyDescriptor -> keySet.contains(propertyDescriptor.getName()))
.map(propertyDescriptor -> { .map(propertyDescriptor -> {
try { try {
@ -117,7 +144,13 @@ public final class CriteriaBuilder<T extends Domain> {
return null; return null;
}) })
.filter(Objects::nonNull) .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 combine(criteria);
} }
return null; return null;
@ -165,12 +198,12 @@ public final class CriteriaBuilder<T extends Domain> {
* @param criteria 结果 * @param criteria 结果
* @return 返回 * @return 返回
*/ */
private Criteria combine(Criteria[] criteria) { private Criteria combine(List<Criteria> criteria) {
if (criteria.length == 0) { if (criteria.size() == 0) {
return new Criteria(); return new Criteria();
} }
if (criteria.length == 1) { if (criteria.size() == 1) {
return criteria[0]; return criteria.get(0);
} }
return new Criteria().andOperator(criteria); return new Criteria().andOperator(criteria);
} }

View File

@ -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());
}
}

View File

@ -15,4 +15,8 @@ public abstract class AuthorizedDomain extends AuditDomain {
// 作用域id一般是部门用户存储时插入 // 作用域id一般是部门用户存储时插入
@Property(readonly = true) @Property(readonly = true)
private String authorizeId; private String authorizeId;
// 是否已发布已发布的内容谁都不能修改
@Property(readonly = true)
private Boolean published = false;
} }

View File

@ -3,11 +3,12 @@ package com.flyfish.framework.domain.authorized;
import com.flyfish.framework.builder.CriteriaBuilder; import com.flyfish.framework.builder.CriteriaBuilder;
import com.flyfish.framework.domain.base.NameLikeQo; import com.flyfish.framework.domain.base.NameLikeQo;
import com.flyfish.framework.domain.po.Department; import com.flyfish.framework.domain.po.Department;
import com.flyfish.framework.enums.UserType;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.mongodb.core.query.Criteria;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
@ -19,12 +20,15 @@ import java.util.Set;
@Setter @Setter
public abstract class AuthorizedQo<T extends AuthorizedDomain> extends NameLikeQo<T> { public abstract class AuthorizedQo<T extends AuthorizedDomain> extends NameLikeQo<T> {
// 是否已发布
private Boolean published;
/** /**
* 获取可见的权限ids * 获取可见的权限ids
* *
* @return 结果 * @return 结果
*/ */
public Set<String> getAuthorizedIds() { private Set<String> authorizeIds() {
if (user instanceof AuthorizedUserDetails) { if (user instanceof AuthorizedUserDetails) {
return ((AuthorizedUserDetails) user).getAuthorityCodes(); return ((AuthorizedUserDetails) user).getAuthorityCodes();
} }
@ -33,6 +37,17 @@ public abstract class AuthorizedQo<T extends AuthorizedDomain> extends NameLikeQ
@Override @Override
public CriteriaBuilder<T> criteriaBuilder() { 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");
} }
} }

View File

@ -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;
}

View File

@ -130,6 +130,6 @@ public class BaseQo<T extends Domain> implements Qo<T> {
@Override @Override
public Sort sorts() { public Sort sorts() {
return Sort.by(Sort.Order.desc("createTime")); return Sort.by(Sort.Order.desc("modifyTime"));
} }
} }

View File

@ -3,7 +3,6 @@ package com.flyfish.framework.domain.base;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.flyfish.framework.annotations.Generation; import com.flyfish.framework.annotations.Generation;
import com.flyfish.framework.annotations.Property; import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.domain.po.User;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
@ -51,7 +50,7 @@ public abstract class Domain implements Po, Named, Serializable {
@Transient @Transient
@JsonIgnore @JsonIgnore
@Property(readonly = true) @Property(readonly = true)
private User currentUser; private IUser currentUser;
@Override @Override
public int hashCode() { public int hashCode() {

View File

@ -83,7 +83,8 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleReact
return Mono.justOrEmpty(QueryBuildUtils.getQuery(query)) return Mono.justOrEmpty(QueryBuildUtils.getQuery(query))
.flatMapMany(querying -> mongoOperations.find(querying, .flatMapMany(querying -> mongoOperations.find(querying,
entityInformation.getJavaType(), 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)) return Mono.justOrEmpty(QueryBuildUtils.getQuery(query))
.flatMap(querying -> mongoOperations.find(querying.with(pageable), .flatMap(querying -> mongoOperations.find(querying.with(pageable),
entityInformation.getJavaType(), entityInformation.getCollectionName()) entityInformation.getJavaType(), entityInformation.getCollectionName())
.doOnNext(t -> t.setCurrentUser(query.getUser()))
.collectList() .collectList()
.flatMap(list -> ReactivePageableExecutionUtils.getPage(list, pageable, this.count(query)))) .flatMap(list -> ReactivePageableExecutionUtils.getPage(list, pageable, this.count(query))))
.defaultIfEmpty(Page.empty()); .defaultIfEmpty(Page.empty());

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -5,11 +5,14 @@ import com.flyfish.framework.controller.reactive.ReactiveTreeController;
import com.flyfish.framework.domain.AdminUserDetails; import com.flyfish.framework.domain.AdminUserDetails;
import com.flyfish.framework.domain.DepartmentQo; import com.flyfish.framework.domain.DepartmentQo;
import com.flyfish.framework.domain.po.Department; import com.flyfish.framework.domain.po.Department;
import com.flyfish.framework.enums.UserType;
import com.flyfish.framework.utils.UserUtils; import com.flyfish.framework.utils.UserUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.ArrayList; import java.util.ArrayList;
@ -31,10 +34,17 @@ public class DepartmentController extends ReactiveTreeController<Department, Dep
public Mono<Result<List<Department>>> getAuthorizedTree() { public Mono<Result<List<Department>>> getAuthorizedTree() {
return ReactiveSecurityContextHolder.getContext() return ReactiveSecurityContextHolder.getContext()
.map(UserUtils::extractUserDetails) .map(UserUtils::extractUserDetails)
.flatMap(detail -> { .flatMapMany(detail -> {
AdminUserDetails details = (AdminUserDetails) 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(this::makeTree)
.map(Result::accept); .map(Result::accept);
} }

View File

@ -1,11 +1,19 @@
package com.flyfish.framework.service; 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.domain.po.Department;
import com.flyfish.framework.enums.UserType;
import com.flyfish.framework.service.impl.BaseReactiveServiceImpl; 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.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -34,4 +42,39 @@ public class DepartmentService extends BaseReactiveServiceImpl<Department> {
query.fields().include("_id"); query.fields().include("_id");
return reactiveMongoOperations.find(query, Department.class).map(Department::getId).collect(Collectors.toSet()); 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);
}
} }

View File

@ -6,18 +6,16 @@ import com.flyfish.framework.domain.po.Department;
import com.flyfish.framework.domain.po.Role; import com.flyfish.framework.domain.po.Role;
import com.flyfish.framework.enums.UserType; import com.flyfish.framework.enums.UserType;
import com.flyfish.framework.utils.CopyUtils; import com.flyfish.framework.utils.CopyUtils;
import com.flyfish.framework.utils.DepartUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.val;
import org.apache.commons.collections4.CollectionUtils; 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.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@ -51,16 +49,11 @@ public class UserDetailsConverter {
*/ */
private Mono<UserDetails> judgeDeparts(IUser user, AdminUserDetails userDetails) { private Mono<UserDetails> judgeDeparts(IUser user, AdminUserDetails userDetails) {
// 整合数据权限 // 整合数据权限
Set<Role.Authority> authorities = user.getRoles().stream().reduce(new HashSet<>(), (result, item) -> { Set<Role.Authority> authorities = user.getRoles().stream()
// 管理员拥有完全控制权限 .flatMap(role -> null == role.getAuthorities() ? Stream.empty() : role.getAuthorities().stream())
if (BooleanUtils.isTrue(item.getAdmin())) { .collect(Collectors.toSet());
result.add(Role.Authority.ADMIN);
}
result.addAll(item.getAuthorities());
return result;
}, (a, b) -> a);
// 根据权限组装查询条件 // 根据权限组装查询条件
Set<String> departs = mergeDeparts(user.getDepartments()); Set<String> departs = DepartUtils.mergeDeparts(user.getDepartments());
// 查询所有子部门id // 查询所有子部门id
return departmentService.getSubCodes(departs) return departmentService.getSubCodes(departs)
.map(codes -> { .map(codes -> {
@ -80,30 +73,25 @@ public class UserDetailsConverter {
} }
// 最终设置权限 // 最终设置权限
if (CollectionUtils.isNotEmpty(all)) { 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; return userDetails;
}); });
} }
/** /**
* 合并部门有包含关系的部门将被合并 * 链接两个set
* *
* @param departments 部门 * @param a 第一个
* @param b 第二个
* @return 结果 * @return 结果
*/ */
private Set<String> mergeDeparts(List<Department> departments) { private Set<String> union(Set<String> a, Set<String> b) {
Set<String> departs = departments.stream().map(Department::getId) Set<String> result = new HashSet<>();
.collect(Collectors.toSet()); result.addAll(a);
List<String> removing = new ArrayList<>(); result.addAll(b);
for (Department department : departments) { return result;
if (CollectionUtils.containsAny(department.getParentIds(), departs)) {
removing.add(department.getId());
}
}
removing.forEach(departs::remove);
return departs;
} }
} }

View File

@ -1,11 +1,19 @@
package com.flyfish.framework.service; 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.domain.po.User;
import com.flyfish.framework.enums.UserType;
import com.flyfish.framework.repository.UserRepository; import com.flyfish.framework.repository.UserRepository;
import com.flyfish.framework.service.impl.BaseReactiveServiceImpl; 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 org.springframework.stereotype.Service;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.ArrayList;
/** /**
* 异步用户service * 异步用户service
* *
@ -25,4 +33,22 @@ public class UserService extends BaseReactiveServiceImpl<User> implements UserFi
return ((UserRepository) repository).findByUsername(username); 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);
}
} }

View File

@ -1,6 +1,7 @@
package com.flyfish.framework.controller.reactive; package com.flyfish.framework.controller.reactive;
import com.flyfish.framework.bean.Result; 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.RootTreeNode;
import com.flyfish.framework.domain.tree.TreeDomain; import com.flyfish.framework.domain.tree.TreeDomain;
import com.flyfish.framework.domain.tree.TreeQo; import com.flyfish.framework.domain.tree.TreeQo;
@ -45,7 +46,7 @@ public abstract class ReactiveTreeController<T extends TreeDomain<T>, Q extends
* @return 结果 * @return 结果
*/ */
@GetMapping("tree") @GetMapping("tree")
public Mono<Result<List<T>>> getTree(Q qo) { public Mono<Result<List<T>>> getTree(@PagedQuery Q qo) {
qo.setRecursive(true); qo.setRecursive(true);
// 第一步查询全部并根据条件筛选 // 第一步查询全部并根据条件筛选
return reactiveService.getList(qo) return reactiveService.getList(qo)

View File

@ -73,6 +73,16 @@ public class ReactiveRedisOperations {
return Mono.just(0L); return Mono.just(0L);
} }
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public Mono<Long> del(Flux<String> key) {
return redisTemplate.delete(key);
}
// ============================String============================= // ============================String=============================
/** /**