diff --git a/muyun-authorization/src/main/java/net/ximatai/muyun/authorization/AuthorizationService.java b/muyun-authorization/src/main/java/net/ximatai/muyun/authorization/AuthorizationService.java index d88a6051..ab535140 100644 --- a/muyun-authorization/src/main/java/net/ximatai/muyun/authorization/AuthorizationService.java +++ b/muyun-authorization/src/main/java/net/ximatai/muyun/authorization/AuthorizationService.java @@ -354,7 +354,7 @@ public String dictDataAuthToCondition(String userID, String module, String dictD .collect(Collectors.joining(","))); case "department" -> "%s='%s'".formatted(departmentColumn, departmentID); case "department_and_subordinates" -> "%s in (%s)" - .formatted(departmentColumn, departmentAndSubordinates(organizationID) + .formatted(departmentColumn, departmentAndSubordinates(departmentID) .stream().map("'%s'"::formatted) .collect(Collectors.joining(","))); case "supervision_region" -> "%s in (%s)" @@ -481,7 +481,7 @@ public Map getModuleByID(String moduleID) { @Override public Set getUserAvailableRoles(String userID) { - if (config.debug()) { + if (config.isTestMode()) { return loadRoles(userID); } else { return userToRoles.get(userID); diff --git a/muyun-boot/src/main/java/net/ximatai/muyun/MainApp.java b/muyun-boot/src/main/java/net/ximatai/muyun/MainApp.java index 9ad99f63..7f415ad2 100644 --- a/muyun-boot/src/main/java/net/ximatai/muyun/MainApp.java +++ b/muyun-boot/src/main/java/net/ximatai/muyun/MainApp.java @@ -5,7 +5,6 @@ import io.quarkus.runtime.annotations.QuarkusMain; import jakarta.inject.Inject; import net.ximatai.muyun.core.config.MuYunConfig; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,12 +16,9 @@ public class MainApp implements QuarkusApplication { @Inject MuYunConfig config; - @ConfigProperty(name = "quarkus.http.port") - int port; - @Override public int run(String... args) { - logger.info("MuYun started successfully! Running on port: {}. Debug mode is {}", port, config.debug() ? "OPEN" : "CLOSE"); + logger.info("PROFILE ON {}", config.profile()); Quarkus.waitForExit(); return 0; } diff --git a/muyun-boot/src/main/resources/application.yml b/muyun-boot/src/main/resources/application.yml index 18d5ff7b..d4b5f5b2 100644 --- a/muyun-boot/src/main/resources/application.yml +++ b/muyun-boot/src/main/resources/application.yml @@ -1,5 +1,4 @@ muyun: - debug: true super-user-id: 1 # 可以在环境变量里预先设置 MUYUN_USERNAME、MUYUN_PASSWORD 来确定初始化的用户名和密码 file-server: upload-path: /Users/liurui/Downloads/uploads diff --git a/muyun-boot/src/test/java/net/ximatai/muyun/test/plaform/TestDictController.java b/muyun-boot/src/test/java/net/ximatai/muyun/test/plaform/TestDictController.java index 0e00853d..6ee4c0e8 100644 --- a/muyun-boot/src/test/java/net/ximatai/muyun/test/plaform/TestDictController.java +++ b/muyun-boot/src/test/java/net/ximatai/muyun/test/plaform/TestDictController.java @@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @QuarkusTest @@ -164,6 +165,39 @@ void testDictCategoryAdd() { }); assertEquals(response.size(), 3); + DictTreeNode node = response.get(0); + assertNotNull(node.getValue()); + + given() + .header("userID", config.superUserId()) + .contentType("application/json") + .body( + Map.of( + "v_value", "031", + "v_name", "name31", + "pid", node.getId() + ) + ) + .when() + .post("%s/dict/update/%s/child/app_dict/create".formatted(base, "root1")) + .then() + .statusCode(200) + .extract() + .asString(); + + given() + .header("userID", config.superUserId()) + .get("%s/dict/tree/%s".formatted(base, "root1")) + .then() + .statusCode(200) + .extract() + .as(new TypeRef<>() { + }); + +// assertEquals(response.size(), 3); +// node = response.get(0); +// assertEquals(node.getChildren().size(), 1); +// assertNotNull(node.getValue()); List response2 = given() .header("userID", config.superUserId()) diff --git a/muyun-boot/src/test/resources/application.yml b/muyun-boot/src/test/resources/application.yml index 261f816b..0fb3e596 100644 --- a/muyun-boot/src/test/resources/application.yml +++ b/muyun-boot/src/test/resources/application.yml @@ -1,5 +1,4 @@ muyun: - debug: true super-user-id: 1 quarkus: diff --git a/muyun-core/src/main/java/net/ximatai/muyun/MuYunConst.java b/muyun-core/src/main/java/net/ximatai/muyun/MuYunConst.java index 122adde6..89774d12 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/MuYunConst.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/MuYunConst.java @@ -2,7 +2,6 @@ public class MuYunConst { public static final String API_REQUEST_CONTEXT_KEY = "apiRequest"; - public static final String DEBUG_MODE_CONTEXT_KEY = "debug"; public static final String SESSION_USER_KEY = "user"; public static final String SSO_MODULE_NAME = "SSO"; } diff --git a/muyun-core/src/main/java/net/ximatai/muyun/ability/IRuntimeAbility.java b/muyun-core/src/main/java/net/ximatai/muyun/ability/IRuntimeAbility.java index 3523e547..dbd40c0c 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/ability/IRuntimeAbility.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/ability/IRuntimeAbility.java @@ -3,11 +3,10 @@ import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.Session; import net.ximatai.muyun.MuYunConst; +import net.ximatai.muyun.core.config.MuYunConfig; import net.ximatai.muyun.model.ApiRequest; import net.ximatai.muyun.model.IRuntimeUser; -import static net.ximatai.muyun.MuYunConst.DEBUG_MODE_CONTEXT_KEY; - /** * 获取运行时上下文的能力 */ @@ -15,6 +14,8 @@ public interface IRuntimeAbility { RoutingContext getRoutingContext(); + MuYunConfig getConfig(); + default ApiRequest getApiRequest() { try { return getRoutingContext().get(MuYunConst.API_REQUEST_CONTEXT_KEY); @@ -28,7 +29,7 @@ default IRuntimeUser getUser() { Session session = getRoutingContext().session(); if (session != null && session.get(MuYunConst.SESSION_USER_KEY) != null) { return session.get(MuYunConst.SESSION_USER_KEY); - } else if (getRoutingContext().get(DEBUG_MODE_CONTEXT_KEY) + } else if (getConfig().isTestMode() // 只有测试模式需要手动提供 userID 放在 Header里 && getRoutingContext().request().getHeader("userID") != null) { String userID = getRoutingContext().request().getHeader("userID"); return IRuntimeUser.build(userID); diff --git a/muyun-core/src/main/java/net/ximatai/muyun/core/Scaffold.java b/muyun-core/src/main/java/net/ximatai/muyun/core/Scaffold.java index 35ef22f5..6d68889c 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/core/Scaffold.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/core/Scaffold.java @@ -7,6 +7,7 @@ import net.ximatai.muyun.ability.IDatabaseAbility; import net.ximatai.muyun.ability.IRuntimeAbility; import net.ximatai.muyun.ability.ITableCreateAbility; +import net.ximatai.muyun.core.config.MuYunConfig; import net.ximatai.muyun.database.IDatabaseOperations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,6 +19,17 @@ public abstract class Scaffold implements IDatabaseAbility, IRuntimeAbility { private IDatabaseOperations databaseOperations; private EventBus eventBus; private RoutingContext routingContext; + private MuYunConfig config; + + @Override + public MuYunConfig getConfig() { + return config; + } + + @Inject + public void setConfig(MuYunConfig config) { + this.config = config; + } @Inject public void setRoutingContext(RoutingContext routingContext) { diff --git a/muyun-core/src/main/java/net/ximatai/muyun/core/config/MuYunConfig.java b/muyun-core/src/main/java/net/ximatai/muyun/core/config/MuYunConfig.java index 1cb9ff97..18b92620 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/core/config/MuYunConfig.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/core/config/MuYunConfig.java @@ -1,12 +1,31 @@ package net.ximatai.muyun.core.config; import io.smallrye.config.ConfigMapping; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; import java.util.Objects; @ConfigMapping(prefix = "muyun") public interface MuYunConfig { - Boolean debug(); + + default ProfileMode profile() { + Config config = ConfigProvider.getConfig(); + String upperCase = config.getValue("quarkus.profile", String.class).toUpperCase(); + return ProfileMode.valueOf(upperCase); + } + + default boolean isTestMode() { + return profile().equals(ProfileMode.TEST); + } + + default boolean isProdMode() { + return profile().equals(ProfileMode.PROD); + } + + default boolean isDevMode() { + return profile().equals(ProfileMode.DEV); + } String superUserId(); diff --git a/muyun-core/src/main/java/net/ximatai/muyun/core/config/ProfileMode.java b/muyun-core/src/main/java/net/ximatai/muyun/core/config/ProfileMode.java new file mode 100644 index 00000000..bd9234e7 --- /dev/null +++ b/muyun-core/src/main/java/net/ximatai/muyun/core/config/ProfileMode.java @@ -0,0 +1,5 @@ +package net.ximatai.muyun.core.config; + +public enum ProfileMode { + DEV, PROD, TEST +} diff --git a/muyun-core/src/main/java/net/ximatai/muyun/core/global/GlobalExceptionHandler.java b/muyun-core/src/main/java/net/ximatai/muyun/core/global/GlobalExceptionHandler.java index e90d4827..46713cc8 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/core/global/GlobalExceptionHandler.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/core/global/GlobalExceptionHandler.java @@ -43,7 +43,7 @@ public Response toResponse(Exception e) { String message = "服务器错误,请检查"; - if (config.debug() && e.getMessage() != null) { + if (!config.isProdMode() && e.getMessage() != null) { // 非生产环境可以访问原始错误信息 message = e.getMessage(); } @@ -74,4 +74,9 @@ public Response toResponse(Exception e) { public RoutingContext getRoutingContext() { return routingContext; } + + @Override + public MuYunConfig getConfig() { + return config; + } } diff --git a/muyun-core/src/main/java/net/ximatai/muyun/http/AuthorizationFilter.java b/muyun-core/src/main/java/net/ximatai/muyun/http/AuthorizationFilter.java index 9a0d984d..2ba08696 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/http/AuthorizationFilter.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/http/AuthorizationFilter.java @@ -19,8 +19,6 @@ import java.io.IOException; -import static net.ximatai.muyun.MuYunConst.DEBUG_MODE_CONTEXT_KEY; - @Provider @Priority(Priorities.AUTHENTICATION) @ApplicationScoped @@ -43,10 +41,6 @@ public void filter(ContainerRequestContext requestContext) throws IOException { // 获取请求的路径 String path = requestContext.getUriInfo().getRequestUri().getPath(); - if (config.debug()) { - routingContext.put(DEBUG_MODE_CONTEXT_KEY, true); - } - if (path.startsWith(restPath)) { //仅对 /api开头的请求做权限拦截 IRuntimeUser runtimeUser = this.getUser(); if ("/".equals(restPath)) { @@ -69,4 +63,9 @@ public void filter(ContainerRequestContext requestContext) throws IOException { public RoutingContext getRoutingContext() { return routingContext; } + + @Override + public MuYunConfig getConfig() { + return config; + } } diff --git a/muyun-core/src/main/java/net/ximatai/muyun/http/LogFilter.java b/muyun-core/src/main/java/net/ximatai/muyun/http/LogFilter.java index 5b5360a3..e9151597 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/http/LogFilter.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/http/LogFilter.java @@ -11,6 +11,7 @@ import jakarta.ws.rs.ext.Provider; import net.ximatai.muyun.MuYunConst; import net.ximatai.muyun.ability.IRuntimeAbility; +import net.ximatai.muyun.core.config.MuYunConfig; import net.ximatai.muyun.model.ApiRequest; import net.ximatai.muyun.model.IRuntimeUser; import net.ximatai.muyun.model.log.LogItem; @@ -41,6 +42,9 @@ public class LogFilter implements ContainerRequestFilter, ContainerResponseFilte @Inject Instance iLogLogin; + @Inject + MuYunConfig config; + private static final Logger LOG = LoggerFactory.getLogger(LogFilter.class); // 定义一个常量用于存储开始时间的键 @@ -144,4 +148,9 @@ private String getHost(ContainerRequestContext requestContext) { public RoutingContext getRoutingContext() { return routingContext; } + + @Override + public MuYunConfig getConfig() { + return config; + } } diff --git a/muyun-core/src/main/java/net/ximatai/muyun/model/TreeNode.java b/muyun-core/src/main/java/net/ximatai/muyun/model/TreeNode.java index e507425f..075ce7c8 100644 --- a/muyun-core/src/main/java/net/ximatai/muyun/model/TreeNode.java +++ b/muyun-core/src/main/java/net/ximatai/muyun/model/TreeNode.java @@ -50,8 +50,8 @@ public TreeNode setData(Map data) { return this; } - public TreeNode setChildren(List children) { - this.children = children; + public TreeNode setChildren(List children) { + this.children = (List) children; return this; } diff --git a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/DictCategoryController.java b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/DictCategoryController.java index 5afd7ac7..edbf5e34 100644 --- a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/DictCategoryController.java +++ b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/DictCategoryController.java @@ -60,8 +60,19 @@ public List getChildren() { @Path("/tree/{id}") public List tree(@PathParam("id") String id) { List list = dictController.tree(id, false, null, null); - return list.stream().map(it -> DictTreeNode.from(it) - .setValue(it.getData().get("v_value").toString())).toList(); + return nodeToDictNode(list); + } + + private List nodeToDictNode(List list) { + return list.stream().map(it -> { + DictTreeNode node = DictTreeNode.from(it) + .setValue(it.getData().get("v_value").toString()); + List children = node.getChildren(); + if (children != null && !children.isEmpty()) { + node.setChildren(nodeToDictNode(children)); + } + return node; + }).toList(); } @GET diff --git a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/ModuleController.java b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/ModuleController.java index 5f748422..5ffd753f 100644 --- a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/ModuleController.java +++ b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/ModuleController.java @@ -67,9 +67,7 @@ public void fitOut(TableWrapper wrapper) { @Override protected void afterInit() { - if (muYunConfig.debug()) { - initData(); - } + initData(); } @Override diff --git a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/RuntimeController.java b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/RuntimeController.java index 2633b998..e46538a8 100644 --- a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/RuntimeController.java +++ b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/RuntimeController.java @@ -95,6 +95,11 @@ public RoutingContext getRoutingContext() { return routingContext; } + @Override + public MuYunConfig getConfig() { + return config; + } + private List filterMenuByAuth(List list) { String userID = getUser().getId(); Map> authorizedResources = authorizationService.getAuthorizedResources(userID); diff --git a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/SsoController.java b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/SsoController.java index 2cb9f975..918d9c79 100644 --- a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/SsoController.java +++ b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/SsoController.java @@ -96,7 +96,8 @@ public IRuntimeUser login(@QueryParam("username") String username, @QueryParam(" Map userInDB = (Map) pageResult.getList().getFirst(); String vPassword = userInDB.get("v_password").toString(); String encryptedPassword = encryptPassword(vPassword, code); - if ((config.debug() && password.equals(vPassword)) || password.equals(encryptedPassword)) { + if (password.equals(encryptedPassword) + || (!config.isProdMode() && password.equals(vPassword))) { // 非生产环境允许使用非加密密码 if ((boolean) userInDB.get("b_enabled")) { Map user = userInfoController.view((String) userInDB.get("id")); IRuntimeUser runtimeUser = mapToUser(user); @@ -121,7 +122,7 @@ private String encryptPassword(String password, String code) { } private RuntimeException verificationCode(String code) { - if (config.debug() && ALL_PURPOSE_CODE_FOR_DEBUG.equals(code)) { + if (!config.isDevMode() && ALL_PURPOSE_CODE_FOR_DEBUG.equals(code)) { // 非生产环境允许万能验证码 return null; } @@ -209,6 +210,11 @@ public RoutingContext getRoutingContext() { return routingContext; } + @Override + public MuYunConfig getConfig() { + return config; + } + private IRuntimeUser mapToUser(Map user) { return new RuntimeUser() .setUsername((String) user.get("v_username")) diff --git a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/UserInfoController.java b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/UserInfoController.java index cf5edd08..c2e81af2 100644 --- a/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/UserInfoController.java +++ b/muyun-platform/src/main/java/net/ximatai/muyun/platform/controller/UserInfoController.java @@ -280,11 +280,16 @@ public ModuleConfig getModuleConfig() { .addAction(new ModuleAction("setRoles", "设置角色", ModuleAction.TypeLike.UPDATE)); } - private static String promptForInput(Scanner scanner, String promptMessage) { + private String promptForInput(Scanner scanner, String promptMessage) { + if (config.isTestMode()) { // 单元测试模式,锁定用户名密码 + return "admin"; + } + String input; do { System.out.print(promptMessage); input = scanner.nextLine().trim(); // 去掉输入前后的空格 + if (input.isEmpty()) { System.out.println("Input cannot be empty. Please try again."); } diff --git a/muyun-platform/src/main/java/net/ximatai/muyun/platform/model/DictTreeNode.java b/muyun-platform/src/main/java/net/ximatai/muyun/platform/model/DictTreeNode.java index 6cfea43b..3f7037ea 100644 --- a/muyun-platform/src/main/java/net/ximatai/muyun/platform/model/DictTreeNode.java +++ b/muyun-platform/src/main/java/net/ximatai/muyun/platform/model/DictTreeNode.java @@ -9,10 +9,10 @@ public class DictTreeNode extends TreeNode { public static DictTreeNode from(TreeNode node) { return (DictTreeNode) new DictTreeNode() - .setId(node.getId()) - .setLabel(node.getLabel()) - .setChildren(node.getChildren()) - .setData(node.getData()); + .setId(node.getId()) + .setLabel(node.getLabel()) + .setChildren(node.getChildren()) + .setData(node.getData()); } public String getValue() {