feat(角色分组): 社区版移植角色分组功能 (#451)
This commit is contained in:
parent
a5b3039be9
commit
4cb4422537
|
|
@ -15,6 +15,7 @@ import org.hswebframework.web.authorization.Dimension;
|
||||||
import org.hswebframework.web.authorization.simple.SimpleDimension;
|
import org.hswebframework.web.authorization.simple.SimpleDimension;
|
||||||
import org.hswebframework.web.crud.generator.Generators;
|
import org.hswebframework.web.crud.generator.Generators;
|
||||||
import org.jetlinks.community.auth.enums.RoleState;
|
import org.jetlinks.community.auth.enums.RoleState;
|
||||||
|
import org.jetlinks.community.auth.service.RoleGroupService;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
@ -42,6 +43,11 @@ public class RoleEntity extends GenericEntity<String> implements RecordCreationE
|
||||||
@DefaultValue("enabled")
|
@DefaultValue("enabled")
|
||||||
private RoleState state;
|
private RoleState state;
|
||||||
|
|
||||||
|
@Column(length = 64)
|
||||||
|
@Schema(description = "所属分组")
|
||||||
|
@DefaultValue(RoleGroupService.DEFAULT_GROUP_ID)
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
@Column(updatable = false)
|
@Column(updatable = false)
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "创建者ID(只读)"
|
description = "创建者ID(只读)"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package org.jetlinks.community.auth.entity;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
|
||||||
|
import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
|
||||||
|
import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
|
||||||
|
import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
|
||||||
|
import org.hswebframework.web.crud.annotation.EnableEntityEvent;
|
||||||
|
import org.hswebframework.web.crud.generator.Generators;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Table(name = "s_role_group")
|
||||||
|
@Comment("角色分组表")
|
||||||
|
@EnableEntityEvent
|
||||||
|
public class RoleGroupEntity extends GenericTreeSortSupportEntity<String> implements RecordCreationEntity {
|
||||||
|
|
||||||
|
@Column(length = 64)
|
||||||
|
@Length(min = 1, max = 64)
|
||||||
|
@Schema(description = "名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Length(max = 255)
|
||||||
|
@Schema(description = "说明")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(updatable = false)
|
||||||
|
@Schema(
|
||||||
|
description = "创建者ID(只读)"
|
||||||
|
, accessMode = Schema.AccessMode.READ_ONLY
|
||||||
|
)
|
||||||
|
private String creatorId;
|
||||||
|
|
||||||
|
@Column(updatable = false)
|
||||||
|
@DefaultValue(generator = Generators.CURRENT_TIME)
|
||||||
|
@Schema(description = "创建时间"
|
||||||
|
, accessMode = Schema.AccessMode.READ_ONLY
|
||||||
|
)
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
private List<RoleGroupEntity> children;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.jetlinks.community.auth.service;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
|
||||||
|
import org.hswebframework.web.crud.events.EntityDeletedEvent;
|
||||||
|
import org.hswebframework.web.crud.query.QueryHelper;
|
||||||
|
import org.hswebframework.web.crud.service.GenericReactiveTreeSupportCrudService;
|
||||||
|
import org.hswebframework.web.exception.I18nSupportException;
|
||||||
|
import org.hswebframework.web.id.IDGenerator;
|
||||||
|
|
||||||
|
import org.jetlinks.community.auth.entity.RoleGroupEntity;
|
||||||
|
import org.jetlinks.community.auth.entity.RoleEntity;
|
||||||
|
import org.jetlinks.community.auth.web.response.RoleGroupDetailTree;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RoleGroupService extends GenericReactiveTreeSupportCrudService<RoleGroupEntity, String> implements CommandLineRunner {
|
||||||
|
|
||||||
|
public static final String DEFAULT_GROUP_ID = "default_group";
|
||||||
|
|
||||||
|
private final RoleService roleService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分组下存在角色时不可删除
|
||||||
|
*/
|
||||||
|
@EventListener
|
||||||
|
public void handleEvent(EntityDeletedEvent<RoleGroupEntity> event) {
|
||||||
|
event.async(
|
||||||
|
Flux.fromIterable(event.getEntity())
|
||||||
|
.map(RoleGroupEntity::getId)
|
||||||
|
//默认分组不可删除
|
||||||
|
.filter(id -> !DEFAULT_GROUP_ID.equals(id))
|
||||||
|
.collectList()
|
||||||
|
.filter(CollectionUtils::isNotEmpty)
|
||||||
|
.flatMapMany(ids -> roleService
|
||||||
|
.createQuery()
|
||||||
|
.in(RoleEntity::getGroupId, ids)
|
||||||
|
.count()
|
||||||
|
.filter(i -> i <= 0)
|
||||||
|
.switchIfEmpty(Mono.error(() -> new I18nSupportException("error.group_role_exists"))))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Flux<RoleGroupDetailTree> queryDetailTree(QueryParamEntity groupParam, QueryParamEntity roleParam) {
|
||||||
|
groupParam.setPaging(false);
|
||||||
|
roleParam.setPaging(false);
|
||||||
|
Flux<RoleGroupDetailTree> groupDetails = this
|
||||||
|
.query(groupParam)
|
||||||
|
.map(RoleGroupDetailTree::of);
|
||||||
|
return QueryHelper
|
||||||
|
.combineOneToMany(
|
||||||
|
groupDetails,
|
||||||
|
RoleGroupDetailTree::getGroupId,
|
||||||
|
roleService.createQuery().setParam(roleParam),
|
||||||
|
RoleEntity::getGroupId,
|
||||||
|
RoleGroupDetailTree::setRoles
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDGenerator<String> getIDGenerator() {
|
||||||
|
return IDGenerator.SNOW_FLAKE_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChildren(RoleGroupEntity entity, List<RoleGroupEntity> children) {
|
||||||
|
entity.setChildren(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兼容旧数据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run(String... args) {
|
||||||
|
//兼容旧数据,空分组即为默认分组
|
||||||
|
roleService
|
||||||
|
.createUpdate()
|
||||||
|
.set(RoleEntity::getGroupId, DEFAULT_GROUP_ID)
|
||||||
|
.isNull(RoleEntity::getGroupId)
|
||||||
|
.execute()
|
||||||
|
.subscribe(ignore -> {
|
||||||
|
},
|
||||||
|
err -> log.error("init role groupId error", err));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.jetlinks.community.auth.web;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
|
||||||
|
import org.hswebframework.web.authorization.annotation.Resource;
|
||||||
|
import org.hswebframework.web.authorization.annotation.SaveAction;
|
||||||
|
import org.hswebframework.web.crud.service.ReactiveCrudService;
|
||||||
|
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
|
||||||
|
import org.jetlinks.community.auth.entity.RoleGroupEntity;
|
||||||
|
import org.jetlinks.community.auth.service.RoleGroupService;
|
||||||
|
import org.jetlinks.community.auth.web.response.RoleGroupDetailTree;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/role/group")
|
||||||
|
@Resource(id = "role-group", name = "角色组管理")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Tag(name = "角色组管理")
|
||||||
|
public class RoleGroupController implements ReactiveServiceCrudController<RoleGroupEntity, String> {
|
||||||
|
|
||||||
|
private final RoleGroupService roleGroupService;
|
||||||
|
|
||||||
|
@PostMapping("/detail/_query/tree")
|
||||||
|
@Operation(summary = "查询分组及角色(树状)")
|
||||||
|
@SaveAction
|
||||||
|
public Flux<RoleGroupDetailTree> queryDetailTree(@RequestParam(defaultValue = "false") @Parameter(description = "true:query为角色条件,false:query为分组条件") boolean queryByRole,
|
||||||
|
@RequestBody Mono<QueryParamEntity> query) {
|
||||||
|
|
||||||
|
return Mono
|
||||||
|
.zip(queryByRole ? query : Mono.just(new QueryParamEntity()),
|
||||||
|
queryByRole ? Mono.just(new QueryParamEntity()) : query)
|
||||||
|
.flatMapMany(tp2 -> roleGroupService.queryDetailTree(tp2.getT2(), tp2.getT1()));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReactiveCrudService<RoleGroupEntity, String> getService() {
|
||||||
|
return roleGroupService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.jetlinks.community.auth.web.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.jetlinks.community.auth.entity.RoleEntity;
|
||||||
|
import org.jetlinks.community.auth.entity.RoleGroupEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gyl
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor(staticName = "of")
|
||||||
|
public class RoleGroupDetailTree {
|
||||||
|
|
||||||
|
private String groupId;
|
||||||
|
private String groupName;
|
||||||
|
private List<RoleEntity> roles;
|
||||||
|
|
||||||
|
|
||||||
|
public static RoleGroupDetailTree of(RoleGroupEntity group) {
|
||||||
|
RoleGroupDetailTree roleGroupDetailTree = new RoleGroupDetailTree();
|
||||||
|
roleGroupDetailTree.setGroupId(group.getId());
|
||||||
|
roleGroupDetailTree.setGroupName(group.getName());
|
||||||
|
return roleGroupDetailTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue