mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
feat: support test mode
This commit is contained in:
parent
5d82b7cc5c
commit
a6de80220a
@ -64,6 +64,10 @@ public class PowerJobDKey {
|
||||
|
||||
public static final String WORKER_RUNTIME_SWAP_TASK_SCHEDULE_INTERVAL_MS = "powerjob.worker.swap.scan-interval";
|
||||
|
||||
public static final String SERVER_TEST_ACCOUNT_USERNAME = "powerjob.server.test-accounts";
|
||||
public static final String SERVER_TEST_ACCOUNT_USERNAME = "powerjob.server.test.user.accounts";
|
||||
public static final String SERVER_TEST_ACCOUNT_PASSWORD = "powerjob.server.test.user.password";
|
||||
public static final String SERVER_TEST_APP_USERNAME = "powerjob.server.test.app.name";
|
||||
public static final String SERVER_TEST_APP_PASSWORD = "powerjob.server.test.app.password";
|
||||
public static final String SERVER_TEST_MODE = "powerjob.server.test.mode";
|
||||
|
||||
}
|
||||
|
@ -53,6 +53,10 @@ public enum ErrorCodes {
|
||||
* 非法参数
|
||||
*/
|
||||
ILLEGAL_ARGS_ERROR("-501", "ILLEGAL_ARGS_ERROR"),
|
||||
/**
|
||||
* 不允许操作
|
||||
*/
|
||||
OPERATION_NOT_PERMITTED("-502", "OPERATION_NOT_PERMITTED"),
|
||||
|
||||
/**
|
||||
* OPENAPI 错误码号段 -10XX
|
||||
|
@ -35,7 +35,7 @@ public class ModifyOrCreateDynamicPermission implements DynamicPermissionPlugin
|
||||
return Permission.NONE;
|
||||
}
|
||||
|
||||
return Permission.WRITE;
|
||||
return Permission.SU;
|
||||
} catch (Exception e) {
|
||||
log.error("[ModifyOrCreateDynamicPermission] check permission failed, please fix the bug!!!", e);
|
||||
}
|
||||
|
@ -40,16 +40,22 @@ public class NewSystemInitializer implements CommandLineRunner {
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
initSystemAdmin();
|
||||
initDefaultNamespace();
|
||||
SystemInitializerContext context = new SystemInitializerContext();
|
||||
initSystemAdmin(context);
|
||||
initDefaultNamespace(context);
|
||||
initTestEnvironment(context);
|
||||
}
|
||||
|
||||
private void initSystemAdmin() {
|
||||
clusterInit(SystemInitializeService.GOAL_INIT_ADMIN, Void -> systemInitializeService.initAdmin());
|
||||
private void initSystemAdmin(SystemInitializerContext context) {
|
||||
clusterInit(SystemInitializeService.GOAL_INIT_ADMIN, Void -> systemInitializeService.initAdmin(context));
|
||||
}
|
||||
|
||||
private void initDefaultNamespace() {
|
||||
clusterInit(SystemInitializeService.GOAL_INIT_NAMESPACE, Void -> systemInitializeService.initNamespace());
|
||||
private void initDefaultNamespace(SystemInitializerContext context) {
|
||||
clusterInit(SystemInitializeService.GOAL_INIT_NAMESPACE, Void -> systemInitializeService.initNamespace(context));
|
||||
}
|
||||
|
||||
private void initTestEnvironment(SystemInitializerContext context) {
|
||||
clusterInit(SystemInitializeService.GOAL_INIT_TEST_ENV, Void -> systemInitializeService.initTestEnvironment(context));
|
||||
}
|
||||
|
||||
private void clusterInit(String name, Consumer<Void> initFunc) {
|
||||
|
@ -10,15 +10,21 @@ public interface SystemInitializeService {
|
||||
|
||||
String GOAL_INIT_ADMIN = "goal_init_admin";
|
||||
String GOAL_INIT_NAMESPACE = "goal_init_namespace";
|
||||
String GOAL_INIT_TEST_ENV = "goal_init_test_env";
|
||||
|
||||
|
||||
/**
|
||||
* 初始化超级管理员
|
||||
*/
|
||||
void initAdmin();
|
||||
void initAdmin(SystemInitializerContext context);
|
||||
|
||||
/**
|
||||
* 初始化 namespace
|
||||
*/
|
||||
void initNamespace();
|
||||
void initNamespace(SystemInitializerContext context);
|
||||
|
||||
/**
|
||||
* 初始化测试环境
|
||||
*/
|
||||
void initTestEnvironment(SystemInitializerContext context);
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package tech.powerjob.server.initializer;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.PowerJobDKey;
|
||||
import tech.powerjob.common.serialize.JsonUtils;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
@ -14,16 +16,23 @@ import tech.powerjob.server.auth.common.AuthConstants;
|
||||
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.common.SJ;
|
||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
||||
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
import tech.powerjob.server.web.request.ModifyAppInfoRequest;
|
||||
import tech.powerjob.server.web.request.ModifyNamespaceRequest;
|
||||
import tech.powerjob.server.web.request.ModifyUserInfoRequest;
|
||||
import tech.powerjob.server.web.service.AppWebService;
|
||||
import tech.powerjob.server.web.service.NamespaceWebService;
|
||||
import tech.powerjob.server.web.service.PwjbUserWebService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 初始化 PowerJob 首次部署相关的内容
|
||||
@ -39,6 +48,8 @@ public class SystemInitializeServiceImpl implements SystemInitializeService {
|
||||
@Value("${oms.auth.initiliaze.admin.password:#{null}}")
|
||||
private String defaultAdminPassword;
|
||||
@Resource
|
||||
private AppWebService appWebService;
|
||||
@Resource
|
||||
private PwjbUserWebService pwjbUserWebService;
|
||||
@Resource
|
||||
private NamespaceWebService namespaceWebService;
|
||||
@ -54,36 +65,18 @@ public class SystemInitializeServiceImpl implements SystemInitializeService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
public void initAdmin() {
|
||||
public void initAdmin(SystemInitializerContext context) {
|
||||
|
||||
String username = SYSTEM_ADMIN_NAME;
|
||||
String password = StringUtils.isEmpty(defaultAdminPassword) ? RandomStringUtils.randomAlphabetic(8) : defaultAdminPassword;
|
||||
|
||||
// STEP1: 创建 PWJB 用户
|
||||
ModifyUserInfoRequest createUser = new ModifyUserInfoRequest();
|
||||
createUser.setUsername(username);
|
||||
createUser.setNick(username);
|
||||
createUser.setPassword(password);
|
||||
// 创建用户
|
||||
PowerJobUser powerJobUser = createUser(username, password, true);
|
||||
context.setAdminUserId(powerJobUser.getId());
|
||||
|
||||
log.info("[SystemInitializeService] [S1] create default PWJB user by request: {}", createUser);
|
||||
PwjbUserInfoDO savedPwjbUser = pwjbUserWebService.save(createUser);
|
||||
log.info("[SystemInitializeService] [S1] create default PWJB user successfully: {}", savedPwjbUser);
|
||||
|
||||
Map<String, Object> params = Maps.newHashMap();
|
||||
params.put(AuthConstants.PARAM_KEY_USERNAME, username);
|
||||
params.put(AuthConstants.PARAM_KEY_PASSWORD, password);
|
||||
|
||||
// STEP2: 创建 USER 对象
|
||||
LoginRequest loginRequest = new LoginRequest()
|
||||
.setLoginType(AuthConstants.ACCOUNT_TYPE_POWER_JOB)
|
||||
.setOriginParams(JsonUtils.toJSONString(params));
|
||||
log.info("[SystemInitializeService] [S2] createPowerJobUser user by request: {}", loginRequest);
|
||||
PowerJobUser powerJobUser = powerJobLoginService.doLogin(loginRequest);
|
||||
log.info("[SystemInitializeService] [S2] createPowerJobUser successfully: {}", powerJobUser);
|
||||
|
||||
// STEP3: 授予全局管理员权限
|
||||
// 授予全局管理员权限
|
||||
powerJobPermissionService.grantRole(RoleScope.GLOBAL, AuthConstants.GLOBAL_ADMIN_TARGET_ID, powerJobUser.getId(), Role.ADMIN, null);
|
||||
log.info("[SystemInitializeService] [S3] GRANT ADMIN successfully!");
|
||||
log.info("[SystemInitializeService] GRANT ADMIN to user[{}] successfully!", powerJobUser);
|
||||
|
||||
// 循环10遍,强提醒用户,第一次使用必须更改 admin 密码
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@ -93,13 +86,99 @@ public class SystemInitializeServiceImpl implements SystemInitializeService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
public void initNamespace() {
|
||||
public void initNamespace(SystemInitializerContext context) {
|
||||
ModifyNamespaceRequest saveNamespaceReq = new ModifyNamespaceRequest();
|
||||
saveNamespaceReq.setName(SYSTEM_DEFAULT_NAMESPACE);
|
||||
saveNamespaceReq.setCode(SYSTEM_DEFAULT_NAMESPACE);
|
||||
|
||||
log.info("[SystemInitializeService] create default namespace by request: {}", saveNamespaceReq);
|
||||
NamespaceDO savedNamespaceDO = namespaceWebService.save(saveNamespaceReq);
|
||||
context.setDefaultNamespaceId(savedNamespaceDO.getId());
|
||||
log.info("[SystemInitializeService] create default namespace successfully: {}", savedNamespaceDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackOn = Exception.class)
|
||||
public void initTestEnvironment(SystemInitializerContext context) {
|
||||
String testMode = System.getProperty(PowerJobDKey.SERVER_TEST_MODE);
|
||||
if (!Boolean.TRUE.toString().equalsIgnoreCase(testMode)) {
|
||||
return;
|
||||
}
|
||||
log.warn("[SystemInitializeService] [TestEnv] Detect test mode and start initializing the test environment");
|
||||
|
||||
// 初始化测试账号
|
||||
String testAccountsStr = System.getProperty(PowerJobDKey.SERVER_TEST_ACCOUNT_USERNAME, "powerjob");
|
||||
String testAccountsPwd = System.getProperty(PowerJobDKey.SERVER_TEST_ACCOUNT_PASSWORD, "powerjob");
|
||||
List<String> testAccounts = Lists.newArrayList(SJ.COMMA_SPLITTER.split(testAccountsStr));
|
||||
|
||||
List<PowerJobUser> testUsers = testAccounts.stream().map(un -> createUser(un, testAccountsPwd, false)).collect(Collectors.toList());
|
||||
List<Long> testUserIds = testUsers.stream().map(PowerJobUser::getId).collect(Collectors.toList());
|
||||
|
||||
log.info("[SystemInitializeService] [TestEnv] test user: {}", testUsers);
|
||||
|
||||
String testAppName = System.getProperty(PowerJobDKey.SERVER_TEST_APP_USERNAME, "powerjob-worker-samples");
|
||||
String testAppPassword = System.getProperty(PowerJobDKey.SERVER_TEST_APP_PASSWORD, "powerjob123");
|
||||
|
||||
AppInfoDO testApp = createApp(testAppName, testAppPassword, context.getDefaultNamespaceId(), testUserIds);
|
||||
log.info("[SystemInitializeService] [TestEnv] test app: {}", testApp);
|
||||
}
|
||||
|
||||
private PowerJobUser createUser(String username, String password, boolean allowedChangePwd) {
|
||||
// STEP1: 创建 PWJB 用户
|
||||
ModifyUserInfoRequest createUser = new ModifyUserInfoRequest();
|
||||
createUser.setUsername(username);
|
||||
createUser.setNick(username);
|
||||
createUser.setPassword(password);
|
||||
|
||||
if (!allowedChangePwd) {
|
||||
Map<String, Object> extra = Maps.newHashMap();
|
||||
extra.put("allowedChangePwd", false);
|
||||
createUser.setExtra(JsonUtils.toJSONString(extra));
|
||||
}
|
||||
|
||||
log.info("[SystemInitializeService] [username:{}] create PWJB user by request: {}", username, createUser);
|
||||
PwjbUserInfoDO savedPwjbUser = pwjbUserWebService.save(createUser);
|
||||
log.info("[SystemInitializeService] [username:{}] create PWJB user successfully: {}", username, savedPwjbUser);
|
||||
|
||||
Map<String, Object> params = Maps.newHashMap();
|
||||
params.put(AuthConstants.PARAM_KEY_USERNAME, username);
|
||||
params.put(AuthConstants.PARAM_KEY_PASSWORD, password);
|
||||
|
||||
// STEP2: 创建 USER 对象
|
||||
LoginRequest loginRequest = new LoginRequest()
|
||||
.setLoginType(AuthConstants.ACCOUNT_TYPE_POWER_JOB)
|
||||
.setOriginParams(JsonUtils.toJSONString(params));
|
||||
log.info("[SystemInitializeService] [username:{}] create PowerJobUser by request: {}", username, loginRequest);
|
||||
PowerJobUser powerJobUser = powerJobLoginService.doLogin(loginRequest);
|
||||
log.info("[SystemInitializeService] [username:{}] create PowerJobUser successfully: {}", username, powerJobUser);
|
||||
return powerJobUser;
|
||||
}
|
||||
|
||||
private AppInfoDO createApp(String appName, String password, Long namespaceId, List<Long> developers) {
|
||||
ModifyAppInfoRequest modifyAppInfoRequest = new ModifyAppInfoRequest();
|
||||
|
||||
modifyAppInfoRequest.setAppName(appName);
|
||||
modifyAppInfoRequest.setTitle(appName);
|
||||
|
||||
modifyAppInfoRequest.setPassword(password);
|
||||
modifyAppInfoRequest.setNamespaceId(namespaceId);
|
||||
|
||||
modifyAppInfoRequest.setTags("test_app");
|
||||
|
||||
// 禁用靠密码成为管理员
|
||||
Map<String, Object> extra = Maps.newHashMap();
|
||||
extra.put("allowedBecomeAdminByPassword", false);
|
||||
modifyAppInfoRequest.setExtra(JsonUtils.toJSONString(extra));
|
||||
|
||||
ComponentUserRoleInfo componentUserRoleInfo = new ComponentUserRoleInfo();
|
||||
modifyAppInfoRequest.setComponentUserRoleInfo(componentUserRoleInfo);
|
||||
|
||||
componentUserRoleInfo.setDeveloper(developers);
|
||||
|
||||
log.info("[SystemInitializeService] [app:{}] create App by request: {}", appName, modifyAppInfoRequest);
|
||||
AppInfoDO appInfoDO = appWebService.save(modifyAppInfoRequest);
|
||||
log.info("[SystemInitializeService] [app:{}] create App successfully: {}", appName, appInfoDO);
|
||||
|
||||
return appInfoDO;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package tech.powerjob.server.initializer;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统初始化上下文
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/12/8
|
||||
*/
|
||||
@Data
|
||||
public class SystemInitializerContext {
|
||||
|
||||
private Long adminUserId;
|
||||
|
||||
private Long defaultNamespaceId;
|
||||
|
||||
private Map<String, Object> extra;
|
||||
}
|
@ -2,27 +2,18 @@ package tech.powerjob.server.web.controller;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
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;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import tech.powerjob.common.enums.ErrorCodes;
|
||||
import tech.powerjob.common.exception.PowerJobExceptionLauncher;
|
||||
import tech.powerjob.common.response.ResultDTO;
|
||||
import tech.powerjob.common.serialize.JsonUtils;
|
||||
import tech.powerjob.common.utils.CommonUtils;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
import tech.powerjob.server.auth.Role;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
@ -31,14 +22,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.common.module.WorkerInfo;
|
||||
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.model.NamespaceDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
|
||||
import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
|
||||
import tech.powerjob.server.web.converter.NamespaceConverter;
|
||||
import tech.powerjob.server.web.request.AppAssertRequest;
|
||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
||||
@ -47,11 +34,13 @@ import tech.powerjob.server.web.request.QueryAppInfoRequest;
|
||||
import tech.powerjob.server.web.response.AppInfoVO;
|
||||
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||
import tech.powerjob.server.web.response.UserBaseVO;
|
||||
import tech.powerjob.server.web.service.AppWebService;
|
||||
import tech.powerjob.server.web.service.NamespaceWebService;
|
||||
import tech.powerjob.server.web.service.UserWebService;
|
||||
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -67,62 +56,20 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class AppInfoController {
|
||||
|
||||
private final AppWebService appWebService;
|
||||
private final WebAuthService webAuthService;
|
||||
|
||||
private final UserWebService userWebService;
|
||||
|
||||
private final AppInfoService appInfoService;
|
||||
private final AppInfoRepository appInfoRepository;
|
||||
|
||||
private final NamespaceWebService namespaceWebService;
|
||||
|
||||
private final WorkerClusterQueryService workerClusterQueryService;
|
||||
|
||||
@PostMapping("/save")
|
||||
@ApiPermission(name = "App-Save", roleScope = RoleScope.APP, dynamicPermissionPlugin = ModifyOrCreateDynamicPermission.class, grandPermissionPlugin = SaveAppGrantPermissionPlugin.class)
|
||||
public ResultDTO<AppInfoVO> saveAppInfo(@RequestBody ModifyAppInfoRequest req) {
|
||||
|
||||
// 根据 ns code 填充 namespaceId(自动化创建过程中,固定的 namespace-code 对用户更友好)
|
||||
if (StringUtils.isNotEmpty(req.getNamespaceCode())) {
|
||||
namespaceWebService.findByCode(req.getNamespaceCode()).ifPresent(x -> req.setNamespaceId(x.getId()));
|
||||
}
|
||||
|
||||
req.valid();
|
||||
AppInfoDO appInfoDO;
|
||||
|
||||
Long id = req.getId();
|
||||
if (id == null) {
|
||||
|
||||
// 前置校验,防止部分没加唯一索引的 DB 重复创建记录导致异常
|
||||
appInfoRepository.findByAppName(req.getAppName()).ifPresent(x -> new PowerJobExceptionLauncher(ErrorCodes.ILLEGAL_ARGS_ERROR, String.format("App[%s] already exists", req.getAppName())));
|
||||
|
||||
appInfoDO = new AppInfoDO();
|
||||
appInfoDO.setGmtCreate(new Date());
|
||||
appInfoDO.setCreator(LoginUserHolder.getUserId());
|
||||
|
||||
} else {
|
||||
appInfoDO = appInfoService.findById(id, false).orElseThrow(() -> new IllegalArgumentException("can't find appInfo by id:" + id));
|
||||
|
||||
// 不允许修改 appName
|
||||
if (!appInfoDO.getAppName().equalsIgnoreCase(req.getAppName())) {
|
||||
throw new IllegalArgumentException("NOT_ALLOW_CHANGE_THE_APP_NAME");
|
||||
}
|
||||
}
|
||||
|
||||
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.getUserId());
|
||||
|
||||
AppInfoDO savedAppInfo = appInfoService.save(appInfoDO);
|
||||
|
||||
// 重现授权
|
||||
webAuthService.processPermissionOnSave(RoleScope.APP, savedAppInfo.getId(), req.getComponentUserRoleInfo());
|
||||
AppInfoDO savedAppInfo = appWebService.save(req);
|
||||
|
||||
return ResultDTO.success(convert(Lists.newArrayList(savedAppInfo), false).get(0));
|
||||
}
|
||||
@ -131,15 +78,7 @@ public class AppInfoController {
|
||||
@ApiPermission(name = "App-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.SU)
|
||||
public ResultDTO<Void> deleteApp(Long appId) {
|
||||
|
||||
log.warn("[AppInfoController] try to delete app: {}", appId);
|
||||
|
||||
List<WorkerInfo> allAliveWorkers = workerClusterQueryService.getAllAliveWorkers(appId);
|
||||
if (CollectionUtils.isNotEmpty(allAliveWorkers)) {
|
||||
return ResultDTO.failed("Unable to delete apps with live workers, Please remove the worker dependency first!");
|
||||
}
|
||||
|
||||
appInfoService.deleteById(appId);
|
||||
log.warn("[AppInfoController] delete app[id={}] successfully!", appId);
|
||||
appWebService.delete(appId);
|
||||
return ResultDTO.success(null);
|
||||
}
|
||||
|
||||
@ -147,54 +86,7 @@ public class AppInfoController {
|
||||
@ApiPermission(name = "App-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE)
|
||||
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) {
|
||||
|
||||
Pageable pageable = PageRequest.of(queryAppInfoRequest.getIndex(), queryAppInfoRequest.getPageSize());
|
||||
|
||||
// 相关权限(先查处关联 ids)
|
||||
Set<Long> queryAppIds;
|
||||
Boolean showMyRelated = queryAppInfoRequest.getShowMyRelated();
|
||||
if (BooleanUtils.isTrue(showMyRelated)) {
|
||||
Set<Long> targetIds = Sets.newHashSet();
|
||||
webAuthService.fetchMyPermissionTargets(RoleScope.APP).values().forEach(targetIds::addAll);
|
||||
queryAppIds = targetIds;
|
||||
|
||||
if (CollectionUtils.isEmpty(queryAppIds)) {
|
||||
return ResultDTO.success(new PageResult<>());
|
||||
}
|
||||
|
||||
} else {
|
||||
queryAppIds = Collections.emptySet();
|
||||
}
|
||||
|
||||
Specification<AppInfoDO> specification = (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> predicates = Lists.newArrayList();
|
||||
|
||||
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.getAppNameLike())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("appName"), QueryConvertUtils.convertLikeParams(queryAppInfoRequest.getAppNameLike())));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(queryAppInfoRequest.getTagLike())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("tags"), QueryConvertUtils.convertLikeParams(queryAppInfoRequest.getTagLike())));
|
||||
}
|
||||
|
||||
if (!queryAppIds.isEmpty()) {
|
||||
predicates.add(criteriaBuilder.in(root.get("id")).value(queryAppIds));
|
||||
}
|
||||
|
||||
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
|
||||
};
|
||||
|
||||
Page<AppInfoDO> pageAppInfoResult = appInfoRepository.findAll(specification, pageable);
|
||||
Page<AppInfoDO> pageAppInfoResult = appWebService.list(queryAppInfoRequest);
|
||||
|
||||
PageResult<AppInfoVO> pageRet = new PageResult<>(pageAppInfoResult);
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
package tech.powerjob.server.web.service;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
|
||||
import tech.powerjob.server.web.request.ModifyAppInfoRequest;
|
||||
import tech.powerjob.server.web.request.QueryAppInfoRequest;
|
||||
|
||||
/**
|
||||
* AppWebService
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/12/8
|
||||
*/
|
||||
public interface AppWebService {
|
||||
|
||||
AppInfoDO save(ModifyAppInfoRequest request);
|
||||
|
||||
void delete(Long id);
|
||||
|
||||
Page<AppInfoDO> list(QueryAppInfoRequest queryAppInfoRequest);
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package tech.powerjob.server.web.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.enums.ErrorCodes;
|
||||
import tech.powerjob.common.exception.PowerJobException;
|
||||
import tech.powerjob.common.exception.PowerJobExceptionLauncher;
|
||||
import tech.powerjob.server.auth.LoginUserHolder;
|
||||
import tech.powerjob.server.auth.RoleScope;
|
||||
import tech.powerjob.server.auth.service.WebAuthService;
|
||||
import tech.powerjob.server.common.module.WorkerInfo;
|
||||
import tech.powerjob.server.core.service.AppInfoService;
|
||||
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.remote.worker.WorkerClusterQueryService;
|
||||
import tech.powerjob.server.web.request.ModifyAppInfoRequest;
|
||||
import tech.powerjob.server.web.request.QueryAppInfoRequest;
|
||||
import tech.powerjob.server.web.service.AppWebService;
|
||||
import tech.powerjob.server.web.service.NamespaceWebService;
|
||||
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* AppWebService
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2024/12/8
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class AppWebServiceImpl implements AppWebService {
|
||||
|
||||
private final WebAuthService webAuthService;
|
||||
|
||||
private final AppInfoService appInfoService;
|
||||
private final AppInfoRepository appInfoRepository;
|
||||
|
||||
private final NamespaceWebService namespaceWebService;
|
||||
|
||||
private final WorkerClusterQueryService workerClusterQueryService;
|
||||
|
||||
@Override
|
||||
public AppInfoDO save(ModifyAppInfoRequest req) {
|
||||
// 根据 ns code 填充 namespaceId(自动化创建过程中,固定的 namespace-code 对用户更友好)
|
||||
if (StringUtils.isNotEmpty(req.getNamespaceCode())) {
|
||||
namespaceWebService.findByCode(req.getNamespaceCode()).ifPresent(x -> req.setNamespaceId(x.getId()));
|
||||
}
|
||||
|
||||
req.valid();
|
||||
AppInfoDO appInfoDO;
|
||||
|
||||
Long id = req.getId();
|
||||
if (id == null) {
|
||||
|
||||
// 前置校验,防止部分没加唯一索引的 DB 重复创建记录导致异常
|
||||
appInfoRepository.findByAppName(req.getAppName()).ifPresent(x -> new PowerJobExceptionLauncher(ErrorCodes.ILLEGAL_ARGS_ERROR, String.format("App[%s] already exists", req.getAppName())));
|
||||
|
||||
appInfoDO = new AppInfoDO();
|
||||
appInfoDO.setGmtCreate(new Date());
|
||||
appInfoDO.setCreator(LoginUserHolder.getUserId());
|
||||
|
||||
} else {
|
||||
appInfoDO = appInfoService.findById(id, false).orElseThrow(() -> new IllegalArgumentException("can't find appInfo by id:" + id));
|
||||
|
||||
// 不允许修改 appName
|
||||
if (!appInfoDO.getAppName().equalsIgnoreCase(req.getAppName())) {
|
||||
throw new IllegalArgumentException("NOT_ALLOW_CHANGE_THE_APP_NAME");
|
||||
}
|
||||
}
|
||||
|
||||
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.getUserId());
|
||||
|
||||
AppInfoDO savedAppInfo = appInfoService.save(appInfoDO);
|
||||
|
||||
// 重现授权
|
||||
webAuthService.processPermissionOnSave(RoleScope.APP, savedAppInfo.getId(), req.getComponentUserRoleInfo());
|
||||
return savedAppInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Long appId) {
|
||||
log.warn("[AppInfoController] try to delete app: {}", appId);
|
||||
|
||||
List<WorkerInfo> allAliveWorkers = workerClusterQueryService.getAllAliveWorkers(appId);
|
||||
if (CollectionUtils.isNotEmpty(allAliveWorkers)) {
|
||||
throw new PowerJobException(ErrorCodes.OPERATION_NOT_PERMITTED, "Unable to delete apps with live workers, Please remove the worker dependency first!");
|
||||
}
|
||||
|
||||
appInfoService.deleteById(appId);
|
||||
log.warn("[AppInfoController] delete app[id={}] successfully!", appId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<AppInfoDO> list(QueryAppInfoRequest queryAppInfoRequest) {
|
||||
Pageable pageable = PageRequest.of(queryAppInfoRequest.getIndex(), queryAppInfoRequest.getPageSize());
|
||||
|
||||
// 相关权限(先查处关联 ids)
|
||||
Set<Long> queryAppIds;
|
||||
Boolean showMyRelated = queryAppInfoRequest.getShowMyRelated();
|
||||
if (BooleanUtils.isTrue(showMyRelated)) {
|
||||
Set<Long> targetIds = Sets.newHashSet();
|
||||
webAuthService.fetchMyPermissionTargets(RoleScope.APP).values().forEach(targetIds::addAll);
|
||||
queryAppIds = targetIds;
|
||||
|
||||
if (CollectionUtils.isEmpty(queryAppIds)) {
|
||||
return Page.empty();
|
||||
}
|
||||
|
||||
} else {
|
||||
queryAppIds = Collections.emptySet();
|
||||
}
|
||||
|
||||
Specification<AppInfoDO> specification = (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> predicates = Lists.newArrayList();
|
||||
|
||||
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.getAppNameLike())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("appName"), QueryConvertUtils.convertLikeParams(queryAppInfoRequest.getAppNameLike())));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(queryAppInfoRequest.getTagLike())) {
|
||||
predicates.add(criteriaBuilder.like(root.get("tags"), QueryConvertUtils.convertLikeParams(queryAppInfoRequest.getTagLike())));
|
||||
}
|
||||
|
||||
if (!queryAppIds.isEmpty()) {
|
||||
predicates.add(criteriaBuilder.in(root.get("id")).value(queryAppIds));
|
||||
}
|
||||
|
||||
return query.where(predicates.toArray(new Predicate[0])).getRestriction();
|
||||
};
|
||||
|
||||
return appInfoRepository.findAll(specification, pageable);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user