优化菜单管理
This commit is contained in:
parent
70b45ee12c
commit
2a96d6896d
|
|
@ -0,0 +1,47 @@
|
|||
package org.jetlinks.community.auth.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MenuButtonInfo {
|
||||
|
||||
@Schema(description = "按钮ID")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "按钮名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "权限信息")
|
||||
private List<PermissionInfo> permissions;
|
||||
|
||||
@Schema(description = "其他配置")
|
||||
private Map<String, Object> options;
|
||||
|
||||
public boolean hasPermission(BiPredicate<String, Collection<String>> predicate) {
|
||||
if (CollectionUtils.isEmpty(permissions)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (PermissionInfo permission : permissions) {
|
||||
if (!predicate.test(permission.getPermission(), permission.getActions())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static MenuButtonInfo of(String id, String name, String permission, String... actions) {
|
||||
MenuButtonInfo info = new MenuButtonInfo();
|
||||
info.setId(id);
|
||||
info.setName(name);
|
||||
info.setPermissions(Arrays.asList(PermissionInfo.of(permission, new HashSet<>(Arrays.asList(actions)))));
|
||||
return info;
|
||||
}
|
||||
}
|
||||
96
jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java
Normal file → Executable file
96
jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/entity/MenuEntity.java
Normal file → Executable file
|
|
@ -1,29 +1,41 @@
|
|||
package org.jetlinks.community.auth.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec;
|
||||
import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
|
||||
import org.jetlinks.community.auth.web.request.AuthorizationSettingDetail;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import java.sql.JDBCType;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 菜单定义实体类
|
||||
*
|
||||
* @author wangzheng
|
||||
* @since 1.0
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "s_menu", indexes = {
|
||||
@Index(name = "idx_menu_path", columnList = "path")
|
||||
@Index(name = "idx_menu_path", columnList = "path")
|
||||
})
|
||||
public class MenuEntity
|
||||
extends GenericTreeSortSupportEntity<String> {
|
||||
extends GenericTreeSortSupportEntity<String> {
|
||||
|
||||
@Schema(description = "名称")
|
||||
@Comment("菜单名称")
|
||||
@Column(length = 32)
|
||||
private String name;
|
||||
|
|
@ -31,29 +43,101 @@ public class MenuEntity
|
|||
@Comment("描述")
|
||||
@Column
|
||||
@ColumnType(jdbcType = JDBCType.CLOB)
|
||||
@Schema(description = "描述")
|
||||
private String describe;
|
||||
|
||||
@Hidden
|
||||
@Deprecated
|
||||
@Comment("权限表达式")
|
||||
@Column(name = "permission_expression", length = 256)
|
||||
private String permissionExpression;
|
||||
|
||||
@Comment("菜单对应的url")
|
||||
@Column(length = 512)
|
||||
@Schema(description = "URL,路由")
|
||||
private String url;
|
||||
|
||||
@Comment("图标")
|
||||
@Column(length = 256)
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Comment("状态")
|
||||
@Column
|
||||
@ColumnType(jdbcType = JDBCType.SMALLINT)
|
||||
@Schema(description = "状态,0为禁用,1为启用")
|
||||
@DefaultValue("1")
|
||||
private Byte status;
|
||||
|
||||
@Schema(description = "默认权限信息")
|
||||
@Column
|
||||
@JsonCodec
|
||||
@ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class)
|
||||
private List<PermissionInfo> permissions;
|
||||
|
||||
@Schema(description = "按钮定义信息")
|
||||
@Column
|
||||
@JsonCodec
|
||||
@ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class)
|
||||
private List<MenuButtonInfo> buttons;
|
||||
|
||||
@Schema(description = "其他配置信息")
|
||||
@Column
|
||||
@JsonCodec
|
||||
@ColumnType(jdbcType = JDBCType.LONGVARCHAR, javaType = String.class)
|
||||
private Map<String, Object> options;
|
||||
|
||||
//子菜单
|
||||
@Schema(description = "子菜单")
|
||||
private List<MenuEntity> children;
|
||||
|
||||
@Override
|
||||
public List<MenuEntity> getChildren() {
|
||||
return children;
|
||||
public MenuEntity copy(Predicate<MenuButtonInfo> buttonPredicate) {
|
||||
MenuEntity entity = this.copyTo(new MenuEntity());
|
||||
|
||||
if (CollectionUtils.isEmpty(entity.getButtons())) {
|
||||
return entity;
|
||||
}
|
||||
entity.setButtons(
|
||||
entity
|
||||
.getButtons()
|
||||
.stream()
|
||||
.filter(buttonPredicate)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public boolean hasPermission(BiPredicate<String, Collection<String>> predicate) {
|
||||
if (CollectionUtils.isEmpty(permissions) && CollectionUtils.isEmpty(buttons)) {
|
||||
return false;
|
||||
}
|
||||
//有权限信息
|
||||
if (CollectionUtils.isNotEmpty(permissions)) {
|
||||
for (PermissionInfo permission : permissions) {
|
||||
if (!predicate.test(permission.getPermission(), permission.getActions())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//有任意按钮信息
|
||||
if (CollectionUtils.isNotEmpty(buttons)) {
|
||||
for (MenuButtonInfo button : buttons) {
|
||||
if (button.hasPermission(predicate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Optional<MenuButtonInfo> getButton(String id) {
|
||||
if (buttons == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return buttons
|
||||
.stream()
|
||||
.filter(button -> Objects.equals(button.getId(), id))
|
||||
.findAny();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package org.jetlinks.community.auth.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
|
||||
import org.hswebframework.web.bean.FastBeanCopier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MenuView extends GenericTreeSortSupportEntity<String> {
|
||||
|
||||
@Schema(description = "菜单名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "图标")
|
||||
private String icon;
|
||||
|
||||
@Schema(description = "URL")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "父节点")
|
||||
private String parentId;
|
||||
|
||||
@Schema(description = "按钮")
|
||||
private List<ButtonView> buttons;
|
||||
|
||||
@Schema(description = "其他配置")
|
||||
private Map<String, Object> options;
|
||||
|
||||
@Schema(description = "子节点")
|
||||
private List<MenuView> children;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
@NoArgsConstructor
|
||||
public static class ButtonView{
|
||||
|
||||
@Schema(description = "按钮ID")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "按钮名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "其他配置")
|
||||
private Map<String,Object> options;
|
||||
}
|
||||
|
||||
public static MenuView of(MenuEntity entity){
|
||||
return FastBeanCopier.copy(entity,new MenuView());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.jetlinks.community.auth.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
@NoArgsConstructor
|
||||
public class PermissionInfo {
|
||||
|
||||
@Schema(description = "权限ID")
|
||||
private String permission;
|
||||
|
||||
@Schema(description = "权限操作")
|
||||
private Set<String> actions;
|
||||
|
||||
}
|
||||
176
jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/MenuController.java
Normal file → Executable file
176
jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/MenuController.java
Normal file → Executable file
|
|
@ -1,31 +1,37 @@
|
|||
package org.jetlinks.community.auth.web;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
|
||||
import org.hswebframework.web.authorization.Authentication;
|
||||
import org.hswebframework.web.authorization.AuthenticationUtils;
|
||||
import org.hswebframework.web.authorization.annotation.Authorize;
|
||||
import org.hswebframework.web.authorization.annotation.Resource;
|
||||
import org.hswebframework.web.authorization.annotation.ResourceAction;
|
||||
import org.hswebframework.web.authorization.exception.UnAuthorizedException;
|
||||
import org.hswebframework.web.crud.service.ReactiveCrudService;
|
||||
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
|
||||
import org.jetlinks.community.auth.entity.MenuButtonInfo;
|
||||
import org.jetlinks.community.auth.entity.MenuEntity;
|
||||
import org.jetlinks.community.auth.entity.MenuView;
|
||||
import org.jetlinks.community.auth.service.AuthorizationSettingDetailService;
|
||||
import org.jetlinks.community.auth.service.DefaultMenuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.jetlinks.community.auth.web.request.MenuGrantRequest;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 菜单管理
|
||||
*
|
||||
* @author wangzheng
|
||||
* @since 1.0
|
||||
*/
|
||||
|
|
@ -33,27 +39,140 @@ import java.util.stream.Collectors;
|
|||
@RequestMapping("/menu")
|
||||
@Authorize
|
||||
@Resource(id = "menu", name = "菜单管理", group = "system")
|
||||
@Hidden
|
||||
@Tag(name = "菜单管理")
|
||||
@AllArgsConstructor
|
||||
public class MenuController implements ReactiveServiceCrudController<MenuEntity, String> {
|
||||
|
||||
@Autowired
|
||||
private DefaultMenuService defaultMenuService;
|
||||
private final DefaultMenuService defaultMenuService;
|
||||
|
||||
private final AuthorizationSettingDetailService settingService;
|
||||
|
||||
@Override
|
||||
public ReactiveCrudService<MenuEntity, String> getService() {
|
||||
return defaultMenuService;
|
||||
}
|
||||
|
||||
public Collection<MenuEntity> predicateUserMenu(Map<String, MenuEntity> menuMap, Authentication autz) {
|
||||
/**
|
||||
* 获取用户自己的菜单列表
|
||||
*
|
||||
* @return 菜单列表
|
||||
*/
|
||||
@GetMapping("/user-own/tree")
|
||||
@Authorize(merge = false)
|
||||
@Operation(summary = "获取当前用户可访问的菜单(树结构)")
|
||||
public Flux<MenuView> getUserMenuAsTree() {
|
||||
return this
|
||||
.getUserMenuAsList()
|
||||
.as(MenuController::listToTree);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/user-own/list")
|
||||
@Authorize(merge = false)
|
||||
@Operation(summary = "获取当前用户可访问的菜单(列表结构)")
|
||||
public Flux<MenuView> getUserMenuAsList() {
|
||||
return Authentication
|
||||
.currentReactive()
|
||||
.switchIfEmpty(Mono.error(UnAuthorizedException::new))
|
||||
.flatMapMany(autz -> defaultMenuService
|
||||
.createQuery()
|
||||
.where(MenuEntity::getStatus,1)
|
||||
.fetch()
|
||||
.collect(Collectors.toMap(MenuEntity::getId, Function.identity()))
|
||||
.flatMapIterable(menuMap -> MenuController
|
||||
.convertMenuView(menuMap,
|
||||
menu -> "admin".equals(autz.getUser().getUsername()) ||
|
||||
menu.hasPermission(autz::hasPermission),
|
||||
button -> "admin".equals(autz.getUser().getUsername()) ||
|
||||
button.hasPermission(autz::hasPermission)
|
||||
)));
|
||||
}
|
||||
|
||||
@PutMapping("/_grant")
|
||||
@Operation(summary = "根据菜单进行授权")
|
||||
@ResourceAction(id = "grant", name = "授权")
|
||||
public Mono<Void> grant(@RequestBody Mono<MenuGrantRequest> body) {
|
||||
return Mono
|
||||
.zip(
|
||||
//T1: 当前用户权限信息
|
||||
Authentication.currentReactive(),
|
||||
//T2: 将菜单信息转为授权信息
|
||||
Mono
|
||||
.zip(body,
|
||||
defaultMenuService
|
||||
.createQuery()
|
||||
.where(MenuEntity::getStatus,1)
|
||||
.fetch()
|
||||
.collectList(),
|
||||
MenuGrantRequest::toAuthorizationSettingDetail
|
||||
)
|
||||
.map(Flux::just),
|
||||
//保存授权信息
|
||||
settingService::saveDetail
|
||||
)
|
||||
.flatMap(Function.identity());
|
||||
}
|
||||
|
||||
@GetMapping("/{targetType}/{targetId}/_grant/tree")
|
||||
@ResourceAction(id = "grant", name = "授权")
|
||||
@Operation(summary = "获取菜单授权信息(树结构)")
|
||||
public Flux<MenuView> getGrantInfoTree(@PathVariable String targetType,
|
||||
@PathVariable String targetId) {
|
||||
|
||||
return this
|
||||
.getGrantInfo(targetType, targetId)
|
||||
.as(MenuController::listToTree);
|
||||
}
|
||||
|
||||
@GetMapping("/{targetType}/{targetId}/_grant/list")
|
||||
@ResourceAction(id = "grant", name = "授权")
|
||||
@Operation(summary = "获取菜单授权信息(列表结构)")
|
||||
public Flux<MenuView> getGrantInfo(@PathVariable String targetType,
|
||||
@PathVariable String targetId) {
|
||||
|
||||
return Mono
|
||||
.zip(
|
||||
//权限设置信息
|
||||
settingService.getSettingDetail(targetType, targetId),
|
||||
//菜单
|
||||
defaultMenuService
|
||||
.createQuery()
|
||||
.where(MenuEntity::getStatus,1)
|
||||
.fetch()
|
||||
.collectMap(MenuEntity::getId, Function.identity()),
|
||||
(detail, menuMap) -> MenuController
|
||||
.convertMenuView(menuMap,
|
||||
menu -> menu.hasPermission(detail::hasPermission),
|
||||
button -> button.hasPermission(detail::hasPermission)
|
||||
)
|
||||
)
|
||||
.flatMapIterable(Function.identity());
|
||||
}
|
||||
|
||||
private static Flux<MenuView> listToTree(Flux<MenuView> flux) {
|
||||
return flux
|
||||
.collectList()
|
||||
.flatMapIterable(list -> TreeSupportEntity
|
||||
.list2tree(list,
|
||||
MenuView::setChildren,
|
||||
(Predicate<MenuView>) n ->
|
||||
StringUtils.isEmpty(n.getParentId())
|
||||
|| "-1".equals(n.getParentId())));
|
||||
}
|
||||
|
||||
private static Collection<MenuView> convertMenuView(Map<String, MenuEntity> menuMap,
|
||||
Predicate<MenuEntity> menuPredicate,
|
||||
Predicate<MenuButtonInfo> buttonPredicate) {
|
||||
Map<String, MenuEntity> group = new HashMap<>();
|
||||
for (MenuEntity menu : menuMap.values()) {
|
||||
if (group.containsKey(menu.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (autz.getUser().getUsername().equals("admin") || AuthenticationUtils.createPredicate(menu.getPermissionExpression()).test(autz)) {
|
||||
if (menuPredicate.test(menu)) {
|
||||
String parentId = menu.getParentId();
|
||||
MenuEntity parent;
|
||||
group.put(menu.getId(), menu);
|
||||
//有子菜单默认就有父菜单
|
||||
while (!StringUtils.isEmpty(parentId)) {
|
||||
parent = menuMap.get(parentId);
|
||||
if (parent == null) {
|
||||
|
|
@ -64,33 +183,12 @@ public class MenuController implements ReactiveServiceCrudController<MenuEntity,
|
|||
}
|
||||
}
|
||||
}
|
||||
List<MenuEntity> list = new ArrayList<>(group.values());
|
||||
Collections.sort(list);
|
||||
|
||||
return list;
|
||||
return group
|
||||
.values()
|
||||
.stream()
|
||||
.map(menu -> MenuView.of(menu.copy(buttonPredicate)))
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户自己的菜单列表
|
||||
* @return 菜单列表
|
||||
*/
|
||||
@GetMapping("user-own/tree")
|
||||
@Authorize(merge = false)
|
||||
public Flux<MenuEntity> getUserMenuAsTree() {
|
||||
return Authentication
|
||||
.currentReactive()
|
||||
.switchIfEmpty(Mono.error(UnAuthorizedException::new))
|
||||
.flatMapMany(autz -> defaultMenuService
|
||||
.createQuery()
|
||||
.fetch()
|
||||
.collect(Collectors.toMap(MenuEntity::getId, Function.identity()))
|
||||
.map(menuMap -> predicateUserMenu(menuMap, autz))
|
||||
.map(menus -> TreeSupportEntity.list2tree(
|
||||
menus,
|
||||
MenuEntity::setChildren,
|
||||
(Predicate<MenuEntity>) n ->
|
||||
StringUtils.isEmpty(n.getParentId())
|
||||
|| "-1".equals(n.getParentId()))).flatMapMany(Flux::fromIterable));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
45
jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/request/AuthorizationSettingDetail.java
Normal file → Executable file
45
jetlinks-manager/authentication-manager/src/main/java/org/jetlinks/community/auth/web/request/AuthorizationSettingDetail.java
Normal file → Executable file
|
|
@ -1,5 +1,7 @@
|
|||
package org.jetlinks.community.auth.web.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.hswebframework.web.authorization.Dimension;
|
||||
|
|
@ -25,56 +27,85 @@ public class AuthorizationSettingDetail {
|
|||
* 设置目标类型(维度)标识,如: org, role
|
||||
*/
|
||||
@NotBlank
|
||||
@Schema(description = "权限类型,如: org,openApi")
|
||||
private String targetType;
|
||||
|
||||
/**
|
||||
* 设置目标.
|
||||
*/
|
||||
@NotBlank
|
||||
@Schema(description = "权限类型对应的数据ID")
|
||||
private String targetId;
|
||||
|
||||
/**
|
||||
* 冲突时是否合并
|
||||
*/
|
||||
@Schema(description = "冲突时是否合并")
|
||||
private boolean merge = true;
|
||||
|
||||
/**
|
||||
* 冲突时优先级
|
||||
*/
|
||||
@Schema(description = "冲突时合并优先级")
|
||||
private int priority = 10;
|
||||
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
@Schema(description = "权限列表")
|
||||
private List<PermissionInfo> permissionList;
|
||||
|
||||
public boolean hasPermission(String id, Collection<String> actions) {
|
||||
if (CollectionUtils.isEmpty(permissionList)) {
|
||||
return false;
|
||||
}
|
||||
for (PermissionInfo info : permissionList) {
|
||||
if (Objects.equals(info.getId(), id)) {
|
||||
if (CollectionUtils.isEmpty(actions)) {
|
||||
return true;
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(info.getActions())) {
|
||||
if (info.getActions().containsAll(actions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权信息
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@Generated
|
||||
public static class PermissionInfo {
|
||||
|
||||
/**
|
||||
* 权限ID
|
||||
*/
|
||||
@NotBlank
|
||||
@Schema(description = "权限ID")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 授权操作
|
||||
*/
|
||||
@Schema(description = "允许执行的操作")
|
||||
private Set<String> actions;
|
||||
|
||||
/**
|
||||
* 字段权限
|
||||
*/
|
||||
@Hidden
|
||||
private List<FieldAccess> fieldAccess;
|
||||
|
||||
/**
|
||||
* 数据权限
|
||||
*/
|
||||
@Hidden
|
||||
private List<DataAccess> dataAccess;
|
||||
|
||||
private PermissionInfo unwrap(AuthorizationSettingEntity entity) {
|
||||
|
|
@ -94,8 +125,8 @@ public class AuthorizationSettingDetail {
|
|||
//字段权限
|
||||
if (DataAccessConfig.DefaultType.DENY_FIELDS.equalsIgnoreCase(access.getType())) {
|
||||
Set<String> fields = Optional.ofNullable(access.getConfig())
|
||||
.<Set<String>>map(conf -> new HashSet<>((Collection<String>) conf.get("fields")))
|
||||
.orElseGet(HashSet::new);
|
||||
.<Set<String>>map(conf -> new HashSet<>((Collection<String>) conf.get("fields")))
|
||||
.orElseGet(HashSet::new);
|
||||
|
||||
for (String field : fields) {
|
||||
filedAccessMap
|
||||
|
|
@ -130,7 +161,7 @@ public class AuthorizationSettingDetail {
|
|||
for (FieldAccess access : fieldAccess) {
|
||||
for (String action : access.getAction()) {
|
||||
group.computeIfAbsent(action, r -> new HashSet<>())
|
||||
.add(access.name);
|
||||
.add(access.name);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Set<String>> entry : group.entrySet()) {
|
||||
|
|
@ -150,6 +181,12 @@ public class AuthorizationSettingDetail {
|
|||
entity.setDataAccesses(entities);
|
||||
}
|
||||
|
||||
public static PermissionInfo of(String id, Collection<String> actions) {
|
||||
PermissionInfo info = new PermissionInfo();
|
||||
info.setId(id);
|
||||
info.setActions(new HashSet<>(actions));
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -184,7 +221,7 @@ public class AuthorizationSettingDetail {
|
|||
}
|
||||
|
||||
public List<DataAccessEntity> toEntity() {
|
||||
if(CollectionUtils.isEmpty(actions)){
|
||||
if (CollectionUtils.isEmpty(actions)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return actions
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
package org.jetlinks.community.auth.web.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import org.jetlinks.community.auth.entity.MenuView;
|
||||
import org.jetlinks.community.auth.entity.MenuEntity;
|
||||
import org.jetlinks.community.auth.entity.MenuView;
|
||||
import org.jetlinks.community.auth.entity.PermissionInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MenuGrantRequest {
|
||||
|
||||
|
||||
private String targetType;
|
||||
|
||||
private String targetId;
|
||||
|
||||
/**
|
||||
* 冲突时是否合并
|
||||
*/
|
||||
@Schema(description = "冲突时是否合并")
|
||||
private boolean merge = true;
|
||||
|
||||
/**
|
||||
* 冲突时优先级
|
||||
*/
|
||||
@Schema(description = "冲突时合并优先级")
|
||||
private int priority = 10;
|
||||
|
||||
@Schema(description = "授权的菜单信息")
|
||||
private List<MenuView> menus;
|
||||
|
||||
public AuthorizationSettingDetail toAuthorizationSettingDetail(List<MenuEntity> menuEntities) {
|
||||
Map<String, MenuEntity> menuMap = menuEntities
|
||||
.stream()
|
||||
.collect(Collectors.toMap(MenuEntity::getId, Function.identity()));
|
||||
AuthorizationSettingDetail detail = new AuthorizationSettingDetail();
|
||||
detail.setTargetType(targetType);
|
||||
detail.setTargetId(targetId);
|
||||
detail.setMerge(merge);
|
||||
detail.setPriority(priority);
|
||||
|
||||
List<AuthorizationSettingDetail.PermissionInfo> permissionInfos = new ArrayList<>();
|
||||
|
||||
for (MenuView menu : menus) {
|
||||
//平铺
|
||||
List<MenuView> expand = TreeSupportEntity.expandTree2List(menu, IDGenerator.MD5);
|
||||
for (MenuView menuView : expand) {
|
||||
MenuEntity entity = menuMap.get(menuView.getId());
|
||||
if (entity == null) {
|
||||
continue;
|
||||
}
|
||||
//自动持有配置的权限
|
||||
if (CollectionUtils.isNotEmpty(entity.getPermissions())) {
|
||||
for (PermissionInfo permission : entity.getPermissions()) {
|
||||
permissionInfos.add(AuthorizationSettingDetail.PermissionInfo.of(permission.getPermission(), permission.getActions()));
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(menuView.getButtons())) {
|
||||
for (MenuView.ButtonView button : menuView.getButtons()) {
|
||||
entity.getButton(button.getId())
|
||||
.ifPresent(buttonInfo -> {
|
||||
if (CollectionUtils.isNotEmpty(buttonInfo.getPermissions())) {
|
||||
for (PermissionInfo permission : buttonInfo.getPermissions()) {
|
||||
permissionInfos
|
||||
.add(AuthorizationSettingDetail.PermissionInfo.of(permission.getPermission(), permission.getActions()));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
detail.setPermissionList(permissionInfos);
|
||||
|
||||
return detail;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue