mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
feat: support namespace
This commit is contained in:
parent
841c7891c8
commit
919a5c3b35
@ -0,0 +1,27 @@
|
||||
package tech.powerjob.server.auth.common.utils;
|
||||
|
||||
import tech.powerjob.common.OmsConstant;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* HttpServletUtils
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/2/12
|
||||
*/
|
||||
public class HttpServletUtils {
|
||||
|
||||
public static String fetchFromHeader(String key, HttpServletRequest httpServletRequest) {
|
||||
// header、cookie 都能获取
|
||||
String v = httpServletRequest.getHeader(key);
|
||||
|
||||
// 解决 window.localStorage.getItem 为 null 的问题
|
||||
if (OmsConstant.NULL.equalsIgnoreCase(v)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +1,21 @@
|
||||
package tech.powerjob.server.auth.interceptor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import tech.powerjob.common.exception.ImpossibleException;
|
||||
import tech.powerjob.common.exception.PowerJobException;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||
import tech.powerjob.server.auth.common.utils.HttpServletUtils;
|
||||
import tech.powerjob.server.auth.service.login.PowerJobLoginService;
|
||||
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
|
||||
import tech.powerjob.server.common.Loggers;
|
||||
@ -24,6 +32,7 @@ import java.util.Optional;
|
||||
* @author tjq
|
||||
* @since 2023/3/25
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PowerJobAuthInterceptor implements HandlerInterceptor {
|
||||
@Resource
|
||||
@ -48,11 +57,9 @@ public class PowerJobAuthInterceptor implements HandlerInterceptor {
|
||||
// 尝试直接解析登陆
|
||||
final Optional<PowerJobUser> loginUserOpt = powerJobLoginService.ifLogin(request);
|
||||
|
||||
// 未登录前先使用302重定向到登录页面 TODO: 前端登录还是服务端直接跳转有待考虑
|
||||
// 未登录直接报错,返回固定状态码,前端拦截后跳转到登录页
|
||||
if (!loginUserOpt.isPresent()) {
|
||||
response.setStatus(302);
|
||||
response.setHeader("location", request.getContextPath() + "/login");
|
||||
return false;
|
||||
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN);
|
||||
}
|
||||
|
||||
// 登陆用户进行权限校验
|
||||
@ -61,7 +68,27 @@ public class PowerJobAuthInterceptor implements HandlerInterceptor {
|
||||
// 写入上下文
|
||||
LoginUserHolder.set(powerJobUser);
|
||||
|
||||
final boolean hasPermission = powerJobPermissionService.hasPermission(request, handler, powerJobUser, apiPermissionAnno);
|
||||
Permission requiredPermission = parsePermission(request, handler, apiPermissionAnno);
|
||||
RoleScope roleScope = apiPermissionAnno.roleScope();
|
||||
Long targetId = null;
|
||||
|
||||
if (RoleScope.NAMESPACE.equals(roleScope)) {
|
||||
|
||||
final String namespaceIdStr = HttpServletUtils.fetchFromHeader("NamespaceId", request);
|
||||
if (StringUtils.isNotEmpty(namespaceIdStr)) {
|
||||
targetId = Long.valueOf(namespaceIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (RoleScope.APP.equals(roleScope)) {
|
||||
final String appIdStr = HttpServletUtils.fetchFromHeader("AppId", request);
|
||||
if (StringUtils.isNotEmpty(appIdStr)) {
|
||||
targetId = Long.valueOf(appIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final boolean hasPermission = powerJobPermissionService.hasPermission(powerJobUser.getId(), roleScope, targetId, requiredPermission);
|
||||
if (hasPermission) {
|
||||
return true;
|
||||
}
|
||||
@ -90,4 +117,19 @@ public class PowerJobAuthInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
private static Permission parsePermission(HttpServletRequest request, Object handler, ApiPermission apiPermission) {
|
||||
Class<? extends DynamicPermissionPlugin> dynamicPermissionPlugin = apiPermission.dynamicPermissionPlugin();
|
||||
if (EmptyPlugin.class.equals(dynamicPermissionPlugin)) {
|
||||
return apiPermission.requiredPermission();
|
||||
}
|
||||
try {
|
||||
DynamicPermissionPlugin 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();
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,11 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.OmsConstant;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.common.AuthConstants;
|
||||
import tech.powerjob.server.auth.common.AuthErrorCode;
|
||||
import tech.powerjob.server.auth.common.PowerJobAuthException;
|
||||
import tech.powerjob.server.auth.common.utils.HttpServletUtils;
|
||||
import tech.powerjob.server.auth.jwt.JwtService;
|
||||
import tech.powerjob.server.auth.login.LoginTypeInfo;
|
||||
import tech.powerjob.server.auth.login.ThirdPartyLoginRequest;
|
||||
@ -140,12 +140,7 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
||||
|
||||
private Optional<String> parseUserName(HttpServletRequest httpServletRequest) {
|
||||
// header、cookie 都能获取
|
||||
String jwtStr = httpServletRequest.getHeader(AuthConstants.JWT_NAME);
|
||||
|
||||
// 解决 window.localStorage.getItem 为 null 的问题
|
||||
if (OmsConstant.NULL.equalsIgnoreCase(jwtStr)) {
|
||||
jwtStr = null;
|
||||
}
|
||||
String jwtStr = HttpServletUtils.fetchFromHeader(AuthConstants.JWT_NAME, httpServletRequest);
|
||||
|
||||
if (StringUtils.isEmpty(jwtStr)) {
|
||||
for (Cookie cookie : Optional.ofNullable(httpServletRequest.getCookies()).orElse(new Cookie[]{})) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
package tech.powerjob.server.auth.service.permission;
|
||||
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
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 javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* PowerJob 鉴权服务
|
||||
@ -15,15 +15,16 @@ import javax.servlet.http.HttpServletRequest;
|
||||
*/
|
||||
public interface PowerJobPermissionService {
|
||||
|
||||
|
||||
/**
|
||||
* 判断用户是否有访问权限
|
||||
* @param request 上下文请求
|
||||
* @param handler hander
|
||||
* @param user 用户
|
||||
* @param apiPermission 权限描述
|
||||
* @return true or false
|
||||
* @param userId userId
|
||||
* @param roleScope 权限范围
|
||||
* @param target 权限目标ID
|
||||
* @param permission 要求的权限
|
||||
* @return 是否有权限
|
||||
*/
|
||||
boolean hasPermission(HttpServletRequest request, Object handler, PowerJobUser user, ApiPermission apiPermission);
|
||||
boolean hasPermission(Long userId, RoleScope roleScope, Long target, Permission permission);
|
||||
|
||||
/**
|
||||
* 授予用户权限
|
||||
@ -34,4 +35,21 @@ public interface PowerJobPermissionService {
|
||||
* @param extra 其他
|
||||
*/
|
||||
void grantPermission(RoleScope roleScope, Long target, Long userId, Role role, String extra);
|
||||
|
||||
/**
|
||||
* 回收用户权限
|
||||
* @param roleScope 权限范围
|
||||
* @param target 权限目标
|
||||
* @param userId 用户ID
|
||||
* @param role 角色
|
||||
*/
|
||||
void retrievePermission(RoleScope roleScope, Long target, Long userId, Role role);
|
||||
|
||||
/**
|
||||
* 获取有相关权限的用户
|
||||
* @param roleScope 权限范围
|
||||
* @param target 目标
|
||||
* @return 角色对应的用户列表
|
||||
*/
|
||||
Map<Role, List<Long>> fetchUserWithPermissions(RoleScope roleScope, Long target);
|
||||
}
|
||||
|
@ -1,27 +1,20 @@
|
||||
package tech.powerjob.server.auth.service.permission;
|
||||
|
||||
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.compress.utils.Lists;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.exception.ImpossibleException;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
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.DynamicPermissionPlugin;
|
||||
import tech.powerjob.server.auth.interceptor.EmptyPlugin;
|
||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.model.UserRoleDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserRoleRepository;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -40,8 +33,8 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
private UserRoleRepository userRoleRepository;
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(HttpServletRequest request, Object handler, PowerJobUser user, ApiPermission apiPermission) {
|
||||
final List<UserRoleDO> userRoleList = Optional.ofNullable(userRoleRepository.findAllByUserId(user.getId())).orElse(Collections.emptyList());
|
||||
public boolean hasPermission(Long userId, RoleScope roleScope, Long target, Permission requiredPermission) {
|
||||
final List<UserRoleDO> userRoleList = Optional.ofNullable(userRoleRepository.findAllByUserId(userId)).orElse(Collections.emptyList());
|
||||
|
||||
Multimap<Long, Role> appId2Role = ArrayListMultimap.create();
|
||||
Multimap<Long, Role> namespaceId2Role = ArrayListMultimap.create();
|
||||
@ -50,7 +43,6 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
|
||||
for (UserRoleDO userRole : userRoleList) {
|
||||
final Role role = Role.of(userRole.getRole());
|
||||
RoleScope roleScope = RoleScope.of(userRole.getScope());
|
||||
|
||||
// 处理全局权限
|
||||
if (RoleScope.GLOBAL.equals(roleScope)) {
|
||||
@ -69,7 +61,6 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
}
|
||||
|
||||
// 前置判断需要的权限(新增场景还没有 appId or namespaceId)
|
||||
final Permission requiredPermission = parsePermission(request, handler, apiPermission);
|
||||
if (requiredPermission == Permission.NONE) {
|
||||
return true;
|
||||
}
|
||||
@ -82,12 +73,12 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
}
|
||||
|
||||
// 无超级管理员权限,校验普通权限
|
||||
if (RoleScope.APP.equals(apiPermission.roleScope())) {
|
||||
return checkAppPermission(request, requiredPermission, appId2Role, namespaceId2Role);
|
||||
if (RoleScope.APP.equals(roleScope)) {
|
||||
return checkAppPermission(target, requiredPermission, appId2Role, namespaceId2Role);
|
||||
}
|
||||
|
||||
if (RoleScope.NAMESPACE.equals(apiPermission.roleScope())) {
|
||||
return checkNamespacePermission(request, requiredPermission, namespaceId2Role);
|
||||
if (RoleScope.NAMESPACE.equals(roleScope)) {
|
||||
return checkNamespacePermission(target, requiredPermission, namespaceId2Role);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -110,15 +101,31 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
log.info("[PowerJobPermissionService] saveAndFlush userRole successfully: {}", userRoleDO);
|
||||
}
|
||||
|
||||
private boolean checkAppPermission(HttpServletRequest request, Permission requiredPermission, Multimap<Long, Role> appId2Role, Multimap<Long, Role> namespaceId2Role) {
|
||||
final String appIdStr = request.getHeader("appId");
|
||||
if (StringUtils.isEmpty(appIdStr)) {
|
||||
throw new IllegalArgumentException("can't find appId in header, please refresh and try again!");
|
||||
}
|
||||
@Override
|
||||
public void retrievePermission(RoleScope roleScope, Long target, Long userId, Role role) {
|
||||
List<UserRoleDO> originUserRole = userRoleRepository.findAllByScopeAndTargetAndRoleAndUserId(roleScope.getV(), target, role.getV(), userId);
|
||||
log.info("[PowerJobPermissionService] [retrievePermission] origin rule: {}", originUserRole);
|
||||
Optional.ofNullable(originUserRole).orElse(Collections.emptyList()).forEach(r -> {
|
||||
userRoleRepository.deleteById(r.getId());
|
||||
log.info("[PowerJobPermissionService] [retrievePermission] delete UserRole: {}", r);
|
||||
});
|
||||
}
|
||||
|
||||
Long appId = Long.valueOf(appIdStr);
|
||||
@Override
|
||||
public Map<Role, List<Long>> fetchUserWithPermissions(RoleScope roleScope, Long target) {
|
||||
List<UserRoleDO> permissionUserList = userRoleRepository.findAllByScopeAndTarget(roleScope.getV(), target);
|
||||
Map<Role, List<Long>> ret = Maps.newHashMap();
|
||||
Optional.ofNullable(permissionUserList).orElse(Collections.emptyList()).forEach(userRoleDO -> {
|
||||
Role role = Role.of(userRoleDO.getRole());
|
||||
List<Long> userIds = ret.computeIfAbsent(role, ignore -> Lists.newArrayList());
|
||||
userIds.add(userRoleDO.getUserId());
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
final Collection<Role> appRoles = appId2Role.get(appId);
|
||||
private boolean checkAppPermission(Long targetId, Permission requiredPermission, Multimap<Long, Role> appId2Role, Multimap<Long, Role> namespaceId2Role) {
|
||||
|
||||
final Collection<Role> appRoles = appId2Role.get(targetId);
|
||||
for (Role role : appRoles) {
|
||||
if (role.getPermissions().contains(requiredPermission)) {
|
||||
return true;
|
||||
@ -126,9 +133,9 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
}
|
||||
|
||||
// 校验 namespace 穿透权限
|
||||
Optional<AppInfoDO> appInfoOpt = appInfoRepository.findById(appId);
|
||||
Optional<AppInfoDO> appInfoOpt = appInfoRepository.findById(targetId);
|
||||
if (!appInfoOpt.isPresent()) {
|
||||
throw new IllegalArgumentException("can't find appInfo by appId in permission check: " + appId);
|
||||
throw new IllegalArgumentException("can't find appInfo by appId in permission check: " + targetId);
|
||||
}
|
||||
Long namespaceId = Optional.ofNullable(appInfoOpt.get().getNamespaceId()).orElse(-1L);
|
||||
Collection<Role> namespaceRoles = namespaceId2Role.get(namespaceId);
|
||||
@ -141,14 +148,8 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkNamespacePermission(HttpServletRequest request, Permission requiredPermission, Multimap<Long, Role> namespaceId2Role) {
|
||||
final String namespaceIdStr = request.getHeader("namespaceId");
|
||||
if (StringUtils.isEmpty(namespaceIdStr)) {
|
||||
throw new IllegalArgumentException("can't find namespace in header, please refresh and try again!");
|
||||
}
|
||||
Long namespaceId = Long.valueOf(namespaceIdStr);
|
||||
|
||||
Collection<Role> namespaceRoles = namespaceId2Role.get(namespaceId);
|
||||
private boolean checkNamespacePermission(Long targetId, Permission requiredPermission, Multimap<Long, Role> namespaceId2Role) {
|
||||
Collection<Role> namespaceRoles = namespaceId2Role.get(targetId);
|
||||
for (Role role : namespaceRoles) {
|
||||
if (role.getPermissions().contains(requiredPermission)) {
|
||||
return true;
|
||||
@ -158,20 +159,4 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Permission parsePermission(HttpServletRequest request, Object handler, ApiPermission apiPermission) {
|
||||
Class<? extends DynamicPermissionPlugin> dynamicPermissionPlugin = apiPermission.dynamicPermissionPlugin();
|
||||
if (EmptyPlugin.class.equals(dynamicPermissionPlugin)) {
|
||||
return apiPermission.requiredPermission();
|
||||
}
|
||||
try {
|
||||
DynamicPermissionPlugin 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();
|
||||
}
|
||||
}
|
||||
|
@ -16,4 +16,6 @@ public interface UserRoleRepository extends JpaRepository<UserRoleDO, Long> {
|
||||
List<UserRoleDO> findAllByUserId(Long userId);
|
||||
|
||||
List<UserRoleDO> findAllByScopeAndTarget(Integer scope, Long target);
|
||||
|
||||
List<UserRoleDO> findAllByScopeAndTargetAndRoleAndUserId(Integer scope, Long target, Integer role, Long userId);
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
package tech.powerjob.server.auth.dp;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import tech.powerjob.common.serialize.JsonUtils;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
import tech.powerjob.server.auth.interceptor.DynamicPermissionPlugin;
|
||||
import tech.powerjob.server.web.request.GrantPermissionRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 授权动态权限计算
|
||||
* 授予权限要低于或等于授权人自身的权限
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/2/12
|
||||
*/
|
||||
@Slf4j
|
||||
public class GrantDynamicPermission implements DynamicPermissionPlugin {
|
||||
@Override
|
||||
public Permission calculate(HttpServletRequest request, Object handler) {
|
||||
try {
|
||||
//获取请求body
|
||||
byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
|
||||
String body = new String(bodyBytes, request.getCharacterEncoding());
|
||||
GrantPermissionRequest grantPermissionRequest = JsonUtils.parseObject(body, GrantPermissionRequest.class);
|
||||
Role role = Role.of(grantPermissionRequest.getRole());
|
||||
|
||||
switch (role) {
|
||||
case OBSERVER: return Permission.READ;
|
||||
case QA: return Permission.OPS;
|
||||
case DEVELOPER: return Permission.WRITE;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[GrantDynamicPermission] check permission failed, please fix the bug!!!", e);
|
||||
}
|
||||
|
||||
return Permission.SU;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package tech.powerjob.server.auth.dp;
|
||||
package tech.powerjob.server.auth.plugin;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StreamUtils;
|
@ -1,4 +1,4 @@
|
||||
package tech.powerjob.server.auth.gp;
|
||||
package tech.powerjob.server.auth.plugin;
|
||||
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package tech.powerjob.server.auth.gp;
|
||||
package tech.powerjob.server.auth.plugin;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.MapUtils;
|
@ -1,4 +1,4 @@
|
||||
package tech.powerjob.server.auth.gp;
|
||||
package tech.powerjob.server.auth.plugin;
|
||||
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
|
@ -0,0 +1,41 @@
|
||||
package tech.powerjob.server.auth.service;
|
||||
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
|
||||
/**
|
||||
* Web Auth 服务
|
||||
* 写在 starter 包下,抽取 controller 的公共逻辑
|
||||
* (powerjob 的 service/core 包核心处理调度核心逻辑,admin 部分代码收口在 stater 包)
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/2/12
|
||||
*/
|
||||
public interface WebAuthService {
|
||||
|
||||
/**
|
||||
* 处理授权
|
||||
* @param roleScope 权限范围
|
||||
* @param target 权限目标
|
||||
* @param componentUserRoleInfo 人员角色信息
|
||||
*/
|
||||
void processPermissionOnSave(RoleScope roleScope, Long target, ComponentUserRoleInfo componentUserRoleInfo);
|
||||
|
||||
/**
|
||||
* 获取目标相关权限人员列表
|
||||
* @param roleScope 权限范围
|
||||
* @param target 权限目标
|
||||
* @return ComponentUserRoleInfo
|
||||
*/
|
||||
ComponentUserRoleInfo fetchComponentUserRoleInfo(RoleScope roleScope, Long target);
|
||||
|
||||
/**
|
||||
* 判断当前用户是否有权限
|
||||
* @param roleScope 权限范围
|
||||
* @param target 权限目标
|
||||
* @param permission 要求的权限
|
||||
* @return 是否有权限
|
||||
*/
|
||||
boolean hasPermission(RoleScope roleScope, Long target, Permission permission);
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package tech.powerjob.server.auth.service.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.serialize.JsonUtils;
|
||||
import tech.powerjob.server.auth.*;
|
||||
import tech.powerjob.server.auth.service.WebAuthService;
|
||||
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* WebAuthService
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/2/12
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WebAuthServiceImpl implements WebAuthService {
|
||||
|
||||
@Resource
|
||||
private PowerJobPermissionService powerJobPermissionService;
|
||||
|
||||
|
||||
@Override
|
||||
public void processPermissionOnSave(RoleScope roleScope, Long target, ComponentUserRoleInfo o) {
|
||||
ComponentUserRoleInfo componentUserRoleInfo = Optional.ofNullable(o).orElse(new ComponentUserRoleInfo());
|
||||
|
||||
Map<Role, List<Long>> role2Uids = powerJobPermissionService.fetchUserWithPermissions(roleScope, target);
|
||||
diffGrant(roleScope, target, Role.OBSERVER, componentUserRoleInfo.getObserver(), role2Uids);
|
||||
diffGrant(roleScope, target, Role.QA, componentUserRoleInfo.getQa(), role2Uids);
|
||||
diffGrant(roleScope, target, Role.DEVELOPER, componentUserRoleInfo.getDeveloper(), role2Uids);
|
||||
diffGrant(roleScope, target, Role.ADMIN, componentUserRoleInfo.getAdmin(), role2Uids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentUserRoleInfo fetchComponentUserRoleInfo(RoleScope roleScope, Long target) {
|
||||
Map<Role, List<Long>> role2Uids = powerJobPermissionService.fetchUserWithPermissions(roleScope, target);
|
||||
return new ComponentUserRoleInfo()
|
||||
.setObserver(role2Uids.getOrDefault(Role.OBSERVER, Collections.emptyList()))
|
||||
.setQa(role2Uids.getOrDefault(Role.QA, Collections.emptyList()))
|
||||
.setDeveloper(role2Uids.getOrDefault(Role.DEVELOPER, Collections.emptyList()))
|
||||
.setAdmin(role2Uids.getOrDefault(Role.ADMIN, Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(RoleScope roleScope, Long target, Permission permission) {
|
||||
|
||||
PowerJobUser powerJobUser = LoginUserHolder.get();
|
||||
if (powerJobUser == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
powerJobPermissionService.hasPermission(powerJobUser.getId(), roleScope, target, permission);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void diffGrant(RoleScope roleScope, Long target, Role role, List<Long> uids, Map<Role, List<Long>> originRole2Uids) {
|
||||
|
||||
Set<Long> orignUids = Sets.newHashSet(Optional.ofNullable(originRole2Uids.get(role)).orElse(Collections.emptyList()));
|
||||
Set<Long> currentUids = Sets.newHashSet(Optional.ofNullable(uids).orElse(Collections.emptyList()));
|
||||
|
||||
Map<String, Object> extraInfo = Maps.newHashMap();
|
||||
extraInfo.put("grantor", LoginUserHolder.getUserName());
|
||||
extraInfo.put("source", "diffGrant");
|
||||
String extra = JsonUtils.toJSONString(extraInfo);
|
||||
|
||||
Set<Long> allIds = Sets.newHashSet(orignUids);
|
||||
allIds.addAll(currentUids);
|
||||
|
||||
Set<Long> allIds2 = Sets.newHashSet(allIds);
|
||||
|
||||
// 在 orignUids 不在 currentUids,需要取消授权
|
||||
allIds.removeAll(currentUids);
|
||||
allIds.forEach(cancelPermissionUid -> {
|
||||
powerJobPermissionService.retrievePermission(roleScope, target, cancelPermissionUid, role);
|
||||
log.info("[WebAuthService] [diffGrant] cancelPermission: roleScope={},target={},uid={},role={}", roleScope, target, cancelPermissionUid, role);
|
||||
});
|
||||
|
||||
// 在 currentUids 当不在 orignUids,需要增加授权
|
||||
allIds2.removeAll(orignUids);
|
||||
allIds2.forEach(addPermissionUid -> {
|
||||
powerJobPermissionService.grantPermission(roleScope, target, addPermissionUid, role, extra);
|
||||
log.info("[WebAuthService] [diffGrant] grantPermission: roleScope={},target={},uid={},role={},extra={}", roleScope, target, addPermissionUid, role, extra);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,26 +1,18 @@
|
||||
package tech.powerjob.server.web.controller;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.common.serialize.JsonUtils;
|
||||
import tech.powerjob.server.auth.*;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.common.AuthConstants;
|
||||
import tech.powerjob.server.auth.dp.GrantDynamicPermission;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
import tech.powerjob.server.auth.login.LoginTypeInfo;
|
||||
import tech.powerjob.server.auth.service.login.LoginRequest;
|
||||
import tech.powerjob.server.auth.service.login.PowerJobLoginService;
|
||||
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
|
||||
import tech.powerjob.server.web.request.GrantPermissionRequest;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@ -35,8 +27,6 @@ public class AuthController {
|
||||
|
||||
@Resource
|
||||
private PowerJobLoginService powerJobLoginService;
|
||||
@Resource
|
||||
private PowerJobPermissionService powerJobPermissionService;
|
||||
|
||||
@GetMapping("/supportLoginTypes")
|
||||
public ResultDTO<List<LoginTypeInfo>> listSupportLoginTypes() {
|
||||
@ -94,40 +84,10 @@ public class AuthController {
|
||||
@GetMapping(value = "/ifLogin")
|
||||
public ResultDTO<PowerJobUser> ifLogin(HttpServletRequest httpServletRequest) {
|
||||
final Optional<PowerJobUser> powerJobUser = powerJobLoginService.ifLogin(httpServletRequest);
|
||||
return powerJobUser.map(ResultDTO::success).orElseGet(() -> ResultDTO.failed("LOGIN_FAILED"));
|
||||
return powerJobUser.map(ResultDTO::success).orElseGet(() -> ResultDTO.success(null));
|
||||
}
|
||||
|
||||
private void fillJwt4LoginUser(PowerJobUser powerJobUser, HttpServletResponse httpServletResponse) {
|
||||
httpServletResponse.addCookie(new Cookie(AuthConstants.JWT_NAME, powerJobUser.getJwtToken()));
|
||||
}
|
||||
|
||||
/* 授权相关 */
|
||||
@PostMapping("/grantApp")
|
||||
@ApiPermission(name = "Auth-GrantAppPermission", roleScope = RoleScope.APP, dynamicPermissionPlugin = GrantDynamicPermission.class)
|
||||
public ResultDTO<Void> grantAppPermission(GrantPermissionRequest grantPermissionRequest) {
|
||||
grantPermission(RoleScope.APP, grantPermissionRequest);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
@PostMapping("/grantNamespace")
|
||||
@ApiPermission(name = "Auth-GrantNamespacePermission", roleScope = RoleScope.NAMESPACE, dynamicPermissionPlugin = GrantDynamicPermission.class)
|
||||
public ResultDTO<Void> grantNamespacePermission(GrantPermissionRequest grantPermissionRequest) {
|
||||
grantPermission(RoleScope.NAMESPACE, grantPermissionRequest);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
private void grantPermission(RoleScope roleScope, GrantPermissionRequest grantPermissionRequest) {
|
||||
|
||||
Role role = Role.of(grantPermissionRequest.getRole());
|
||||
|
||||
Optional.ofNullable(grantPermissionRequest.getUserIds()).orElse(Collections.emptyList()).forEach(uid -> {
|
||||
// 记录授权人信息
|
||||
Map<String, Object> extraInfo = Maps.newHashMap();
|
||||
extraInfo.put("grantor", LoginUserHolder.getUserName());
|
||||
String extra = JsonUtils.toJSONString(extraInfo);
|
||||
|
||||
powerJobPermissionService.grantPermission(roleScope, grantPermissionRequest.getTargetId(), uid, role, extra);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
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.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@ -13,31 +11,28 @@ import org.springframework.web.bind.annotation.*;
|
||||
import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.dp.ModifyOrCreateDynamicPermission;
|
||||
import tech.powerjob.server.auth.gp.SaveNamespaceGrantPermissionPlugin;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission;
|
||||
import tech.powerjob.server.auth.plugin.SaveNamespaceGrantPermissionPlugin;
|
||||
import tech.powerjob.server.auth.service.WebAuthService;
|
||||
import tech.powerjob.server.common.constants.SwitchableStatus;
|
||||
import tech.powerjob.server.persistence.PageResult;
|
||||
import tech.powerjob.server.persistence.QueryConvertUtils;
|
||||
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.ComponentUserRoleInfo;
|
||||
import tech.powerjob.server.web.request.ModifyNamespaceRequest;
|
||||
import tech.powerjob.server.web.request.QueryNamespaceRequest;
|
||||
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||
import tech.powerjob.server.web.response.NamespaceDetailVO;
|
||||
import tech.powerjob.server.web.response.UserBaseVO;
|
||||
import tech.powerjob.server.web.response.NamespaceVO;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -51,23 +46,24 @@ import java.util.stream.Collectors;
|
||||
@RequestMapping("/namespace")
|
||||
public class NamespaceController {
|
||||
|
||||
@Resource
|
||||
private WebAuthService webAuthService;
|
||||
@Resource
|
||||
private NamespaceRepository namespaceRepository;
|
||||
@Resource
|
||||
private UserInfoRepository userInfoRepository;
|
||||
@Resource
|
||||
private UserRoleRepository userRoleRepository;
|
||||
|
||||
@ResponseBody
|
||||
@PostMapping("/save")
|
||||
@ApiPermission(name = "Namespace-Save", roleScope = RoleScope.NAMESPACE, dynamicPermissionPlugin = ModifyOrCreateDynamicPermission.class, grandPermissionPlugin = SaveNamespaceGrantPermissionPlugin.class)
|
||||
public ResultDTO<NamespaceBaseVO> save(@RequestBody ModifyNamespaceRequest req) {
|
||||
public ResultDTO<NamespaceVO> save(@RequestBody ModifyNamespaceRequest req) {
|
||||
|
||||
req.valid();
|
||||
|
||||
Long id = req.getId();
|
||||
NamespaceDO namespaceDO;
|
||||
if (id == null) {
|
||||
|
||||
boolean isCreate = id == null;
|
||||
|
||||
if (isCreate) {
|
||||
namespaceDO = new NamespaceDO();
|
||||
namespaceDO.setGmtCreate(new Date());
|
||||
|
||||
@ -80,20 +76,36 @@ public class NamespaceController {
|
||||
} else {
|
||||
namespaceDO = fetchById(id);
|
||||
namespaceDO.setModifier(LoginUserHolder.getUserName());
|
||||
|
||||
if (!namespaceDO.getCode().equalsIgnoreCase(req.getCode())) {
|
||||
throw new IllegalArgumentException("NOT_ALLOW_CHANGE_THE_NAMESPACE_CODE");
|
||||
}
|
||||
}
|
||||
|
||||
// 拷贝通用变更属性(code 不允许更改)
|
||||
namespaceDO.setTags(req.getTags());
|
||||
namespaceDO.setName(req.getName());
|
||||
namespaceDO.setExtra(req.getExtra());
|
||||
namespaceDO.setStatus(Optional.ofNullable(req.getStatus()).orElse(SwitchableStatus.ENABLE.getV()));
|
||||
|
||||
namespaceDO.setGmtModified(new Date());
|
||||
NamespaceDO savedNamespace = namespaceRepository.save(namespaceDO);
|
||||
|
||||
// 授权
|
||||
webAuthService.processPermissionOnSave(RoleScope.NAMESPACE, savedNamespace.getId(), req.getComponentUserRoleInfo());
|
||||
|
||||
return ResultDTO.success(NamespaceConverter.do2BaseVo(savedNamespace));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiPermission(name = "Namespace-Delete", roleScope = RoleScope.NAMESPACE, requiredPermission = Permission.SU)
|
||||
public ResultDTO<Void> deleteNamespace(Long id) {
|
||||
namespaceRepository.deleteById(id);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
public ResultDTO<PageResult<NamespaceBaseVO>> listNamespace(@RequestBody QueryNamespaceRequest queryNamespaceRequest) {
|
||||
public ResultDTO<PageResult<NamespaceVO>> listNamespace(@RequestBody QueryNamespaceRequest queryNamespaceRequest) {
|
||||
|
||||
String codeLike = queryNamespaceRequest.getCodeLike();
|
||||
String nameLike = queryNamespaceRequest.getNameLike();
|
||||
@ -123,39 +135,29 @@ public class NamespaceController {
|
||||
|
||||
Page<NamespaceDO> namespacePageResult = namespaceRepository.findAll(specification, pageable);
|
||||
|
||||
PageResult<NamespaceBaseVO> ret = new PageResult<>(namespacePageResult);
|
||||
ret.setData(namespacePageResult.get().map(NamespaceConverter::do2BaseVo).collect(Collectors.toList()));
|
||||
PageResult<NamespaceVO> ret = new PageResult<>(namespacePageResult);
|
||||
ret.setData(namespacePageResult.get().map(x -> {
|
||||
NamespaceVO namespaceVO = NamespaceConverter.do2BaseVo(x);
|
||||
fillPermissionInfo(x, namespaceVO);
|
||||
return namespaceVO;
|
||||
}).collect(Collectors.toList()));
|
||||
|
||||
return ResultDTO.success(ret);
|
||||
}
|
||||
|
||||
@GetMapping("/detail")
|
||||
@ApiPermission(name = "Namespace-GetDetail", roleScope = RoleScope.NAMESPACE, requiredPermission = Permission.READ)
|
||||
public ResultDTO<NamespaceDetailVO> queryNamespaceDetail(Long id) {
|
||||
private void fillPermissionInfo(NamespaceDO namespaceDO, NamespaceVO namespaceVO) {
|
||||
|
||||
NamespaceDO namespaceDO = fetchById(id);
|
||||
NamespaceDetailVO namespaceDetailVO = new NamespaceDetailVO();
|
||||
Long namespaceId = namespaceVO.getId();
|
||||
|
||||
// 拷贝基础字段
|
||||
NamespaceBaseVO namespaceBaseVO = NamespaceConverter.do2BaseVo(namespaceDO);
|
||||
BeanUtils.copyProperties(namespaceBaseVO, namespaceDetailVO);
|
||||
// 权限用户关系
|
||||
ComponentUserRoleInfo componentUserRoleInfo = webAuthService.fetchComponentUserRoleInfo(RoleScope.NAMESPACE, namespaceId);
|
||||
namespaceVO.setComponentUserRoleInfo(componentUserRoleInfo);
|
||||
|
||||
// 处理 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);
|
||||
// 有权限用户填充 token
|
||||
boolean hasPermission = webAuthService.hasPermission(RoleScope.NAMESPACE, namespaceId, Permission.READ);
|
||||
if (hasPermission) {
|
||||
namespaceVO.setToken(namespaceDO.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
private NamespaceDO fetchById(Long id) {
|
||||
|
@ -4,7 +4,7 @@ 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;
|
||||
import tech.powerjob.server.web.response.NamespaceVO;
|
||||
|
||||
/**
|
||||
* NamespaceConverter
|
||||
@ -14,8 +14,8 @@ import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||
*/
|
||||
public class NamespaceConverter {
|
||||
|
||||
public static NamespaceBaseVO do2BaseVo(NamespaceDO d) {
|
||||
NamespaceBaseVO v = new NamespaceBaseVO();
|
||||
public static NamespaceVO do2BaseVo(NamespaceDO d) {
|
||||
NamespaceVO v = new NamespaceVO();
|
||||
BeanUtils.copyProperties(d, v);
|
||||
v.setGmtCreateStr(CommonUtils.formatTime(d.getGmtCreate()));
|
||||
v.setGmtModifiedStr(CommonUtils.formatTime(d.getGmtModified()));
|
||||
|
@ -0,0 +1,34 @@
|
||||
package tech.powerjob.server.web.request;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 组件上的用户角色信息
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/2/12
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ComponentUserRoleInfo {
|
||||
/**
|
||||
* 观察者
|
||||
*/
|
||||
private List<Long> observer;
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
private List<Long> qa;
|
||||
/**
|
||||
* 开发者
|
||||
*/
|
||||
private List<Long> developer;
|
||||
/**
|
||||
* 管理员
|
||||
*/
|
||||
private List<Long> admin;
|
||||
|
||||
}
|
@ -39,6 +39,10 @@ public class ModifyNamespaceRequest {
|
||||
* 扩展字段
|
||||
*/
|
||||
private String extra;
|
||||
/**
|
||||
* 权限表单
|
||||
*/
|
||||
private ComponentUserRoleInfo componentUserRoleInfo;
|
||||
|
||||
public void valid() {
|
||||
CommonUtils.requireNonNull(code, "namespace code can't be empty");
|
||||
|
@ -1,29 +0,0 @@
|
||||
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;
|
||||
}
|
@ -3,6 +3,7 @@ package tech.powerjob.server.web.response;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
@ -16,7 +17,7 @@ import java.util.Date;
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class NamespaceBaseVO implements Serializable {
|
||||
public class NamespaceVO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
@ -52,4 +53,13 @@ public class NamespaceBaseVO implements Serializable {
|
||||
private String creator;
|
||||
|
||||
private String modifier;
|
||||
|
||||
/**
|
||||
* 访问 token
|
||||
* 仅拥有当前 namespace 权限的访问者可见
|
||||
*/
|
||||
private String token;
|
||||
|
||||
private ComponentUserRoleInfo componentUserRoleInfo;
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user