feat:实现用户数据权限细化
This commit is contained in:
parent
23fbdbccf6
commit
0a0b63e480
@ -8,6 +8,7 @@ import lombok.Setter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 带鉴权的查询实体,主要以部门隔绝
|
||||
@ -23,11 +24,11 @@ public abstract class AuthorizedQo<T extends AuthorizedDomain> extends NameLikeQ
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public List<String> getAuthorizedIds() {
|
||||
public Set<String> getAuthorizedIds() {
|
||||
if (user instanceof AuthorizedUserDetails) {
|
||||
return ((AuthorizedUserDetails) user).getAuthorityCodes();
|
||||
}
|
||||
return Collections.singletonList(Department.PUBLIC);
|
||||
return Collections.singleton(Department.PUBLIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.flyfish.framework.domain.authorized;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 支持授权的用户详情
|
||||
@ -14,5 +14,12 @@ public interface AuthorizedUserDetails {
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
List<String> getAuthorityCodes();
|
||||
Set<String> getAuthorityCodes();
|
||||
|
||||
/**
|
||||
* 获取可见部门
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
Set<String> getVisibleDeparts();
|
||||
}
|
||||
|
@ -19,6 +19,11 @@ public class Department extends TreeDomain<Department> {
|
||||
|
||||
public static final String PUBLIC = "public";
|
||||
|
||||
/**
|
||||
* 部门的完整名称
|
||||
*/
|
||||
private String fullName;
|
||||
|
||||
/**
|
||||
* 默认选中
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.flyfish.framework.domain.po;
|
||||
|
||||
import com.flyfish.framework.domain.base.AuditDomain;
|
||||
import com.flyfish.framework.enums.NamedEnum;
|
||||
import com.flyfish.framework.enums.RoleType;
|
||||
import lombok.*;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
@ -46,4 +47,22 @@ public class Role extends AuditDomain {
|
||||
*/
|
||||
@DBRef
|
||||
private List<Permission> permissions;
|
||||
|
||||
/**
|
||||
* 角色拥有的数据权限
|
||||
*/
|
||||
private List<Authority> authorities;
|
||||
|
||||
/**
|
||||
* 数据规则权限
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum Authority implements NamedEnum {
|
||||
|
||||
ADMIN("拥有完全控制权限"), VIEW("查看本部门"), EDIT("编辑本部门"),
|
||||
VIEW_CHILDREN("查看所有下级"), EDIT_CHILDREN("编辑所有下级");
|
||||
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -32,7 +33,7 @@ public class DepartmentController extends ReactiveTreeController<Department, Dep
|
||||
.map(UserUtils::extractUserDetails)
|
||||
.flatMap(detail -> {
|
||||
AdminUserDetails details = (AdminUserDetails) detail;
|
||||
return reactiveService.getByIds(details.getAuthorityCodes()).collectList();
|
||||
return reactiveService.getByIds(new ArrayList<>(details.getVisibleDeparts())).collectList();
|
||||
})
|
||||
.map(this::makeTree)
|
||||
.map(Result::accept);
|
||||
|
@ -19,10 +19,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 客户端用户详情
|
||||
@ -105,7 +102,11 @@ public class AdminUserDetails implements UserDetails, IUser, AuthorizedUserDetai
|
||||
/**
|
||||
* 权限code列表
|
||||
*/
|
||||
private List<String> authorityCodes;
|
||||
private Set<String> authorityCodes;
|
||||
/**
|
||||
* 可见的部门codes
|
||||
*/
|
||||
private Set<String> visibleDeparts;
|
||||
|
||||
/**
|
||||
* 判断是否是管理员
|
||||
|
@ -10,6 +10,8 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 部门服务
|
||||
@ -27,9 +29,9 @@ public class DepartmentService extends BaseReactiveServiceImpl<Department> {
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public Mono<List<String>> getSubCodes(List<String> parents) {
|
||||
public Mono<Set<String>> getSubCodes(Set<String> parents) {
|
||||
Query query = Query.query(Criteria.where("parentIds").in(parents));
|
||||
query.fields().include("_id");
|
||||
return reactiveMongoOperations.find(query, Department.class).map(Department::getId).collectList();
|
||||
return reactiveMongoOperations.find(query, Department.class).map(Department::getId).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
@ -3,17 +3,20 @@ package com.flyfish.framework.service;
|
||||
import com.flyfish.framework.domain.AdminUserDetails;
|
||||
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 com.flyfish.framework.utils.CopyUtils;
|
||||
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.Collections;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@ -31,22 +34,76 @@ public class UserDetailsConverter {
|
||||
public Mono<UserDetails> mapToUserDetails(IUser user) {
|
||||
AdminUserDetails userDetail = new AdminUserDetails();
|
||||
CopyUtils.copyProps(user, userDetail);
|
||||
userDetail.setAuthorityCodes(Collections.singletonList(Department.PUBLIC));
|
||||
userDetail.setAuthorityCodes(Collections.singleton(Department.PUBLIC));
|
||||
if (user.getType() == UserType.SUPER_ADMIN) {
|
||||
userDetail.setAuthorityCodes(null);
|
||||
}
|
||||
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)) {
|
||||
userDetail.setAuthorityCodes(ListUtils.union(codes, userDetail.getAuthorityCodes()));
|
||||
}
|
||||
return userDetail;
|
||||
});
|
||||
} else if (CollectionUtils.isNotEmpty(user.getDepartments())) {
|
||||
return judgeDeparts(user, userDetail);
|
||||
}
|
||||
return Mono.just(userDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断部门包含关系,默认看不到本部门的数据却可以看到子部门的
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param userDetails 用户详情
|
||||
*/
|
||||
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<String> departs = mergeDeparts(user.getDepartments());
|
||||
// 查询所有子部门id
|
||||
return departmentService.getSubCodes(departs)
|
||||
.map(codes -> {
|
||||
// 取出权限,便于判定
|
||||
boolean admin = authorities.contains(Role.Authority.ADMIN);
|
||||
boolean view = authorities.contains(Role.Authority.VIEW);
|
||||
boolean viewChildren = authorities.contains(Role.Authority.VIEW_CHILDREN);
|
||||
// 全部
|
||||
Set<String> all = new HashSet<>();
|
||||
// 拥有查看本部门的权限
|
||||
if (admin || view) {
|
||||
all.addAll(departs);
|
||||
}
|
||||
// 拥有查看所有下级的权限
|
||||
if (admin || viewChildren) {
|
||||
all.addAll(codes);
|
||||
}
|
||||
// 最终设置权限
|
||||
if (CollectionUtils.isNotEmpty(all)) {
|
||||
userDetails.setAuthorityCodes(SetUtils.union(all, userDetails.getAuthorityCodes()));
|
||||
}
|
||||
userDetails.setVisibleDeparts(SetUtils.union(codes, departs));
|
||||
return userDetails;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并部门,有包含关系的部门将被合并
|
||||
*
|
||||
* @param departments 部门
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user