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.crud.generator.Generators;
|
||||
import org.jetlinks.community.auth.enums.RoleState;
|
||||
import org.jetlinks.community.auth.service.RoleGroupService;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Table;
|
||||
|
|
@ -42,6 +43,11 @@ public class RoleEntity extends GenericEntity<String> implements RecordCreationE
|
|||
@DefaultValue("enabled")
|
||||
private RoleState state;
|
||||
|
||||
@Column(length = 64)
|
||||
@Schema(description = "所属分组")
|
||||
@DefaultValue(RoleGroupService.DEFAULT_GROUP_ID)
|
||||
private String groupId;
|
||||
|
||||
@Column(updatable = false)
|
||||
@Schema(
|
||||
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