mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
fix: [auth] grant and chekc permission's bug
This commit is contained in:
parent
919a5c3b35
commit
05c22a5dc5
@ -18,4 +18,6 @@ public class AuthConstants {
|
||||
* 前端跳转到指定页面指令
|
||||
*/
|
||||
public static final String FE_REDIRECT_KEY = "FE-REDIRECT:";
|
||||
|
||||
public static final String TIPS_NO_PERMISSION_TO_SEE = "NO_PERMISSION_TO_SEE";
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class HttpServletUtils {
|
||||
String v = httpServletRequest.getHeader(key);
|
||||
|
||||
// 解决 window.localStorage.getItem 为 null 的问题
|
||||
if (OmsConstant.NULL.equalsIgnoreCase(v)) {
|
||||
if (OmsConstant.NULL.equalsIgnoreCase(v) || "undefined".equalsIgnoreCase(v)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -45,17 +45,17 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
final Role role = Role.of(userRole.getRole());
|
||||
|
||||
// 处理全局权限
|
||||
if (RoleScope.GLOBAL.equals(roleScope)) {
|
||||
if (RoleScope.GLOBAL.getV() == userRole.getScope()) {
|
||||
if (Role.ADMIN.equals(role)) {
|
||||
return true;
|
||||
}
|
||||
globalRoles.add(role);
|
||||
}
|
||||
|
||||
if (Objects.equals(userRole.getScope(), RoleScope.NAMESPACE.getV())) {
|
||||
if (RoleScope.NAMESPACE.getV() == userRole.getScope()) {
|
||||
namespaceId2Role.put(userRole.getTarget(), role);
|
||||
}
|
||||
if (Objects.equals(userRole.getScope(), RoleScope.APP.getV())) {
|
||||
if (RoleScope.APP.getV() == userRole.getScope()) {
|
||||
appId2Role.put(userRole.getTarget(), role);
|
||||
}
|
||||
}
|
||||
@ -98,7 +98,7 @@ public class PowerJobPermissionServiceImpl implements PowerJobPermissionService
|
||||
userRoleDO.setRole(role.getV());
|
||||
|
||||
userRoleRepository.saveAndFlush(userRoleDO);
|
||||
log.info("[PowerJobPermissionService] saveAndFlush userRole successfully: {}", userRoleDO);
|
||||
log.info("[PowerJobPermissionService] [grantPermission] saveAndFlush userRole successfully: {}", userRoleDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,12 +22,14 @@ public class AppInfoDO {
|
||||
@GenericGenerator(name = "native", strategy = "native")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 命名空间ID,外键关联
|
||||
*/
|
||||
private Long namespaceId;
|
||||
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 应用分组密码
|
||||
*/
|
||||
@ -40,7 +42,24 @@ public class AppInfoDO {
|
||||
*/
|
||||
private String currentServer;
|
||||
|
||||
/**
|
||||
* 命名空间ID,外键关联
|
||||
*/
|
||||
private Long namespaceId;
|
||||
/**
|
||||
* 管理标签
|
||||
*/
|
||||
private String tags;
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
private Date gmtCreate;
|
||||
|
||||
private Date gmtModified;
|
||||
|
||||
private String creator;
|
||||
|
||||
private String modifier;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package tech.powerjob.server.auth.plugin;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import tech.powerjob.common.response.ResultDTO;
|
||||
@ -9,12 +10,10 @@ import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.interceptor.GrantPermissionPlugin;
|
||||
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
|
||||
import tech.powerjob.server.common.utils.SpringUtils;
|
||||
import tech.powerjob.server.persistence.remote.model.UserRoleDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserRoleRepository;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -65,17 +64,12 @@ public abstract class SaveGrantPermissionPlugin implements GrantPermissionPlugin
|
||||
throw new IllegalArgumentException("[GrantPermission] result success but id not exits, maybe there has some bug, please fix it!!!");
|
||||
}
|
||||
|
||||
UserRoleRepository userRoleRepository = SpringUtils.getBean(UserRoleRepository.class);
|
||||
UserRoleDO userRoleDO = new UserRoleDO();
|
||||
PowerJobPermissionService powerJobPermissionService = SpringUtils.getBean(PowerJobPermissionService.class);
|
||||
|
||||
userRoleDO.setUserId(powerJobUser.getId());
|
||||
userRoleDO.setRole(Role.ADMIN.getV());
|
||||
userRoleDO.setScope(fetchRuleScope().getV());
|
||||
userRoleDO.setTarget(savedId);
|
||||
userRoleDO.setGmtCreate(new Date());
|
||||
userRoleDO.setGmtModified(new Date());
|
||||
Map<String, Object> extra = Maps.newHashMap();
|
||||
extra.put("source", "SaveGrantPermissionPlugin");
|
||||
|
||||
userRoleRepository.saveAndFlush(userRoleDO);
|
||||
powerJobPermissionService.grantPermission(fetchRuleScope(), savedId, powerJobUser.getId(), Role.ADMIN, JsonUtils.toJSONString(extra));
|
||||
}
|
||||
|
||||
protected abstract RoleScope fetchRuleScope();
|
||||
|
@ -56,9 +56,7 @@ public class WebAuthServiceImpl implements WebAuthService {
|
||||
return false;
|
||||
}
|
||||
|
||||
powerJobPermissionService.hasPermission(powerJobUser.getId(), roleScope, target, permission);
|
||||
|
||||
return false;
|
||||
return powerJobPermissionService.hasPermission(powerJobUser.getId(), roleScope, target, permission);
|
||||
}
|
||||
|
||||
private void diffGrant(RoleScope roleScope, Long target, Role role, List<Long> uids, Map<Role, List<Long>> originRole2Uids) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package tech.powerjob.server.web.controller;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
@ -11,24 +10,30 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import tech.powerjob.common.exception.PowerJobException;
|
||||
import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.common.utils.CommonUtils;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.common.AuthConstants;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission;
|
||||
import tech.powerjob.server.auth.plugin.SaveAppGrantPermissionPlugin;
|
||||
import tech.powerjob.server.auth.service.WebAuthService;
|
||||
import tech.powerjob.server.core.service.AppInfoService;
|
||||
import tech.powerjob.server.persistence.PageResult;
|
||||
import tech.powerjob.server.persistence.QueryConvertUtils;
|
||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
||||
import tech.powerjob.server.web.request.AppAssertRequest;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
import tech.powerjob.server.web.request.ModifyAppInfoRequest;
|
||||
import tech.powerjob.server.web.request.QueryAppInfoRequest;
|
||||
import tech.powerjob.server.web.response.AppInfoVO;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -43,6 +48,8 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class AppInfoController {
|
||||
|
||||
private final WebAuthService webAuthService;
|
||||
|
||||
private final AppInfoService appInfoService;
|
||||
|
||||
private final AppInfoRepository appInfoRepository;
|
||||
@ -50,6 +57,7 @@ public class AppInfoController {
|
||||
private static final int MAX_APP_NUM = 200;
|
||||
|
||||
@PostMapping("/save")
|
||||
@ApiPermission(name = "App-Save", roleScope = RoleScope.APP, dynamicPermissionPlugin = ModifyOrCreateDynamicPermission.class, grandPermissionPlugin = SaveAppGrantPermissionPlugin.class)
|
||||
public ResultDTO<AppInfoVO> saveAppInfo(@RequestBody ModifyAppInfoRequest req) {
|
||||
|
||||
req.valid();
|
||||
@ -59,73 +67,73 @@ public class AppInfoController {
|
||||
if (id == null) {
|
||||
appInfoDO = new AppInfoDO();
|
||||
appInfoDO.setGmtCreate(new Date());
|
||||
}else {
|
||||
appInfoDO.setCreator(LoginUserHolder.getUserName());
|
||||
} else {
|
||||
appInfoDO = appInfoRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("can't find appInfo by id:" + id));
|
||||
|
||||
// 对比密码
|
||||
if (!Objects.equals(req.getOldPassword(), appInfoDO.getPassword())) {
|
||||
throw new PowerJobException("The password is incorrect.");
|
||||
// 不允许修改 appName
|
||||
if (!appInfoDO.getAppName().equalsIgnoreCase(req.getAppName())) {
|
||||
throw new IllegalArgumentException("NOT_ALLOW_CHANGE_THE_APP_NAME");
|
||||
}
|
||||
}
|
||||
BeanUtils.copyProperties(req, appInfoDO);
|
||||
|
||||
appInfoDO.setAppName(req.getAppName());
|
||||
appInfoDO.setTitle(req.getTitle());
|
||||
appInfoDO.setPassword(req.getPassword());
|
||||
appInfoDO.setNamespaceId(req.getNamespaceId());
|
||||
appInfoDO.setTags(req.getTags());
|
||||
appInfoDO.setExtra(req.getExtra());
|
||||
|
||||
appInfoDO.setGmtModified(new Date());
|
||||
appInfoDO.setModifier(LoginUserHolder.getUserName());
|
||||
|
||||
AppInfoDO savedAppInfo = appInfoRepository.saveAndFlush(appInfoDO);
|
||||
|
||||
// 重现授权
|
||||
webAuthService.processPermissionOnSave(RoleScope.APP, savedAppInfo.getId(), req.getComponentUserRoleInfo());
|
||||
|
||||
return ResultDTO.success(convert(Lists.newArrayList(savedAppInfo), false).get(0));
|
||||
}
|
||||
|
||||
@GetMapping("/delete")
|
||||
@ApiPermission(name = "App-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.SU)
|
||||
public ResultDTO<Void> deleteAppInfo(Long appId) {
|
||||
appInfoRepository.deleteById(appId);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
@PostMapping("/assert")
|
||||
public ResultDTO<Long> assertApp(@RequestBody AppAssertRequest request) {
|
||||
return ResultDTO.success(appInfoService.assertApp(request.getAppName(), request.getPassword()));
|
||||
}
|
||||
|
||||
@GetMapping("/delete")
|
||||
public ResultDTO<Void> deleteAppInfo(Long appId) {
|
||||
appInfoRepository.deleteById(appId);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public ResultDTO<List<AppInfoVO>> listAppInfo(@RequestParam(required = false) String condition) {
|
||||
List<AppInfoDO> result;
|
||||
Pageable limit = PageRequest.of(0, MAX_APP_NUM);
|
||||
if (StringUtils.isEmpty(condition)) {
|
||||
result = appInfoRepository.findAll(limit).getContent();
|
||||
}else {
|
||||
result = appInfoRepository.findByAppNameLike("%" + condition + "%", limit).getContent();
|
||||
}
|
||||
return ResultDTO.success(convert(result, false));
|
||||
}
|
||||
|
||||
@PostMapping("/listByQuery")
|
||||
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(QueryAppInfoRequest queryAppInfoRequest) {
|
||||
@PostMapping("/list")
|
||||
@ApiPermission(name = "Namespace-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE)
|
||||
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) {
|
||||
|
||||
Pageable pageable = PageRequest.of(queryAppInfoRequest.getIndex(), queryAppInfoRequest.getPageSize());
|
||||
|
||||
// TODO: 我有权限的列表
|
||||
Specification<AppInfoDO> specification = new Specification<AppInfoDO>() {
|
||||
@Override
|
||||
public Predicate toPredicate(Root<AppInfoDO> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
|
||||
List<Predicate> predicates = Lists.newArrayList();
|
||||
Specification<AppInfoDO> specification = (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> predicates = Lists.newArrayList();
|
||||
|
||||
|
||||
Long appId = queryAppInfoRequest.getAppId();
|
||||
Long namespaceId = queryAppInfoRequest.getNamespaceId();
|
||||
Long appId = queryAppInfoRequest.getAppId();
|
||||
Long namespaceId = queryAppInfoRequest.getNamespaceId();
|
||||
|
||||
if (appId != null) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("id"), appId));
|
||||
}
|
||||
|
||||
if (namespaceId != null) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("namespaceId"), namespaceId));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(queryAppInfoRequest.getAppName())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("appName"), QueryConvertUtils.convertLikeParams(queryAppInfoRequest.getAppName())));
|
||||
}
|
||||
|
||||
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
|
||||
if (appId != null) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("id"), appId));
|
||||
}
|
||||
|
||||
if (namespaceId != null) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("namespaceId"), namespaceId));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(queryAppInfoRequest.getAppNameLike())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("appName"), QueryConvertUtils.convertLikeParams(queryAppInfoRequest.getAppNameLike())));
|
||||
}
|
||||
|
||||
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
|
||||
};
|
||||
|
||||
Page<AppInfoDO> pageAppInfoResult = appInfoRepository.findAll(specification, pageable);
|
||||
@ -139,27 +147,30 @@ public class AppInfoController {
|
||||
}
|
||||
|
||||
|
||||
private static List<AppInfoVO> convert(List<AppInfoDO> data, boolean fillDetail) {
|
||||
private List<AppInfoVO> convert(List<AppInfoDO> data, boolean fillDetail) {
|
||||
if (CollectionUtils.isEmpty(data)) {
|
||||
return Lists.newLinkedList();
|
||||
}
|
||||
List<AppInfoVO> appInfoVOList = data.stream().map(appInfoDO -> {
|
||||
|
||||
return data.stream().map(appInfoDO -> {
|
||||
AppInfoVO appInfoVO = new AppInfoVO();
|
||||
BeanUtils.copyProperties(appInfoDO, appInfoVO);
|
||||
|
||||
appInfoVO.setGmtCreateStr(CommonUtils.formatTime(appInfoDO.getGmtCreate()));
|
||||
appInfoVO.setGmtModifiedStr(CommonUtils.formatTime(appInfoDO.getGmtModified()));
|
||||
|
||||
if (fillDetail) {
|
||||
// 人员面板
|
||||
ComponentUserRoleInfo componentUserRoleInfo = webAuthService.fetchComponentUserRoleInfo(RoleScope.APP, appInfoDO.getId());
|
||||
appInfoVO.setComponentUserRoleInfo(componentUserRoleInfo);
|
||||
|
||||
// 密码
|
||||
boolean hasPermission = webAuthService.hasPermission(RoleScope.APP, appInfoDO.getId(), Permission.READ);
|
||||
appInfoVO.setPassword(hasPermission ? appInfoDO.getPassword() : AuthConstants.TIPS_NO_PERMISSION_TO_SEE);
|
||||
}
|
||||
|
||||
return appInfoVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
if (fillDetail) {
|
||||
// TODO: 补全权限等额外信息
|
||||
}
|
||||
|
||||
return appInfoVOList;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class AppInfoVO {
|
||||
private Long id;
|
||||
private String appName;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.common.AuthConstants;
|
||||
import tech.powerjob.server.auth.interceptor.ApiPermission;
|
||||
import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission;
|
||||
import tech.powerjob.server.auth.plugin.SaveNamespaceGrantPermissionPlugin;
|
||||
@ -105,6 +106,7 @@ public class NamespaceController {
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
@ApiPermission(name = "Namespace-List", roleScope = RoleScope.NAMESPACE, requiredPermission = Permission.NONE)
|
||||
public ResultDTO<PageResult<NamespaceVO>> listNamespace(@RequestBody QueryNamespaceRequest queryNamespaceRequest) {
|
||||
|
||||
String codeLike = queryNamespaceRequest.getCodeLike();
|
||||
@ -155,9 +157,7 @@ public class NamespaceController {
|
||||
|
||||
// 有权限用户填充 token
|
||||
boolean hasPermission = webAuthService.hasPermission(RoleScope.NAMESPACE, namespaceId, Permission.READ);
|
||||
if (hasPermission) {
|
||||
namespaceVO.setToken(namespaceDO.getToken());
|
||||
}
|
||||
namespaceVO.setToken(hasPermission ? namespaceDO.getToken() : AuthConstants.TIPS_NO_PERMISSION_TO_SEE);
|
||||
}
|
||||
|
||||
private NamespaceDO fetchById(Long id) {
|
||||
|
@ -15,14 +15,34 @@ import org.apache.commons.lang3.StringUtils;
|
||||
public class ModifyAppInfoRequest {
|
||||
|
||||
private Long id;
|
||||
private String oldPassword;
|
||||
private String appName;
|
||||
|
||||
private Long namespaceId;
|
||||
|
||||
private String oldPassword;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 管理标签
|
||||
*/
|
||||
private String tags;
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
private ComponentUserRoleInfo componentUserRoleInfo;
|
||||
|
||||
public void valid() {
|
||||
CommonUtils.requireNonNull(appName, "appName can't be empty");
|
||||
if (StringUtils.containsWhitespace(appName)) {
|
||||
throw new PowerJobException("appName can't contains white space!");
|
||||
}
|
||||
CommonUtils.requireNonNull(password, "password can't be empty");
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ public class QueryAppInfoRequest {
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String appName;
|
||||
private String appNameLike;
|
||||
|
||||
private String tagLike;
|
||||
|
||||
/**
|
||||
* 查询与我相关的任务(我有直接权限的)
|
||||
|
@ -0,0 +1,46 @@
|
||||
package tech.powerjob.server.web.response;
|
||||
|
||||
import lombok.Data;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* AppInfoVO
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/2/12
|
||||
*/
|
||||
@Data
|
||||
public class AppInfoVO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String title;
|
||||
|
||||
private String password;
|
||||
|
||||
private String tags;
|
||||
|
||||
private String extra;
|
||||
|
||||
private ComponentUserRoleInfo componentUserRoleInfo;
|
||||
|
||||
private Date gmtCreate;
|
||||
|
||||
private String gmtCreateStr;
|
||||
|
||||
private Date gmtModified;
|
||||
|
||||
private String gmtModifiedStr;
|
||||
|
||||
private String creator;
|
||||
|
||||
private String modifier;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user