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 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"),
|
ILLEGAL_ARGS_ERROR("-501", "ILLEGAL_ARGS_ERROR"),
|
||||||
|
/**
|
||||||
|
* 不允许操作
|
||||||
|
*/
|
||||||
|
OPERATION_NOT_PERMITTED("-502", "OPERATION_NOT_PERMITTED"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OPENAPI 错误码号段 -10XX
|
* OPENAPI 错误码号段 -10XX
|
||||||
|
@ -35,7 +35,7 @@ public class ModifyOrCreateDynamicPermission implements DynamicPermissionPlugin
|
|||||||
return Permission.NONE;
|
return Permission.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Permission.WRITE;
|
return Permission.SU;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[ModifyOrCreateDynamicPermission] check permission failed, please fix the bug!!!", e);
|
log.error("[ModifyOrCreateDynamicPermission] check permission failed, please fix the bug!!!", e);
|
||||||
}
|
}
|
||||||
|
@ -40,16 +40,22 @@ public class NewSystemInitializer implements CommandLineRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) throws Exception {
|
public void run(String... args) throws Exception {
|
||||||
initSystemAdmin();
|
SystemInitializerContext context = new SystemInitializerContext();
|
||||||
initDefaultNamespace();
|
initSystemAdmin(context);
|
||||||
|
initDefaultNamespace(context);
|
||||||
|
initTestEnvironment(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSystemAdmin() {
|
private void initSystemAdmin(SystemInitializerContext context) {
|
||||||
clusterInit(SystemInitializeService.GOAL_INIT_ADMIN, Void -> systemInitializeService.initAdmin());
|
clusterInit(SystemInitializeService.GOAL_INIT_ADMIN, Void -> systemInitializeService.initAdmin(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDefaultNamespace() {
|
private void initDefaultNamespace(SystemInitializerContext context) {
|
||||||
clusterInit(SystemInitializeService.GOAL_INIT_NAMESPACE, Void -> systemInitializeService.initNamespace());
|
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) {
|
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_ADMIN = "goal_init_admin";
|
||||||
String GOAL_INIT_NAMESPACE = "goal_init_namespace";
|
String GOAL_INIT_NAMESPACE = "goal_init_namespace";
|
||||||
|
String GOAL_INIT_TEST_ENV = "goal_init_test_env";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化超级管理员
|
* 初始化超级管理员
|
||||||
*/
|
*/
|
||||||
void initAdmin();
|
void initAdmin(SystemInitializerContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化 namespace
|
* 初始化 namespace
|
||||||
*/
|
*/
|
||||||
void initNamespace();
|
void initNamespace(SystemInitializerContext context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化测试环境
|
||||||
|
*/
|
||||||
|
void initTestEnvironment(SystemInitializerContext context);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package tech.powerjob.server.initializer;
|
package tech.powerjob.server.initializer;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import tech.powerjob.common.PowerJobDKey;
|
||||||
import tech.powerjob.common.serialize.JsonUtils;
|
import tech.powerjob.common.serialize.JsonUtils;
|
||||||
import tech.powerjob.server.auth.PowerJobUser;
|
import tech.powerjob.server.auth.PowerJobUser;
|
||||||
import tech.powerjob.server.auth.Role;
|
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.LoginRequest;
|
||||||
import tech.powerjob.server.auth.service.login.PowerJobLoginService;
|
import tech.powerjob.server.auth.service.login.PowerJobLoginService;
|
||||||
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
|
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.NamespaceDO;
|
||||||
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
|
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.ModifyNamespaceRequest;
|
||||||
import tech.powerjob.server.web.request.ModifyUserInfoRequest;
|
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.NamespaceWebService;
|
||||||
import tech.powerjob.server.web.service.PwjbUserWebService;
|
import tech.powerjob.server.web.service.PwjbUserWebService;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.transaction.Transactional;
|
import javax.transaction.Transactional;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化 PowerJob 首次部署相关的内容
|
* 初始化 PowerJob 首次部署相关的内容
|
||||||
@ -39,6 +48,8 @@ public class SystemInitializeServiceImpl implements SystemInitializeService {
|
|||||||
@Value("${oms.auth.initiliaze.admin.password:#{null}}")
|
@Value("${oms.auth.initiliaze.admin.password:#{null}}")
|
||||||
private String defaultAdminPassword;
|
private String defaultAdminPassword;
|
||||||
@Resource
|
@Resource
|
||||||
|
private AppWebService appWebService;
|
||||||
|
@Resource
|
||||||
private PwjbUserWebService pwjbUserWebService;
|
private PwjbUserWebService pwjbUserWebService;
|
||||||
@Resource
|
@Resource
|
||||||
private NamespaceWebService namespaceWebService;
|
private NamespaceWebService namespaceWebService;
|
||||||
@ -54,36 +65,18 @@ public class SystemInitializeServiceImpl implements SystemInitializeService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackOn = Exception.class)
|
@Transactional(rollbackOn = Exception.class)
|
||||||
public void initAdmin() {
|
public void initAdmin(SystemInitializerContext context) {
|
||||||
|
|
||||||
String username = SYSTEM_ADMIN_NAME;
|
String username = SYSTEM_ADMIN_NAME;
|
||||||
String password = StringUtils.isEmpty(defaultAdminPassword) ? RandomStringUtils.randomAlphabetic(8) : defaultAdminPassword;
|
String password = StringUtils.isEmpty(defaultAdminPassword) ? RandomStringUtils.randomAlphabetic(8) : defaultAdminPassword;
|
||||||
|
|
||||||
// STEP1: 创建 PWJB 用户
|
// 创建用户
|
||||||
ModifyUserInfoRequest createUser = new ModifyUserInfoRequest();
|
PowerJobUser powerJobUser = createUser(username, password, true);
|
||||||
createUser.setUsername(username);
|
context.setAdminUserId(powerJobUser.getId());
|
||||||
createUser.setNick(username);
|
|
||||||
createUser.setPassword(password);
|
|
||||||
|
|
||||||
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);
|
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 密码
|
// 循环10遍,强提醒用户,第一次使用必须更改 admin 密码
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
@ -93,13 +86,99 @@ public class SystemInitializeServiceImpl implements SystemInitializeService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackOn = Exception.class)
|
@Transactional(rollbackOn = Exception.class)
|
||||||
public void initNamespace() {
|
public void initNamespace(SystemInitializerContext context) {
|
||||||
ModifyNamespaceRequest saveNamespaceReq = new ModifyNamespaceRequest();
|
ModifyNamespaceRequest saveNamespaceReq = new ModifyNamespaceRequest();
|
||||||
saveNamespaceReq.setName(SYSTEM_DEFAULT_NAMESPACE);
|
saveNamespaceReq.setName(SYSTEM_DEFAULT_NAMESPACE);
|
||||||
saveNamespaceReq.setCode(SYSTEM_DEFAULT_NAMESPACE);
|
saveNamespaceReq.setCode(SYSTEM_DEFAULT_NAMESPACE);
|
||||||
|
|
||||||
log.info("[SystemInitializeService] create default namespace by request: {}", saveNamespaceReq);
|
log.info("[SystemInitializeService] create default namespace by request: {}", saveNamespaceReq);
|
||||||
NamespaceDO savedNamespaceDO = namespaceWebService.save(saveNamespaceReq);
|
NamespaceDO savedNamespaceDO = namespaceWebService.save(saveNamespaceReq);
|
||||||
|
context.setDefaultNamespaceId(savedNamespaceDO.getId());
|
||||||
log.info("[SystemInitializeService] create default namespace successfully: {}", savedNamespaceDO);
|
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.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
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.beans.BeanUtils;
|
||||||
import org.springframework.data.domain.Page;
|
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.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
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.response.ResultDTO;
|
||||||
import tech.powerjob.common.serialize.JsonUtils;
|
import tech.powerjob.common.serialize.JsonUtils;
|
||||||
import tech.powerjob.common.utils.CommonUtils;
|
import tech.powerjob.common.utils.CommonUtils;
|
||||||
import tech.powerjob.server.auth.LoginUserHolder;
|
|
||||||
import tech.powerjob.server.auth.Permission;
|
import tech.powerjob.server.auth.Permission;
|
||||||
import tech.powerjob.server.auth.Role;
|
import tech.powerjob.server.auth.Role;
|
||||||
import tech.powerjob.server.auth.RoleScope;
|
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.ModifyOrCreateDynamicPermission;
|
||||||
import tech.powerjob.server.auth.plugin.SaveAppGrantPermissionPlugin;
|
import tech.powerjob.server.auth.plugin.SaveAppGrantPermissionPlugin;
|
||||||
import tech.powerjob.server.auth.service.WebAuthService;
|
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.core.service.AppInfoService;
|
||||||
import tech.powerjob.server.persistence.PageResult;
|
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.AppInfoDO;
|
||||||
import tech.powerjob.server.persistence.remote.model.NamespaceDO;
|
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.converter.NamespaceConverter;
|
||||||
import tech.powerjob.server.web.request.AppAssertRequest;
|
import tech.powerjob.server.web.request.AppAssertRequest;
|
||||||
import tech.powerjob.server.web.request.ComponentUserRoleInfo;
|
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.AppInfoVO;
|
||||||
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
import tech.powerjob.server.web.response.NamespaceBaseVO;
|
||||||
import tech.powerjob.server.web.response.UserBaseVO;
|
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.NamespaceWebService;
|
||||||
import tech.powerjob.server.web.service.UserWebService;
|
import tech.powerjob.server.web.service.UserWebService;
|
||||||
|
|
||||||
import javax.persistence.criteria.Predicate;
|
import java.util.List;
|
||||||
import java.util.*;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,62 +56,20 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AppInfoController {
|
public class AppInfoController {
|
||||||
|
|
||||||
|
private final AppWebService appWebService;
|
||||||
private final WebAuthService webAuthService;
|
private final WebAuthService webAuthService;
|
||||||
|
|
||||||
private final UserWebService userWebService;
|
private final UserWebService userWebService;
|
||||||
|
|
||||||
private final AppInfoService appInfoService;
|
private final AppInfoService appInfoService;
|
||||||
private final AppInfoRepository appInfoRepository;
|
|
||||||
|
|
||||||
private final NamespaceWebService namespaceWebService;
|
private final NamespaceWebService namespaceWebService;
|
||||||
|
|
||||||
private final WorkerClusterQueryService workerClusterQueryService;
|
|
||||||
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
@ApiPermission(name = "App-Save", roleScope = RoleScope.APP, dynamicPermissionPlugin = ModifyOrCreateDynamicPermission.class, grandPermissionPlugin = SaveAppGrantPermissionPlugin.class)
|
@ApiPermission(name = "App-Save", roleScope = RoleScope.APP, dynamicPermissionPlugin = ModifyOrCreateDynamicPermission.class, grandPermissionPlugin = SaveAppGrantPermissionPlugin.class)
|
||||||
public ResultDTO<AppInfoVO> saveAppInfo(@RequestBody ModifyAppInfoRequest req) {
|
public ResultDTO<AppInfoVO> saveAppInfo(@RequestBody ModifyAppInfoRequest req) {
|
||||||
|
|
||||||
// 根据 ns code 填充 namespaceId(自动化创建过程中,固定的 namespace-code 对用户更友好)
|
AppInfoDO savedAppInfo = appWebService.save(req);
|
||||||
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 ResultDTO.success(convert(Lists.newArrayList(savedAppInfo), false).get(0));
|
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)
|
@ApiPermission(name = "App-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.SU)
|
||||||
public ResultDTO<Void> deleteApp(Long appId) {
|
public ResultDTO<Void> deleteApp(Long appId) {
|
||||||
|
|
||||||
log.warn("[AppInfoController] try to delete app: {}", appId);
|
appWebService.delete(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);
|
|
||||||
return ResultDTO.success(null);
|
return ResultDTO.success(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,54 +86,7 @@ public class AppInfoController {
|
|||||||
@ApiPermission(name = "App-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE)
|
@ApiPermission(name = "App-List", roleScope = RoleScope.APP, requiredPermission = Permission.NONE)
|
||||||
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) {
|
public ResultDTO<PageResult<AppInfoVO>> listAppInfoByQuery(@RequestBody QueryAppInfoRequest queryAppInfoRequest) {
|
||||||
|
|
||||||
Pageable pageable = PageRequest.of(queryAppInfoRequest.getIndex(), queryAppInfoRequest.getPageSize());
|
Page<AppInfoDO> pageAppInfoResult = appWebService.list(queryAppInfoRequest);
|
||||||
|
|
||||||
// 相关权限(先查处关联 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);
|
|
||||||
|
|
||||||
PageResult<AppInfoVO> pageRet = new PageResult<>(pageAppInfoResult);
|
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