feat: [auth] The web interface adds ApiPermission for authentication.

This commit is contained in:
tjq 2024-02-13 11:21:14 +08:00
parent 05c22a5dc5
commit 31a7690844
18 changed files with 170 additions and 55 deletions

View File

@ -1,7 +1,6 @@
package tech.powerjob.server.core.uid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tech.powerjob.server.remote.server.self.ServerInfoService;
@ -22,7 +21,7 @@ public class IdGenerateService {
private static final int DATA_CENTER_ID = 0;
public IdGenerateService(ServerInfoService serverInfoService) {
long id = serverInfoService.fetchServiceInfo().getId();
long id = serverInfoService.fetchCurrentServerInfo().getId();
snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
log.info("[IdGenerateService] initialize IdGenerateService successfully, ID:{}", id);
}

View File

@ -14,6 +14,13 @@ public interface ServerInfoService {
* fetch current server info
* @return ServerInfo
*/
ServerInfo fetchServiceInfo();
ServerInfo fetchCurrentServerInfo();
/**
* fetch schedule server info
* @param appId appId
* @return ServerInfo
*/
ServerInfo fetchAppServerInfo(Long appId);
}

View File

@ -15,6 +15,7 @@ import tech.powerjob.server.common.module.ServerInfo;
import tech.powerjob.server.extension.LockService;
import tech.powerjob.server.persistence.remote.model.ServerInfoDO;
import tech.powerjob.server.persistence.remote.repository.ServerInfoRepository;
import tech.powerjob.server.remote.server.redirector.DesignateServer;
import java.util.Date;
import java.util.List;
@ -138,7 +139,13 @@ public class ServerInfoServiceImpl implements ServerInfoService {
}
@Override
public ServerInfo fetchServiceInfo() {
public ServerInfo fetchCurrentServerInfo() {
return serverInfo;
}
@Override
@DesignateServer
public ServerInfo fetchAppServerInfo(Long appId) {
return serverInfo;
}
}

View File

@ -61,7 +61,7 @@ public class WebAuthServiceImpl implements WebAuthService {
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> originUids = 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();
@ -69,12 +69,12 @@ public class WebAuthServiceImpl implements WebAuthService {
extraInfo.put("source", "diffGrant");
String extra = JsonUtils.toJSONString(extraInfo);
Set<Long> allIds = Sets.newHashSet(orignUids);
Set<Long> allIds = Sets.newHashSet(originUids);
allIds.addAll(currentUids);
Set<Long> allIds2 = Sets.newHashSet(allIds);
// orignUids 不在 currentUids需要取消授权
// originUids 不在 currentUids需要取消授权
allIds.removeAll(currentUids);
allIds.forEach(cancelPermissionUid -> {
powerJobPermissionService.retrievePermission(roleScope, target, cancelPermissionUid, role);
@ -82,7 +82,7 @@ public class WebAuthServiceImpl implements WebAuthService {
});
// currentUids 当不在 orignUids需要增加授权
allIds2.removeAll(orignUids);
allIds2.removeAll(originUids);
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);

View File

@ -41,7 +41,7 @@ public class SwaggerConfig {
return new OpenAPI()
.info(new Info().title("PowerJob")
.description("Distributed scheduling and computing framework.")
.version(serverInfoService.fetchServiceInfo().getVersion())
.version(serverInfoService.fetchCurrentServerInfo().getVersion())
.contact(contact)
.license(new License().name("Apache License 2.0").url("https://github.com/PowerJob/PowerJob/blob/master/LICENSE")));
}

View File

@ -19,7 +19,7 @@ import java.util.List;
public class ServerInfoAwareProcessor {
public ServerInfoAwareProcessor(ServerInfoService serverInfoService, List<ServerInfoAware> awareList) {
final ServerInfo serverInfo = serverInfoService.fetchServiceInfo();
final ServerInfo serverInfo = serverInfoService.fetchCurrentServerInfo();
log.info("[ServerInfoAwareProcessor] current server info: {}", serverInfo);
awareList.forEach(aware -> {
aware.setServerInfo(serverInfo);

View File

@ -20,12 +20,10 @@ 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;
@ -50,12 +48,8 @@ public class AppInfoController {
private final WebAuthService webAuthService;
private final AppInfoService appInfoService;
private final AppInfoRepository appInfoRepository;
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) {
@ -102,11 +96,6 @@ public class AppInfoController {
return ResultDTO.success(null);
}
@PostMapping("/assert")
public ResultDTO<Long> assertApp(@RequestBody AppAssertRequest request) {
return ResultDTO.success(appInfoService.assertApp(request.getAppName(), request.getPassword()));
}
@PostMapping("/list")
@ApiPermission(name = "Namespace-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE)
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) {
@ -146,7 +135,6 @@ public class AppInfoController {
return ResultDTO.success(pageRet);
}
private List<AppInfoVO> convert(List<AppInfoDO> data, boolean fillDetail) {
if (CollectionUtils.isEmpty(data)) {
return Lists.newLinkedList();

View File

@ -4,11 +4,13 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import tech.powerjob.common.OmsConstant;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.common.constants.ContainerSourceType;
import tech.powerjob.server.common.constants.SwitchableStatus;
import tech.powerjob.server.common.utils.OmsFileUtils;
@ -39,22 +41,25 @@ import java.util.stream.Collectors;
@RequestMapping("/container")
public class ContainerController {
private final int port;
private final ContainerService containerService;
private final AppInfoRepository appInfoRepository;
private final ContainerInfoRepository containerInfoRepository;
public ContainerController(@Value("${server.port}") int port, ContainerService containerService, AppInfoRepository appInfoRepository, ContainerInfoRepository containerInfoRepository) {
this.port = port;
public ContainerController(ContainerService containerService, AppInfoRepository appInfoRepository, ContainerInfoRepository containerInfoRepository) {
this.containerService = containerService;
this.appInfoRepository = appInfoRepository;
this.containerInfoRepository = containerInfoRepository;
}
/**
* 暴露给 worker 的下载端口制品本身 version 不可枚举不单独鉴权
* 如果对此有安全性需求可自行实现加密鉴权逻辑或者干脆走自己的下载通道下载制品
* @param version 容器版本
* @param response 响应
* @throws IOException 异常
*/
@GetMapping("/downloadJar")
public void downloadJar(String version, HttpServletResponse response) throws IOException {
File file = containerService.fetchContainerJarFile(version);
@ -66,12 +71,14 @@ public class ContainerController {
}
@PostMapping("/downloadContainerTemplate")
@ApiPermission(name = "Container-DownloadContainerTemplate", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public void downloadContainerTemplate(@RequestBody GenerateContainerTemplateRequest req, HttpServletResponse response) throws IOException {
File zipFile = ContainerTemplateGenerator.generate(req.getGroup(), req.getArtifact(), req.getName(), req.getPackageName(), req.getJavaVersion());
OmsFileUtils.file2HttpResponse(zipFile, response);
}
@PostMapping("/jarUpload")
@ApiPermission(name = "Container-JarUpload", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<String> fileUpload(@RequestParam("file") MultipartFile file) throws Exception {
if (file == null || file.isEmpty()) {
return ResultDTO.failed("empty file");
@ -80,6 +87,7 @@ public class ContainerController {
}
@PostMapping("/save")
@ApiPermission(name = "Container-Save", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> saveContainer(@RequestBody SaveContainerInfoRequest request) {
request.valid();
@ -93,12 +101,14 @@ public class ContainerController {
}
@GetMapping("/delete")
@ApiPermission(name = "Container-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> deleteContainer(Long appId, Long containerId) {
containerService.delete(appId, containerId);
return ResultDTO.success(null);
}
@GetMapping("/list")
@ApiPermission(name = "Container-List", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<List<ContainerInfoVO>> listContainers(Long appId) {
List<ContainerInfoVO> res = containerInfoRepository.findByAppIdAndStatusNot(appId, SwitchableStatus.DELETED.getV())
.stream().map(ContainerController::convert).collect(Collectors.toList());
@ -106,6 +116,7 @@ public class ContainerController {
}
@GetMapping("/listDeployedWorker")
@ApiPermission(name = "Container-ListDeployedWorker", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<String> listDeployedWorker(Long appId, Long containerId, HttpServletResponse response) {
AppInfoDO appInfoDO = appInfoRepository.findById(appId).orElseThrow(() -> new IllegalArgumentException("can't find app by id:" + appId));
String targetServer = appInfoDO.getCurrentServer();

View File

@ -2,6 +2,9 @@ package tech.powerjob.server.web.controller;
import tech.powerjob.common.enums.InstanceStatus;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.common.utils.OmsFileUtils;
import tech.powerjob.server.persistence.PageResult;
import tech.powerjob.server.persistence.StringPage;
@ -43,8 +46,6 @@ import java.util.stream.Collectors;
@RequestMapping("/instance")
public class InstanceController {
@Resource
private InstanceService instanceService;
@Resource
@ -56,18 +57,21 @@ public class InstanceController {
private InstanceInfoRepository instanceInfoRepository;
@GetMapping("/stop")
@ApiPermission(name = "Instance-Stop", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> stopInstance(Long appId,Long instanceId) {
instanceService.stopInstance(appId,instanceId);
return ResultDTO.success(null);
}
@GetMapping("/retry")
@ApiPermission(name = "Instance-Retry", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> retryInstance(String appId, Long instanceId) {
instanceService.retryInstance(Long.valueOf(appId), instanceId);
return ResultDTO.success(null);
}
@GetMapping("/detail")
@ApiPermission(name = "Instance-Detail", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<InstanceDetailVO> getInstanceDetail(Long appId, Long instanceId) {
// 兼容老版本前端不存在 appId 的场景
@ -79,11 +83,13 @@ public class InstanceController {
}
@GetMapping("/log")
@ApiPermission(name = "Instance-Log", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<StringPage> getInstanceLog(Long appId, Long instanceId, Long index) {
return ResultDTO.success(instanceLogService.fetchInstanceLog(appId, instanceId, index));
}
@GetMapping("/downloadLogUrl")
@ApiPermission(name = "Instance-FetchDownloadLogUrl", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<String> getDownloadUrl(Long appId, Long instanceId) {
return ResultDTO.success(instanceLogService.fetchDownloadUrl(appId, instanceId));
}
@ -115,6 +121,7 @@ public class InstanceController {
}
@PostMapping("/list")
@ApiPermission(name = "Instance-List", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<PageResult<InstanceInfoVO>> list(@RequestBody QueryInstanceRequest request) {
Sort sort = Sort.by(Sort.Direction.DESC, "gmtModified");

View File

@ -3,6 +3,9 @@ package tech.powerjob.server.web.controller;
import org.apache.commons.lang3.StringUtils;
import tech.powerjob.common.request.http.SaveJobInfoRequest;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.common.constants.SwitchableStatus;
import tech.powerjob.server.persistence.PageResult;
import tech.powerjob.server.persistence.remote.model.JobInfoDO;
@ -39,39 +42,46 @@ public class JobController {
private JobInfoRepository jobInfoRepository;
@PostMapping("/save")
@ApiPermission(name = "Job-Save", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> saveJobInfo(@RequestBody SaveJobInfoRequest request) {
jobService.saveJob(request);
return ResultDTO.success(null);
}
@PostMapping("/copy")
@ApiPermission(name = "Job-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<JobInfoVO> copyJob(String jobId) {
return ResultDTO.success(JobInfoVO.from(jobService.copyJob(Long.valueOf(jobId))));
}
@GetMapping("/export")
@ApiPermission(name = "Job-Export", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<SaveJobInfoRequest> exportJob(String jobId) {
return ResultDTO.success(jobService.exportJob(Long.valueOf(jobId)));
}
@GetMapping("/disable")
@ApiPermission(name = "Job-Disable", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> disableJob(String jobId) {
jobService.disableJob(Long.valueOf(jobId));
return ResultDTO.success(null);
}
@GetMapping("/delete")
@ApiPermission(name = "Job-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> deleteJob(String jobId) {
jobService.deleteJob(Long.valueOf(jobId));
return ResultDTO.success(null);
}
@GetMapping("/run")
@ApiPermission(name = "Job-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Long> runImmediately(String appId, String jobId, @RequestParam(required = false) String instanceParams) {
return ResultDTO.success(jobService.runJob(Long.valueOf(appId), Long.valueOf(jobId), instanceParams, 0L));
}
@PostMapping("/list")
@ApiPermission(name = "Job-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<PageResult<JobInfoVO>> listJobs(@RequestBody QueryJobInfoRequest request) {
Sort sort = Sort.by(Sort.Direction.ASC, "id");

View File

@ -26,6 +26,7 @@ import tech.powerjob.server.web.converter.NamespaceConverter;
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.NamespaceVO;
import javax.annotation.Resource;
@ -147,6 +148,22 @@ public class NamespaceController {
return ResultDTO.success(ret);
}
@PostMapping("/listAll")
@ApiPermission(name = "Namespace-ListAll", roleScope = RoleScope.NAMESPACE, requiredPermission = Permission.NONE)
public ResultDTO<List<NamespaceBaseVO>> listAll() {
// 数量应该不是很多先简单处理不查询精简对象
List<NamespaceDO> namespaceRepositoryAll = namespaceRepository.findAll();
List<NamespaceBaseVO> namespaceBaseVOList = namespaceRepositoryAll.stream().map(nd -> {
NamespaceBaseVO nv = new NamespaceBaseVO();
nv.setId(nd.getId());
nv.setCode(nd.getCode());
nv.setName(nd.getName());
nv.genFrontName();
return nv;
}).collect(Collectors.toList());
return ResultDTO.success(namespaceBaseVOList);
}
private void fillPermissionInfo(NamespaceDO namespaceDO, NamespaceVO namespaceVO) {
Long namespaceId = namespaceVO.getId();

View File

@ -12,6 +12,8 @@ import tech.powerjob.common.enums.InstanceStatus;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.common.constants.SwitchableStatus;
import tech.powerjob.server.common.module.WorkerInfo;
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
import tech.powerjob.server.persistence.remote.repository.InstanceInfoRepository;
import tech.powerjob.server.persistence.remote.repository.JobInfoRepository;
import tech.powerjob.server.remote.server.self.ServerInfoService;
@ -21,6 +23,7 @@ import tech.powerjob.server.web.response.WorkerStatusVO;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.TimeZone;
import java.util.stream.Collectors;
@ -36,6 +39,8 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class SystemInfoController {
private final AppInfoRepository appInfoRepository;
private final JobInfoRepository jobInfoRepository;
private final InstanceInfoRepository instanceInfoRepository;
@ -56,6 +61,14 @@ public class SystemInfoController {
SystemOverviewVO overview = new SystemOverviewVO();
Optional<AppInfoDO> appInfoOpt = appInfoRepository.findById(appId);
if (appInfoOpt.isPresent()) {
AppInfoDO appInfo = appInfoOpt.get();
overview.setAppId(appId);
overview.setAppName(appInfo.getAppName());
}
// 总任务数量
overview.setJobCount(jobInfoRepository.countByAppIdAndStatusNot(appId, SwitchableStatus.DELETED.getV()));
// 运行任务数
@ -69,7 +82,8 @@ public class SystemInfoController {
// 服务器时间
overview.setServerTime(DateFormatUtils.format(new Date(), OmsConstant.TIME_PATTERN));
overview.setServerInfo(serverInfoService.fetchServiceInfo());
overview.setWebServerInfo(serverInfoService.fetchCurrentServerInfo());
overview.setScheduleServerInfo(serverInfoService.fetchAppServerInfo(appId));
return ResultDTO.success(overview);
}

View File

@ -1,26 +1,28 @@
package tech.powerjob.server.web.controller;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import tech.powerjob.common.request.http.SaveWorkflowNodeRequest;
import tech.powerjob.common.request.http.SaveWorkflowRequest;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.common.constants.SwitchableStatus;
import tech.powerjob.server.core.workflow.WorkflowService;
import tech.powerjob.server.persistence.PageResult;
import tech.powerjob.server.persistence.remote.model.WorkflowInfoDO;
import tech.powerjob.server.persistence.remote.model.WorkflowNodeInfoDO;
import tech.powerjob.server.persistence.remote.repository.WorkflowInfoRepository;
import tech.powerjob.server.core.workflow.WorkflowService;
import tech.powerjob.server.web.request.QueryWorkflowInfoRequest;
import tech.powerjob.server.web.response.WorkflowInfoVO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.text.ParseException;
import java.util.List;
import java.util.function.LongToDoubleFunction;
import java.util.stream.Collectors;
/**
@ -40,34 +42,40 @@ public class WorkflowController {
private WorkflowInfoRepository workflowInfoRepository;
@PostMapping("/save")
@ApiPermission(name = "Workflow-Save", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Long> save(@RequestBody SaveWorkflowRequest req) throws ParseException {
return ResultDTO.success(workflowService.saveWorkflow(req));
}
@PostMapping("/copy")
@ApiPermission(name = "Workflow-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Long> copy(Long workflowId, Long appId) {
return ResultDTO.success(workflowService.copyWorkflow(workflowId,appId));
}
@GetMapping("/disable")
@ApiPermission(name = "Workflow-Disable", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> disableWorkflow(Long workflowId, Long appId) {
workflowService.disableWorkflow(workflowId, appId);
return ResultDTO.success(null);
}
@GetMapping("/enable")
@ApiPermission(name = "Workflow-Enable", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> enableWorkflow(Long workflowId, Long appId) {
workflowService.enableWorkflow(workflowId, appId);
return ResultDTO.success(null);
}
@GetMapping("/delete")
@ApiPermission(name = "Workflow-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> deleteWorkflow(Long workflowId, Long appId) {
workflowService.deleteWorkflow(workflowId, appId);
return ResultDTO.success(null);
}
@PostMapping("/list")
@ApiPermission(name = "Workflow-List", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<PageResult<WorkflowInfoVO>> list(@RequestBody QueryWorkflowInfoRequest req) {
Sort sort = Sort.by(Sort.Direction.DESC, "gmtCreate");
@ -89,6 +97,7 @@ public class WorkflowController {
}
@GetMapping("/run")
@ApiPermission(name = "Workflow-Run", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Long> runWorkflow(Long workflowId, Long appId,
@RequestParam(required = false,defaultValue = "0") Long delay,
@RequestParam(required = false) String initParams
@ -97,12 +106,14 @@ public class WorkflowController {
}
@GetMapping("/fetch")
@ApiPermission(name = "Workflow-Fetch", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<WorkflowInfoVO> fetchWorkflow(Long workflowId, Long appId) {
WorkflowInfoDO workflowInfoDO = workflowService.fetchWorkflow(workflowId, appId);
return ResultDTO.success(WorkflowInfoVO.from(workflowInfoDO));
}
@PostMapping("/saveNode")
@ApiPermission(name = "Workflow-SaveNode", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<List<WorkflowNodeInfoDO>> addWorkflowNode(@RequestBody List<SaveWorkflowNodeRequest> request) {
return ResultDTO.success(workflowService.saveWorkflowNode(request));
}

View File

@ -2,6 +2,9 @@ package tech.powerjob.server.web.controller;
import tech.powerjob.common.enums.WorkflowInstanceStatus;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.persistence.PageResult;
import tech.powerjob.server.persistence.remote.model.WorkflowInstanceInfoDO;
import tech.powerjob.server.persistence.remote.repository.WorkflowInstanceInfoRepository;
@ -38,18 +41,21 @@ public class WorkflowInstanceController {
private WorkflowInstanceInfoRepository workflowInstanceInfoRepository;
@GetMapping("/stop")
@ApiPermission(name = "WorkflowInstance-Stop", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> stopWfInstance(Long wfInstanceId, Long appId) {
workflowInstanceService.stopWorkflowInstanceEntrance(wfInstanceId, appId);
return ResultDTO.success(null);
}
@RequestMapping("/retry")
@ApiPermission(name = "WorkflowInstance-Retry", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> retryWfInstance(Long wfInstanceId, Long appId) {
workflowInstanceService.retryWorkflowInstance(wfInstanceId, appId);
return ResultDTO.success(null);
}
@RequestMapping("/markNodeAsSuccess")
@ApiPermission(name = "WorkflowInstance-MarkNodeAsSuccess", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Void> markNodeAsSuccess(Long wfInstanceId, Long appId, Long nodeId) {
workflowInstanceService.markNodeAsSuccess(appId, wfInstanceId, nodeId);
return ResultDTO.success(null);
@ -57,12 +63,14 @@ public class WorkflowInstanceController {
@GetMapping("/info")
@ApiPermission(name = "WorkflowInstance-Info", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<WorkflowInstanceInfoVO> getInfo(Long wfInstanceId, Long appId) {
WorkflowInstanceInfoDO wfInstanceDO = workflowInstanceService.fetchWfInstance(wfInstanceId, appId);
return ResultDTO.success(WorkflowInstanceInfoVO.from(wfInstanceDO, cacheService.getWorkflowName(wfInstanceDO.getWorkflowId())));
}
@PostMapping("/list")
@ApiPermission(name = "WorkflowInstance-List", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<PageResult<WorkflowInstanceInfoVO>> listWfInstance(@RequestBody QueryWorkflowInstanceRequest req) {
Sort sort = Sort.by(Sort.Direction.DESC, "gmtModified");
PageRequest pageable = PageRequest.of(req.getIndex(), req.getPageSize(), sort);

View File

@ -19,6 +19,8 @@ public class AppInfoVO implements Serializable {
private String appName;
private Long namespaceId;
/**
* 描述
*/

View File

@ -0,0 +1,38 @@
package tech.powerjob.server.web.response;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* namespace 基本 VO 对象用于列表渲染
*
* @author tjq
* @since 2024/2/12
*/
@Getter
@Setter
public class NamespaceBaseVO implements Serializable {
protected Long id;
/**
* 空间唯一标识
*/
protected String code;
/**
* 空间名称比如中文描述XX部门XX空间
*/
protected String name;
/**
* 前端名称拼接 code + name更容易辨认
*/
protected String frontName;
public void genFrontName() {
frontName = String.format("%s(%s)", name, code);
}
}

View File

@ -5,7 +5,6 @@ import lombok.Setter;
import lombok.ToString;
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
import java.io.Serializable;
import java.util.Date;
/**
@ -17,19 +16,7 @@ import java.util.Date;
@Getter
@Setter
@ToString
public class NamespaceVO implements Serializable {
private Long id;
/**
* 空间唯一标识
*/
private String code;
/**
* 空间名称比如中文描述XX部门XX空间
*/
private String name;
public class NamespaceVO extends NamespaceBaseVO {
private String dept;
private String tags;

View File

@ -1,8 +1,6 @@
package tech.powerjob.server.web.response;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import tech.powerjob.server.common.module.ServerInfo;
/**
@ -14,6 +12,10 @@ import tech.powerjob.server.common.module.ServerInfo;
@Data
public class SystemOverviewVO {
private Long appId;
private String appName;
private long jobCount;
private long runningInstanceCount;
private long failedInstanceCount;
@ -26,5 +28,12 @@ public class SystemOverviewVO {
*/
private String serverTime;
private ServerInfo serverInfo;
/**
* 处理当前 WEB 服务的 server 信息
*/
private ServerInfo webServerInfo;
/**
* 调度服务器信息
*/
private ServerInfo scheduleServerInfo;
}