mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
feat: add namespace to manage app
This commit is contained in:
parent
70e3afec1a
commit
0da830a6bc
@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -147,6 +148,13 @@ public class CommonUtils {
|
||||
return OmsConstant.NONE;
|
||||
}
|
||||
|
||||
public static String formatTime(Date date) {
|
||||
if (date == null) {
|
||||
return OmsConstant.NONE;
|
||||
}
|
||||
return formatTime(date.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化字符串,如果是 null 或空则显示 N/A
|
||||
* @param str 字符串
|
||||
|
@ -0,0 +1,22 @@
|
||||
package tech.powerjob.server.auth;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 权限范围
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RoleScope {
|
||||
|
||||
NAMESPACE(1),
|
||||
|
||||
APP(10)
|
||||
;
|
||||
|
||||
private final int v;
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package tech.powerjob.server.auth.anno;
|
||||
package tech.powerjob.server.auth.interceptor;
|
||||
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.interceptor.dp.DynamicPermission;
|
||||
import tech.powerjob.server.auth.interceptor.dp.EmptyDynamicPermission;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -26,5 +28,11 @@ public @interface ApiPermission {
|
||||
* 需要的权限
|
||||
* @return 权限
|
||||
*/
|
||||
Permission requiredPermission();
|
||||
Permission requiredPermission() default Permission.GLOBAL_SU;
|
||||
|
||||
/**
|
||||
* 固定权限不支持的场景,需要使用动态权限
|
||||
* @return 动态权限
|
||||
*/
|
||||
Class<? extends DynamicPermission> dynamicPermissionPlugin() default EmptyDynamicPermission.class;
|
||||
}
|
@ -9,7 +9,6 @@ import tech.powerjob.common.Loggers;
|
||||
import tech.powerjob.common.exception.PowerJobException;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.anno.ApiPermission;
|
||||
import tech.powerjob.server.auth.service.PowerJobAuthService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -59,7 +58,7 @@ public class PowerJobAuthInterceptor implements HandlerInterceptor {
|
||||
// 写入上下文
|
||||
LoginUserHolder.set(powerJobUser);
|
||||
|
||||
final boolean hasPermission = powerJobAuthService.hasPermission(request, powerJobUser, apiPermissionAnno);
|
||||
final boolean hasPermission = powerJobAuthService.hasPermission(request, handler, powerJobUser, apiPermissionAnno);
|
||||
if (hasPermission) {
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package tech.powerjob.server.auth.interceptor.dp;
|
||||
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 动态权限
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
public interface DynamicPermission {
|
||||
Permission calculate(HttpServletRequest request, Object handler);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package tech.powerjob.server.auth.interceptor.dp;
|
||||
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* NotUseDynamicPermission
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
public class EmptyDynamicPermission implements DynamicPermission {
|
||||
@Override
|
||||
public Permission calculate(HttpServletRequest request, Object handler) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package tech.powerjob.server.auth.interceptor.dp;
|
||||
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 创建不需要权限,修改需要校验权限
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
public class ModifyOrCreateDynamicPermission implements DynamicPermission {
|
||||
@Override
|
||||
public Permission calculate(HttpServletRequest request, Object handler) {
|
||||
// TODO: 动态权限判断,新建不需要权限
|
||||
return Permission.WRITE;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ package tech.powerjob.server.auth.service;
|
||||
|
||||
import tech.powerjob.server.auth.LoginContext;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.anno.ApiPermission;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
@ -43,9 +43,10 @@ public interface PowerJobAuthService {
|
||||
/**
|
||||
* 判断用户是否有访问权限
|
||||
* @param request 上下文请求
|
||||
* @param handler hander
|
||||
* @param user 用户
|
||||
* @param apiPermission 权限描述
|
||||
* @return true or false
|
||||
*/
|
||||
boolean hasPermission(HttpServletRequest request, PowerJobUser user, ApiPermission apiPermission);
|
||||
boolean hasPermission(HttpServletRequest request, Object handler, PowerJobUser user, ApiPermission apiPermission);
|
||||
}
|
||||
|
@ -4,21 +4,25 @@ import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.Loggers;
|
||||
import tech.powerjob.server.auth.LoginContext;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
import tech.powerjob.server.auth.anno.ApiPermission;
|
||||
import tech.powerjob.common.exception.ImpossibleException;
|
||||
import tech.powerjob.server.auth.*;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
import tech.powerjob.server.auth.interceptor.dp.DynamicPermission;
|
||||
import tech.powerjob.server.auth.interceptor.dp.EmptyDynamicPermission;
|
||||
import tech.powerjob.server.auth.jwt.JwtService;
|
||||
import tech.powerjob.server.auth.login.BizLoginService;
|
||||
import tech.powerjob.server.auth.login.BizUser;
|
||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.model.UserRoleDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserRoleRepository;
|
||||
|
||||
@ -32,10 +36,12 @@ import java.util.*;
|
||||
* @author tjq
|
||||
* @since 2023/3/21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PowerJobAuthServiceImpl implements PowerJobAuthService {
|
||||
|
||||
private final JwtService jwtService;
|
||||
private final AppInfoRepository appInfoRepository;
|
||||
private final UserInfoRepository userInfoRepository;
|
||||
private final UserRoleRepository userRoleRepository;
|
||||
private final Map<String, BizLoginService> type2LoginService = Maps.newHashMap();
|
||||
@ -45,8 +51,9 @@ public class PowerJobAuthServiceImpl implements PowerJobAuthService {
|
||||
private static final String KEY_USERNAME = "userName";
|
||||
|
||||
@Autowired
|
||||
public PowerJobAuthServiceImpl(List<BizLoginService> loginServices, JwtService jwtService, UserInfoRepository userInfoRepository, UserRoleRepository userRoleRepository) {
|
||||
public PowerJobAuthServiceImpl(List<BizLoginService> loginServices, JwtService jwtService, AppInfoRepository appInfoRepository, UserInfoRepository userInfoRepository, UserRoleRepository userRoleRepository) {
|
||||
this.jwtService = jwtService;
|
||||
this.appInfoRepository = appInfoRepository;
|
||||
this.userInfoRepository = userInfoRepository;
|
||||
this.userRoleRepository = userRoleRepository;
|
||||
loginServices.forEach(k -> type2LoginService.put(k.type(), k));
|
||||
@ -109,33 +116,52 @@ public class PowerJobAuthServiceImpl implements PowerJobAuthService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(HttpServletRequest request, PowerJobUser user, ApiPermission apiPermission) {
|
||||
public boolean hasPermission(HttpServletRequest request, Object handler, PowerJobUser user, ApiPermission apiPermission) {
|
||||
|
||||
final List<UserRoleDO> userRoleList = Optional.ofNullable(userRoleRepository.findAllByUserId(user.getId())).orElse(Collections.emptyList());
|
||||
|
||||
Multimap<String, Role> appId2Role = ArrayListMultimap.create();
|
||||
Multimap<Long, Role> appId2Role = ArrayListMultimap.create();
|
||||
Multimap<Long, Role> namespaceId2Role = ArrayListMultimap.create();
|
||||
|
||||
for (UserRoleDO userRole : userRoleList) {
|
||||
if (userRole.getRole().equalsIgnoreCase(String.valueOf(Role.GOD.getV()))) {
|
||||
if (Objects.equals(Role.GOD.getV(), userRole.getRole())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 除了上帝角色,其他任何角色都是 roleId_appId 的形式
|
||||
final String[] split = userRole.getRole().split("_");
|
||||
final Role role = Role.of(Integer.parseInt(split[0]));
|
||||
appId2Role.put(split[1], role);
|
||||
final Role role = Role.of(userRole.getRole());
|
||||
if (Objects.equals(userRole.getScope(), RoleScope.NAMESPACE.getV())) {
|
||||
namespaceId2Role.put(userRole.getTarget(), role);
|
||||
}
|
||||
if (Objects.equals(userRole.getScope(), RoleScope.APP.getV())) {
|
||||
appId2Role.put(userRole.getTarget(), role);
|
||||
}
|
||||
}
|
||||
|
||||
// 无超级管理员权限,校验普通权限
|
||||
final String appId = request.getHeader("appId");
|
||||
if (StringUtils.isEmpty(appId)) {
|
||||
throw new IllegalArgumentException("can't find appId in header, please login again!");
|
||||
final String appIdStr = request.getHeader("appId");
|
||||
if (StringUtils.isEmpty(appIdStr)) {
|
||||
throw new IllegalArgumentException("can't find appId in header, please refresh and try again!");
|
||||
}
|
||||
|
||||
final Permission requiredPermission = apiPermission.requiredPermission();
|
||||
Long appId = Long.valueOf(appIdStr);
|
||||
|
||||
final Collection<Role> roleCollection = appId2Role.get(appId);
|
||||
for (Role role : roleCollection) {
|
||||
final Permission requiredPermission = parsePermission(request, handler, apiPermission);
|
||||
|
||||
final Collection<Role> appRoles = appId2Role.get(appId);
|
||||
for (Role role : appRoles) {
|
||||
if (role.getPermissions().contains(requiredPermission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 校验 namespace 穿透权限
|
||||
Optional<AppInfoDO> appInfoOpt = appInfoRepository.findById(appId);
|
||||
if (!appInfoOpt.isPresent()) {
|
||||
throw new IllegalArgumentException("can't find appInfo by appId in permission check: " + appId);
|
||||
}
|
||||
Long namespaceId = Optional.ofNullable(appInfoOpt.get().getNamespaceId()).orElse(-1L);
|
||||
Collection<Role> namespaceRoles = namespaceId2Role.get(namespaceId);
|
||||
for (Role role : namespaceRoles) {
|
||||
if (role.getPermissions().contains(requiredPermission)) {
|
||||
return true;
|
||||
}
|
||||
@ -184,4 +210,19 @@ public class PowerJobAuthServiceImpl implements PowerJobAuthService {
|
||||
|
||||
powerJobUser.setJwtToken(jwtService.build(jwtMap, null));
|
||||
}
|
||||
|
||||
private static Permission parsePermission(HttpServletRequest request, Object handler, ApiPermission apiPermission) {
|
||||
Class<? extends DynamicPermission> dynamicPermissionPlugin = apiPermission.dynamicPermissionPlugin();
|
||||
if (EmptyDynamicPermission.class.equals(dynamicPermissionPlugin)) {
|
||||
return apiPermission.requiredPermission();
|
||||
}
|
||||
try {
|
||||
DynamicPermission dynamicPermission = dynamicPermissionPlugin.getDeclaredConstructor().newInstance();
|
||||
return dynamicPermission.calculate(request, handler);
|
||||
} catch (Throwable t) {
|
||||
log.error("[PowerJobAuthService] process dynamicPermissionPlugin failed!", t);
|
||||
ExceptionUtils.rethrow(t);
|
||||
}
|
||||
throw new ImpossibleException();
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
public enum SwitchableStatus {
|
||||
/**
|
||||
*
|
||||
* 启用
|
||||
*/
|
||||
ENABLE(1),
|
||||
DISABLE(2),
|
||||
|
@ -22,6 +22,11 @@ public class AppInfoDO {
|
||||
@GenericGenerator(name = "native", strategy = "native")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 命名空间ID,外键关联
|
||||
*/
|
||||
private Long namespaceId;
|
||||
|
||||
private String appName;
|
||||
/**
|
||||
* 应用分组密码
|
||||
|
@ -0,0 +1,54 @@
|
||||
package tech.powerjob.server.persistence.remote.model;
|
||||
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 命名空间,用于组织管理 App
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(uniqueConstraints = {@UniqueConstraint(name = "uidx01_namespace", columnNames = {"code"})})
|
||||
public class NamespaceDO {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
|
||||
@GenericGenerator(name = "native", strategy = "native")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 空间唯一标识
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 空间名称,比如中文描述(XX部门XX空间)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 鉴权 token,后续 OpenAPI 调用需要
|
||||
*/
|
||||
private String token;
|
||||
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
private Date gmtCreate;
|
||||
|
||||
private Date gmtModified;
|
||||
|
||||
private String creator;
|
||||
|
||||
private String modifier;
|
||||
}
|
@ -28,10 +28,20 @@ public class UserRoleDO {
|
||||
* 授予角色的用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色,${role}_${appId},比如 Observer_277
|
||||
* 权限范围,namespace 还是 app
|
||||
*/
|
||||
private String role;
|
||||
private Integer scope;
|
||||
/**
|
||||
* 和 scope 一起组成授权目标,比如某个 app 或 某个 namespace
|
||||
*/
|
||||
private Long target;
|
||||
|
||||
/**
|
||||
* 角色,比如 Observer
|
||||
*/
|
||||
private Integer role;
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
|
@ -0,0 +1,13 @@
|
||||
package tech.powerjob.server.persistence.remote.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
||||
|
||||
/**
|
||||
* 命名空间
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
public interface NamespaceRepository extends JpaRepository<NamespaceDO, Long> {
|
||||
}
|
@ -14,4 +14,6 @@ import java.util.List;
|
||||
public interface UserRoleRepository extends JpaRepository<UserRoleDO, Long> {
|
||||
|
||||
List<UserRoleDO> findAllByUserId(Long userId);
|
||||
|
||||
List<UserRoleDO> findAllByScopeAndTarget(Integer scope, Long target);
|
||||
}
|
||||
|
@ -0,0 +1,126 @@
|
||||
package tech.powerjob.server.web.controller;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
import tech.powerjob.server.auth.interceptor.dp.ModifyOrCreateDynamicPermission;
|
||||
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.model.UserRoleDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.NamespaceRepository;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserRoleRepository;
|
||||
import tech.powerjob.server.web.converter.NamespaceConverter;
|
||||
import tech.powerjob.server.web.converter.UserConverter;
|
||||
import tech.powerjob.server.web.request.ModifyNamespaceRequest;
|
||||
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||
import tech.powerjob.server.web.response.NamespaceDetailVO;
|
||||
import tech.powerjob.server.web.response.UserBaseVO;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 命名空间 Controller
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/namespace")
|
||||
public class NamespaceController {
|
||||
|
||||
@Resource
|
||||
private NamespaceRepository namespaceRepository;
|
||||
@Resource
|
||||
private UserInfoRepository userInfoRepository;
|
||||
@Resource
|
||||
private UserRoleRepository userRoleRepository;
|
||||
|
||||
@PostMapping("/save")
|
||||
@ApiPermission(name = "Namespace-Save", dynamicPermissionPlugin = ModifyOrCreateDynamicPermission.class)
|
||||
public ResultDTO<Void> save(ModifyNamespaceRequest req) {
|
||||
|
||||
req.valid();
|
||||
|
||||
Long id = req.getId();
|
||||
NamespaceDO namespaceDO;
|
||||
if (id == null) {
|
||||
namespaceDO = new NamespaceDO();
|
||||
namespaceDO.setGmtCreate(new Date());
|
||||
|
||||
// code 单独拷贝
|
||||
namespaceDO.setCode(req.getCode());
|
||||
// 创建时生成 token
|
||||
namespaceDO.setToken(UUID.randomUUID().toString());
|
||||
|
||||
} else {
|
||||
namespaceDO = fetchById(id);
|
||||
}
|
||||
|
||||
// 拷贝通用变更属性(code 不允许更改)
|
||||
namespaceDO.setName(req.getName());
|
||||
namespaceDO.setExtra(req.getExtra());
|
||||
namespaceDO.setStatus(req.getStatus());
|
||||
|
||||
namespaceDO.setGmtModified(new Date());
|
||||
namespaceRepository.save(namespaceDO);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
@GetMapping("/listAll")
|
||||
public ResultDTO<List<NamespaceBaseVO>> listAllNamespace() {
|
||||
List<NamespaceDO> allDos = namespaceRepository.findAll();
|
||||
return ResultDTO.success(allDos.stream().map(NamespaceConverter::do2BaseVo).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
@ApiPermission(name = "Namespace-DetailInfo", requiredPermission = Permission.READ)
|
||||
public ResultDTO<NamespaceDetailVO> queryNamespaceDetail(Long id) {
|
||||
|
||||
NamespaceDO namespaceDO = fetchById(id);
|
||||
NamespaceDetailVO namespaceDetailVO = new NamespaceDetailVO();
|
||||
|
||||
// 拷贝基础字段
|
||||
NamespaceBaseVO namespaceBaseVO = NamespaceConverter.do2BaseVo(namespaceDO);
|
||||
BeanUtils.copyProperties(namespaceBaseVO, namespaceDetailVO);
|
||||
|
||||
// 处理 token
|
||||
namespaceDetailVO.setToken(namespaceDO.getToken());
|
||||
|
||||
// 处理权限视图
|
||||
Map<String, List<UserBaseVO>> privilegedUsers = Maps.newHashMap();
|
||||
namespaceDetailVO.setPrivilegedUsers(privilegedUsers);
|
||||
List<UserRoleDO> permissionUserList = userRoleRepository.findAllByScopeAndTarget(RoleScope.NAMESPACE.getV(), namespaceDO.getId());
|
||||
permissionUserList.forEach(r -> {
|
||||
Role role = Role.of(r.getRole());
|
||||
List<UserBaseVO> userBaseVOList = privilegedUsers.computeIfAbsent(role.name(), ignore -> Lists.newArrayList());
|
||||
|
||||
Optional<UserInfoDO> userInfoDoOpt = userInfoRepository.findById(r.getUserId());
|
||||
userInfoDoOpt.ifPresent(userInfoDO -> userBaseVOList.add(UserConverter.do2BaseVo(userInfoDO)));
|
||||
});
|
||||
|
||||
return ResultDTO.success(namespaceDetailVO);
|
||||
}
|
||||
|
||||
private NamespaceDO fetchById(Long id) {
|
||||
Optional<NamespaceDO> namespaceDoOpt = namespaceRepository.findById(id);
|
||||
if (!namespaceDoOpt.isPresent()) {
|
||||
throw new IllegalArgumentException("can't find namespace by id: " + id);
|
||||
}
|
||||
return namespaceDoOpt.get();
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
package tech.powerjob.server.web.controller;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@ -12,7 +9,9 @@ import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.server.core.service.UserService;
|
||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||
import tech.powerjob.server.web.converter.UserConverter;
|
||||
import tech.powerjob.server.web.request.ModifyUserInfoRequest;
|
||||
import tech.powerjob.server.web.response.UserBaseVO;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
@ -41,7 +40,7 @@ public class UserInfoController {
|
||||
}
|
||||
|
||||
@GetMapping("list")
|
||||
public ResultDTO<List<UserItemVO>> list(@RequestParam(required = false) String name) {
|
||||
public ResultDTO<List<UserBaseVO>> list(@RequestParam(required = false) String name) {
|
||||
|
||||
List<UserInfoDO> result;
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
@ -52,18 +51,10 @@ public class UserInfoController {
|
||||
return ResultDTO.success(convert(result));
|
||||
}
|
||||
|
||||
private static List<UserItemVO> convert(List<UserInfoDO> data) {
|
||||
private static List<UserBaseVO> convert(List<UserInfoDO> data) {
|
||||
if (CollectionUtils.isEmpty(data)) {
|
||||
return Lists.newLinkedList();
|
||||
}
|
||||
return data.stream().map(x -> new UserItemVO(x.getId(), x.getUsername())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static final class UserItemVO {
|
||||
private Long id;
|
||||
private String username;
|
||||
return data.stream().map(UserConverter::do2BaseVo).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
package tech.powerjob.server.web.converter;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import tech.powerjob.common.utils.CommonUtils;
|
||||
import tech.powerjob.server.common.constants.SwitchableStatus;
|
||||
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
||||
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||
|
||||
/**
|
||||
* NamespaceConverter
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/4
|
||||
*/
|
||||
public class NamespaceConverter {
|
||||
|
||||
public static NamespaceBaseVO do2BaseVo(NamespaceDO d) {
|
||||
NamespaceBaseVO v = new NamespaceBaseVO();
|
||||
BeanUtils.copyProperties(d, v);
|
||||
v.setGmtCreateStr(CommonUtils.formatTime(d.getGmtCreate()));
|
||||
v.setGmtModifiedStr(CommonUtils.formatTime(d.getGmtModified()));
|
||||
v.setStatusStr(SwitchableStatus.of(d.getStatus()).name());
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package tech.powerjob.server.web.converter;
|
||||
|
||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||
import tech.powerjob.server.web.response.UserBaseVO;
|
||||
|
||||
/**
|
||||
* UserConverter
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/4
|
||||
*/
|
||||
public class UserConverter {
|
||||
|
||||
public static UserBaseVO do2BaseVo(UserInfoDO x) {
|
||||
UserBaseVO userBaseVO = new UserBaseVO();
|
||||
userBaseVO.setId(x.getId());
|
||||
userBaseVO.setUsername(x.getUsername());
|
||||
userBaseVO.setNick(x.getNick());
|
||||
return userBaseVO;
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
public class ModifyAppInfoRequest {
|
||||
|
||||
private Long id;
|
||||
private Long namespaceId;
|
||||
private String oldPassword;
|
||||
private String appName;
|
||||
private String password;
|
||||
|
@ -0,0 +1,42 @@
|
||||
package tech.powerjob.server.web.request;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import tech.powerjob.common.exception.PowerJobException;
|
||||
import tech.powerjob.common.utils.CommonUtils;
|
||||
|
||||
/**
|
||||
* ModifyNamespaceRequest
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Data
|
||||
public class ModifyNamespaceRequest {
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 空间唯一标识
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 空间名称,比如中文描述(XX部门XX空间)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
public void valid() {
|
||||
CommonUtils.requireNonNull(code, "namespace code can't be empty");
|
||||
if (StringUtils.containsWhitespace(code)) {
|
||||
throw new PowerJobException("namespace code can't contains white space!");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package tech.powerjob.server.web.response;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 基础版本的命名空间
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class NamespaceBaseVO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 空间唯一标识
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 空间名称,比如中文描述(XX部门XX空间)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private Integer status;
|
||||
private String statusStr;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
private Date gmtCreate;
|
||||
|
||||
private String gmtCreateStr;
|
||||
|
||||
private Date gmtModified;
|
||||
|
||||
private String gmtModifiedStr;
|
||||
|
||||
private String creator;
|
||||
|
||||
private String modifier;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package tech.powerjob.server.web.response;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 详细命名空间信息,需要权限访问
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString(callSuper = true)
|
||||
public class NamespaceDetailVO extends NamespaceBaseVO {
|
||||
|
||||
/**
|
||||
* 访问 token
|
||||
*/
|
||||
private String token;
|
||||
/**
|
||||
* 有权限的用户
|
||||
*/
|
||||
private Map<String, List<UserBaseVO>> privilegedUsers;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package tech.powerjob.server.web.response;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 用户基础信息
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/9/3
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class UserBaseVO {
|
||||
private Long id;
|
||||
private String username;
|
||||
private String nick;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user