From 6f03cb6ca6710176e761dec6bd632cde878d6b5a Mon Sep 17 00:00:00 2001 From: Alan Yeh Date: Sat, 23 Nov 2024 22:52:24 +0800 Subject: [PATCH] =?UTF-8?q?[ADD]=20=E6=96=B0=E5=A2=9E=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8F=8A=E5=85=B6=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增 ApplicationController 2. 新增 TestApplicationController 单元测试 3. 应用模块改为应用路由,独立表存储改为JSON存储 Signed-off-by: Alan Yeh --- .../controller/ApplicationController.java | 125 ++++ .../saas/param/ApplicationParams.java | 123 ++++ .../saas/param/ApplicationRouteParams.java | 56 +- .../saas/query/ApplicationPageQuery.java | 81 +++ .../logic/saas/ApplicationLogic.java | 141 ++++ .../saas/TestApplicationController.java | 304 ++++++++ .../src/test/resources/images/logo-80x80.png | Bin 0 -> 6036 bytes .../core/attribute/ExchangeAttributes.java | 6 +- .../global/ApplicationDispatcherFilter.java | 26 +- .../global/routing/HttpRoutingFilter.java | 6 +- .../MasterTenantInitializer.java | 6 + .../database/migration/v0/v0_0_1_initial.java | 29 +- .../graphql/saas/dto/ApplicationDTO.java | 29 +- .../saas/dto/ApplicationModuleDTO.java | 74 -- .../saas/entity/ApplicationEntity.java | 8 + .../saas/mapper/ApplicationModuleMapper.java | 39 -- .../mutation/ApplicationModuleMutation.java | 172 ----- .../saas/mutation/ApplicationMutation.java | 49 +- .../saas/query/ApplicationModuleQuery.java | 163 ----- .../graphql/saas/query/ApplicationQuery.java | 22 +- .../applicationModuleMutation.graphql | 79 --- .../saas/mutation/applicationMutation.graphql | 26 +- .../saas/query/applicationModuleQuery.graphql | 89 --- .../saas/query/applicationQuery.graphql | 26 +- .../graphql/authority/TestMenuProvider.java | 11 + .../authority/TestPermissionProvider.java | 10 + .../graphql/authority/TestRoleProvider.java | 11 + .../TestMulticastBroadcasterProvider.java | 1 + .../TestMulticastMessageProvider.java | 1 + .../saas/TestApplicationModuleProvider.java | 656 ------------------ .../graphql/saas/TestApplicationProvider.java | 329 +++------ .../saas/TestTenantApplicationProvider.java | 1 + .../graphql/saas/TestTenantProvider.java | 1 + .../storage/TestStorageBucketProvider.java | 1 + .../storage/TestStorageObjectProvider.java | 1 + .../graphql/system/TestDatabaseProvider.java | 3 +- .../system/TestDictionaryProvider.java | 11 + .../java/central/data/saas/Application.java | 7 +- .../central/data/saas/ApplicationInput.java | 4 +- ...ationModule.java => ApplicationRoute.java} | 59 +- ...eInput.java => ApplicationRouteInput.java} | 53 +- .../saas/ApplicationModuleProvider.java | 44 -- .../stub/authority/authorizationProvider.md | 4 +- .../stub/saas/applicationModuleProvider.md | 460 ------------ .../graphql/stub/saas/applicationProvider.md | 50 +- .../graphql/stub/saas/tenantProvider.md | 39 +- 46 files changed, 1119 insertions(+), 2317 deletions(-) create mode 100644 central-dashboard/src/main/java/central/studio/dashboard/controller/saas/controller/ApplicationController.java create mode 100644 central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationParams.java rename central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationModuleEntity.java => central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationRouteParams.java (60%) create mode 100644 central-dashboard/src/main/java/central/studio/dashboard/controller/saas/query/ApplicationPageQuery.java create mode 100644 central-dashboard/src/main/java/central/studio/dashboard/logic/saas/ApplicationLogic.java create mode 100644 central-dashboard/src/test/java/central/studio/dashboard/controller/saas/TestApplicationController.java create mode 100644 central-dashboard/src/test/resources/images/logo-80x80.png delete mode 100644 central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationModuleDTO.java delete mode 100644 central-provider/src/main/java/central/studio/provider/graphql/saas/mapper/ApplicationModuleMapper.java delete mode 100644 central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationModuleMutation.java delete mode 100644 central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationModuleQuery.java delete mode 100644 central-provider/src/main/resources/central/graphql/saas/mutation/applicationModuleMutation.graphql delete mode 100644 central-provider/src/main/resources/central/graphql/saas/query/applicationModuleQuery.graphql delete mode 100644 central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationModuleProvider.java rename central-studio-library/src/main/java/central/data/saas/{ApplicationModule.java => ApplicationRoute.java} (66%) rename central-studio-library/src/main/java/central/data/saas/{ApplicationModuleInput.java => ApplicationRouteInput.java} (72%) delete mode 100644 central-studio-library/src/main/java/central/provider/graphql/saas/ApplicationModuleProvider.java delete mode 100644 central-studio-library/src/main/resources/central/graphql/stub/saas/applicationModuleProvider.md diff --git a/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/controller/ApplicationController.java b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/controller/ApplicationController.java new file mode 100644 index 00000000..7ccecc43 --- /dev/null +++ b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/controller/ApplicationController.java @@ -0,0 +1,125 @@ +/* + * MIT License + * + * Copyright (c) 2022-present Alan Yeh + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package central.studio.dashboard.controller.saas.controller; + +import central.bean.Page; +import central.data.saas.Application; +import central.starter.web.param.IdsParams; +import central.starter.web.query.IdQuery; +import central.studio.dashboard.controller.saas.param.ApplicationParams; +import central.studio.dashboard.controller.saas.query.ApplicationPageQuery; +import central.studio.dashboard.logic.saas.ApplicationLogic; +import central.validation.group.Insert; +import central.validation.group.Update; +import jakarta.validation.groups.Default; +import lombok.Setter; +import org.apache.shiro.authz.annotation.RequiresAuthentication; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * Application Controller + *

+ * 应用管理 + * + * @author Alan Yeh + * @since 2024/11/19 + */ +@RestController +@RequiresAuthentication +@RequestMapping("/dashboard/api/saas/applications") +public class ApplicationController { + + public interface Permissions { + String VIEW = "saas:application:view"; + String ADD = "saas:application:add"; + String EDIT = "saas:application:edit"; + String DELETE = "saas:application:delete"; + String ENABLE = "saas:application:enable"; + String DISABLE = "saas:application:disable"; + } + + @Setter(onMethod_ = @Autowired) + private ApplicationLogic logic; + + /** + * 按条件分页查询列表 + * + * @param query 查询 + * @return 分页结果 + */ + @GetMapping("/page") + public Page page(@Validated ApplicationPageQuery query) { + return this.logic.pageBy(query.getPageIndex(), query.getPageSize(), query.build(), null); + } + + /** + * 根据主键查询详情 + * + * @param query 查询 + * @return 详情 + */ + @GetMapping("/details") + public Application details(@Validated IdQuery query) { + return this.logic.findById(query.getId()); + } + + /** + * 更新行政数据 + * + * @param params 数据入参 + * @param accountId 当前登录帐号 + * @return 新增后的数据 + */ + @PostMapping + public Application add(@RequestBody @Validated({Insert.class, Default.class}) ApplicationParams params, @RequestAttribute String accountId) { + return this.logic.insert(params.toInput(), accountId); + } + + /** + * 更新数据 + * + * @param params 数据入参 + * @param accountId 当前登录帐号 + * @return 更新后的数据 + */ + @PutMapping + public Application update(@RequestBody @Validated({Update.class, Default.class}) ApplicationParams params, @RequestAttribute String accountId) { + return this.logic.update(params.toInput(), accountId); + } + + /** + * 根据主键删除数据 + * + * @param params 待删除主键列表 + * @param accountId 当前登录帐号 + * @return 受影响数据行数 + */ + @DeleteMapping + public long delete(@Validated IdsParams params, @RequestAttribute String accountId) { + return this.logic.deleteByIds(params.getIds(), accountId); + } +} diff --git a/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationParams.java b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationParams.java new file mode 100644 index 00000000..cb27f73c --- /dev/null +++ b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationParams.java @@ -0,0 +1,123 @@ +/* + * MIT License + * + * Copyright (c) 2022-present Alan Yeh + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package central.studio.dashboard.controller.saas.param; + +import central.data.saas.ApplicationInput; +import central.util.Listx; +import central.validation.Label; +import central.validation.group.Insert; +import central.validation.group.Update; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * Application Params + *

+ * 应用数据入参 + * + * @author Alan Yeh + * @since 2024/11/19 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ApplicationParams { + + @Label("主键") + @Null(groups = Insert.class) + @NotBlank(groups = Update.class) + @Size(min = 1, max = 32, groups = Insert.class) + private String id; + + @Label("标识") + @NotBlank + @Size(min = 1, max = 32) + @Pattern(regexp = "^[0-9a-zA-Z_-]+$", message = "${label}[${property}]只能由数字、英文字母、中划线、下划线组成") + @Pattern(regexp = "^(?!-)(?!_).*$", message = "${label}[${property}]不能由中划线或下划线开头") + @Pattern(regexp = "^(?!.*?[-_]$).*$", message = "${label}[${property}]不能由中划线或下划线结尾") + @Pattern(regexp = "^(?!.*(--).*$).*$", message = "${label}[${property}]不能出现连续中划线") + @Pattern(regexp = "^(?!.*(__).*$).*$", message = "${label}[${property}]不能出现连续下划线") + @Pattern(regexp = "^(?!.*(-_|_-).*$).*$", message = "${label}[${property}]不能出现连续中划线、下划线") + private String code; + + @Label("名称") + @NotBlank + @Size(min = 1, max = 50) + private String name; + + @Label("图标") + @NotBlank + @Size(max = 2 * 1024 * 1024) + private String logo; + + @Label("上下文路径") + @NotBlank + @Size(min = 1, max = 64) + private String contextPath; + + @Label("服务地址") + @NotBlank + @Size(min = 1, max = 1024) + private String url; + + @Label("密钥") + @NotBlank + @Size(min = 1, max = 32) + private String secret; + + @Label("是否启用") + @NotNull + private Boolean enabled; + + @Label("备注") + @Size(max = 1024) + private String remark; + + @Valid + @Label("路由") + private List routes; + + public ApplicationInput toInput() { + return ApplicationInput.builder() + .id(this.getId()) + .code(this.getCode()) + .name(this.getName()) + .logo(this.getLogo()) + .url(this.getUrl()) + .contextPath(this.getContextPath()) + .secret(this.getSecret()) + .enabled(this.getEnabled()) + .remark(this.getRemark()) + .routes(Listx.asStream(this.getRoutes()).map(ApplicationRouteParams::toInput).toList()) + .build(); + } +} diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationModuleEntity.java b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationRouteParams.java similarity index 60% rename from central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationModuleEntity.java rename to central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationRouteParams.java index be644b1b..3442a5fe 100644 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationModuleEntity.java +++ b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/param/ApplicationRouteParams.java @@ -22,60 +22,42 @@ * SOFTWARE. */ -package central.studio.provider.graphql.saas.entity; +package central.studio.dashboard.controller.saas.param; -import central.data.saas.ApplicationModuleInput; -import central.sql.data.ModifiableEntity; -import central.sql.meta.annotation.Relation; +import central.data.saas.ApplicationRouteInput; import central.validation.Label; -import jakarta.persistence.Id; -import jakarta.persistence.Table; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import java.io.Serial; - /** - * 应用模块信息 + * Application Module Params + *

+ * 应用路由参数 * * @author Alan Yeh - * @since 2022/09/25 + * @since 2024/11/19 */ @Data +@Builder @NoArgsConstructor @AllArgsConstructor -@Table(name = "X_SAAS_APPLICATION_MODULE") -@EqualsAndHashCode(callSuper = true) -@Relation(alias = "application", target = ApplicationEntity.class, property = "applicationId") -public class ApplicationModuleEntity extends ModifiableEntity { - @Serial - private static final long serialVersionUID = 7015722509704015462L; - - @Id - @Label("主键") - @Size(max = 32) - private String id; +public class ApplicationRouteParams { - @Label("所属应用主键") + @Label("上下文路径") @NotBlank - @Size(min = 1, max = 32) - private String applicationId; + @Size(min = 1, max = 64) + private String contextPath; @Label("服务地址") @NotBlank @Size(min = 1, max = 1024) private String url; - @Label("上下文路径") - @NotBlank - @Size(min = 1, max = 64) - private String contextPath; - @Label("是否启用") @NotNull private Boolean enabled; @@ -84,12 +66,12 @@ public class ApplicationModuleEntity extends ModifiableEntity { @Size(max = 1024) private String remark; - public void fromInput(ApplicationModuleInput input) { - this.setId(input.getId()); - this.setApplicationId(input.getApplicationId()); - this.setUrl(input.getUrl()); - this.setContextPath(input.getContextPath()); - this.setEnabled(input.getEnabled()); - this.setRemark(input.getRemark()); + public ApplicationRouteInput toInput() { + return ApplicationRouteInput.builder() + .contextPath(this.getContextPath()) + .url(this.getUrl()) + .enabled(this.getEnabled()) + .remark(this.getRemark()) + .build(); } } diff --git a/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/query/ApplicationPageQuery.java b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/query/ApplicationPageQuery.java new file mode 100644 index 00000000..f5ae6f52 --- /dev/null +++ b/central-dashboard/src/main/java/central/studio/dashboard/controller/saas/query/ApplicationPageQuery.java @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (c) 2022-present Alan Yeh + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package central.studio.dashboard.controller.saas.query; + +import central.data.saas.Application; +import central.lang.Stringx; +import central.sql.query.Conditions; +import central.starter.web.query.PageQuery; +import central.validation.Label; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * Application Page Query + *

+ * 应用分页查询 + * + * @author Alan Yeh + * @since 2024/11/19 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ApplicationPageQuery extends PageQuery { + @Serial + private static final long serialVersionUID = -6899015669281335622L; + + @Label("主键") + private String id; + + @Label("名称") + private String name; + + @Label("标识") + private String code; + + @Override + public Conditions build() { + var conditions = Conditions.of(Application.class); + + // 精确字段搜索 + if (Stringx.isNotEmpty(this.getId())) { + conditions.eq(Application::getId, this.getId()); + } + if (Stringx.isNotEmpty(this.getName())) { + conditions.like(Application::getName, this.getName()); + } + if (Stringx.isNotEmpty(this.getCode())) { + conditions.like(Application::getCode, this.getCode()); + } + + // 模糊搜索 + for (String keyword : this.getKeywords()) { + conditions.and(filter -> filter.like(Application::getCode, keyword).or().like(Application::getName, keyword)); + } + return conditions; + } +} diff --git a/central-dashboard/src/main/java/central/studio/dashboard/logic/saas/ApplicationLogic.java b/central-dashboard/src/main/java/central/studio/dashboard/logic/saas/ApplicationLogic.java new file mode 100644 index 00000000..8b406ea0 --- /dev/null +++ b/central-dashboard/src/main/java/central/studio/dashboard/logic/saas/ApplicationLogic.java @@ -0,0 +1,141 @@ +/* + * MIT License + * + * Copyright (c) 2022-present Alan Yeh + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package central.studio.dashboard.logic.saas; + +import central.bean.Page; +import central.data.saas.Application; +import central.data.saas.ApplicationInput; +import central.provider.graphql.saas.ApplicationProvider; +import central.sql.query.Conditions; +import central.sql.query.Orders; +import central.util.Collectionx; +import central.util.Listx; +import central.validation.group.Insert; +import central.validation.group.Update; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import jakarta.validation.groups.Default; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * Application Logic + *

+ * 应用业务逻辑 + * + * @author Alan Yeh + * @since 2024/11/19 + */ +@Service +public class ApplicationLogic { + + @Setter(onMethod_ = @Autowired) + private ApplicationProvider provider; + + /** + * 如用用户没有指定排序条件,则构建默认的排序条件 + * + * @param orders 用户指定的排序条件 + */ + private Orders getDefaultOrders(@Nullable Orders orders) { + if (Collectionx.isNullOrEmpty(orders)) { + return orders; + } + return Orders.of(Application.class).asc(Application::getCode); + } + + /** + * 分页查询 + * + * @param pageIndex 分页下标 + * @param pageSize 分页大小 + * @param conditions 筛选条件 + * @param orders 排序条件 + * @return 分页数据 + */ + public Page pageBy(@Nonnull Long pageIndex, @Nonnull Long pageSize, @Nullable Conditions conditions, @Nullable Orders orders) { + orders = this.getDefaultOrders(orders); + return this.provider.pageBy(pageIndex, pageSize, conditions, orders, "master"); + } + + /** + * 主键查询 + * + * @param id 主键 + * @return 详情 + */ + public Application findById(@Nonnull String id) { + return this.provider.findById(id, "master"); + } + + /** + * 根据标识查询租户 + * + * @param code 标识 + * @return 租户信息 + */ + public @Nullable Application findByCode(@Nonnull String code) { + var data = provider.findBy(1L, 0L, Conditions.of(Application.class).eq(Application::getCode, code), null, "master"); + return Listx.getFirstOrNull(data); + } + + /** + * 插入数据 + * + * @param input 数据输入 + * @param accountId 操作帐号主键 + * @return 插入后的数据 + */ + public Application insert(@Nonnull @Validated({Insert.class, Default.class}) ApplicationInput input, @Nonnull String accountId) { + return this.provider.insert(input, accountId, "master"); + } + + /** + * 更新数据 + * + * @param input 数据输入 + * @param accountId 操作帐号主键 + * @return 更新后的数据 + */ + public Application update(@Nonnull @Validated({Update.class, Default.class}) ApplicationInput input, @Nonnull String accountId) { + return this.provider.update(input, accountId, "master"); + } + + /** + * 根据主键删除数据 + * + * @param ids 主键 + * @param accountId 操作帐号主键 + * @return 受影响数据行数 + */ + public long deleteByIds(@Nullable List ids, @Nonnull String accountId) { + return this.provider.deleteByIds(ids, "master"); + } + +} diff --git a/central-dashboard/src/test/java/central/studio/dashboard/controller/saas/TestApplicationController.java b/central-dashboard/src/test/java/central/studio/dashboard/controller/saas/TestApplicationController.java new file mode 100644 index 00000000..ae447dd4 --- /dev/null +++ b/central-dashboard/src/test/java/central/studio/dashboard/controller/saas/TestApplicationController.java @@ -0,0 +1,304 @@ +/* + * MIT License + * + * Copyright (c) 2022-present Alan Yeh + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package central.studio.dashboard.controller.saas; + +import central.data.saas.Application; +import central.io.IOStreamx; +import central.lang.reflect.TypeRef; +import central.provider.scheduled.DataContext; +import central.starter.test.cookie.CookieStore; +import central.studio.dashboard.DashboardApplication; +import central.studio.dashboard.controller.TestController; +import central.studio.dashboard.controller.saas.controller.ApplicationController; +import central.studio.dashboard.controller.saas.param.ApplicationParams; +import central.studio.dashboard.controller.saas.param.ApplicationRouteParams; +import central.studio.dashboard.logic.system.DatabaseLogic; +import central.util.Jsonx; +import central.web.XForwardedHeaders; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.util.Base64; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Application Controller Test Cases + * + * @author Alan Yeh + * @since 2024/11/19 + */ +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = DashboardApplication.class) +public class TestApplicationController extends TestController { + + private static final String PATH = "/dashboard/api/saas/applications"; + + /** + * @see ApplicationController#add + * @see ApplicationController#details + * @see ApplicationController#page + * @see ApplicationController#delete + */ + @Test + public void case0(@Autowired MockMvc mvc, @Autowired CookieStore cookieStore, @Autowired DatabaseLogic databaseLogic) throws Exception { + // 新增 + var addRequest = MockMvcRequestBuilders.post(PATH) + .cookie(this.getSessionCookie(PATH, mvc, cookieStore)) + .contentType(MediaType.APPLICATION_JSON) + .content(Jsonx.Default().serialize(ApplicationParams.builder() + .code("test") + .name("测试应用") + .logo(Base64.getEncoder().encodeToString(IOStreamx.readBytes(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/logo-80x80.png")))) + .url("http://localhost:8080") + .contextPath("/test") + .secret("test-secret") + .enabled(Boolean.TRUE) + .remark("测试应用") + .routes(List.of( + ApplicationRouteParams.builder().contextPath("/test/abc").url("http://localhost:8081").enabled(Boolean.TRUE).remark("测试路由").build() + )) + .build())) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + var response = mvc.perform(addRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string(Matchers.not(Matchers.emptyString()))) + .andExpect(jsonPath("$.id").isNotEmpty()) + .andExpect(jsonPath("$.code").isNotEmpty()) + .andExpect(jsonPath("$.name").isNotEmpty()) + .andExpect(jsonPath("$.logo").isNotEmpty()) + .andExpect(jsonPath("$.contextPath").isNotEmpty()) + .andExpect(jsonPath("$.url").isNotEmpty()) + .andExpect(jsonPath("$.secret").isNotEmpty()) + .andExpect(jsonPath("$.enabled").isNotEmpty()) + .andExpect(jsonPath("$.remark").isNotEmpty()) + .andExpect(jsonPath("$.routes").isNotEmpty()) + .andReturn().getResponse(); + + var body = Jsonx.Default().deserialize(response.getContentAsString(), TypeRef.of(Application.class)); + assertNotNull(body); + + // 详情查询 + var detailsRequest = MockMvcRequestBuilders.get(PATH + "/details") + .cookie(this.getSessionCookie(PATH + "/details", mvc, cookieStore)) + .queryParam("id", body.getId()) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + + mvc.perform(detailsRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string(Matchers.not(Matchers.emptyString()))) + .andExpect(jsonPath("$.id").value(body.getId())) + .andExpect(jsonPath("$.code").value(body.getCode())) + .andExpect(jsonPath("$.name").value(body.getName())) + .andExpect(jsonPath("$.logo").value(body.getLogo())) + .andExpect(jsonPath("$.contextPath").value(body.getContextPath())) + .andExpect(jsonPath("$.url").value(body.getUrl())) + .andExpect(jsonPath("$.secret").value(body.getSecret())) + .andExpect(jsonPath("$.enabled").value(body.getEnabled())) + .andExpect(jsonPath("$.remark").value(body.getRemark())) + .andExpect(jsonPath("$.routes[0].contextPath").value(body.getRoutes().get(0).getContextPath())) + .andExpect(jsonPath("$.routes[0].url").value(body.getRoutes().get(0).getUrl())) + .andExpect(jsonPath("$.routes[0].enabled").value(body.getRoutes().get(0).getEnabled())) + .andExpect(jsonPath("$.routes[0].remark").value(body.getRoutes().get(0).getRemark())); + + // 分页查询 + var pageRequest = MockMvcRequestBuilders.get(PATH + "/page") + .cookie(this.getSessionCookie(PATH + "/page", mvc, cookieStore)) + .queryParam("pageIndex", "1") + .queryParam("pageSize", "20") + .queryParam("code", "test") + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + mvc.perform(pageRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.pager.pageIndex").value(1)) + .andExpect(jsonPath("$.pager.pageSize").value(20)) + .andExpect(jsonPath("$.pager.pageCount").value(1)) + // master 租户 + 新创建的租户,所以是 2 个租户 + .andExpect(jsonPath("$.pager.itemCount").value(1)) + .andExpect(jsonPath("$.data").isArray()) + .andExpect(jsonPath("$.data[0].id").value(body.getId())) + .andExpect(jsonPath("$.data[0].code").value(body.getCode())) + .andExpect(jsonPath("$.data[0].name").value(body.getName())) + .andExpect(jsonPath("$.data[0].logo").value(body.getLogo())) + .andExpect(jsonPath("$.data[0].contextPath").value(body.getContextPath())) + .andExpect(jsonPath("$.data[0].url").value(body.getUrl())) + .andExpect(jsonPath("$.data[0].secret").value(body.getSecret())) + .andExpect(jsonPath("$.data[0].enabled").value(body.getEnabled())) + .andExpect(jsonPath("$.data[0].remark").value(body.getRemark())) + .andExpect(jsonPath("$.data[0].routes[0].contextPath").value(body.getRoutes().get(0).getContextPath())) + .andExpect(jsonPath("$.data[0].routes[0].url").value(body.getRoutes().get(0).getUrl())) + .andExpect(jsonPath("$.data[0].routes[0].enabled").value(body.getRoutes().get(0).getEnabled())) + .andExpect(jsonPath("$.data[0].routes[0].remark").value(body.getRoutes().get(0).getRemark())); + + // 删除数据 + var deleteRequest = MockMvcRequestBuilders.delete(PATH) + .cookie(this.getSessionCookie(PATH, mvc, cookieStore)) + .queryParam("ids", body.getId()) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + + mvc.perform(deleteRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string("1")); + } + + /** + * @see ApplicationController#add + * @see ApplicationController#update + * @see ApplicationController#details + * @see ApplicationController#delete + */ + @Test + public void case1(@Autowired MockMvc mvc, @Autowired CookieStore cookieStore, @Autowired DataContext context) throws Exception { + // 新增 + var addRequest = MockMvcRequestBuilders.post(PATH) + .cookie(this.getSessionCookie(PATH, mvc, cookieStore)) + .contentType(MediaType.APPLICATION_JSON) + .content(Jsonx.Default().serialize(ApplicationParams.builder() + .code("test") + .name("测试应用") + .logo(Base64.getEncoder().encodeToString(IOStreamx.readBytes(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/logo-80x80.png")))) + .url("http://localhost:8080") + .contextPath("/test") + .secret("test-secret") + .enabled(Boolean.TRUE) + .remark("测试应用") + .routes(List.of( + ApplicationRouteParams.builder().contextPath("/test/abc").url("http://localhost:8081").enabled(Boolean.TRUE).remark("测试路由").build() + )) + .build())) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + var response = mvc.perform(addRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string(Matchers.not(Matchers.emptyString()))) + .andExpect(jsonPath("$.id").isNotEmpty()) + .andExpect(jsonPath("$.code").isNotEmpty()) + .andExpect(jsonPath("$.name").isNotEmpty()) + .andExpect(jsonPath("$.logo").isNotEmpty()) + .andExpect(jsonPath("$.contextPath").isNotEmpty()) + .andExpect(jsonPath("$.url").isNotEmpty()) + .andExpect(jsonPath("$.secret").isNotEmpty()) + .andExpect(jsonPath("$.enabled").isNotEmpty()) + .andExpect(jsonPath("$.remark").isNotEmpty()) + .andExpect(jsonPath("$.routes").isNotEmpty()) + .andReturn().getResponse(); + + var body = Jsonx.Default().deserialize(response.getContentAsString(), TypeRef.of(Application.class)); + assertNotNull(body); + + // 更新 + var updateRequest = MockMvcRequestBuilders.put(PATH) + .cookie(this.getSessionCookie(PATH, mvc, cookieStore)) + .contentType(MediaType.APPLICATION_JSON) + .content(Jsonx.Default().serialize(ApplicationParams.builder() + .id(body.getId()) + .code("test") + .name("测试应用") + .logo(Base64.getEncoder().encodeToString(IOStreamx.readBytes(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/logo-80x80.png")))) + .url("http://localhost:8080") + .contextPath("/test") + .secret("test-secret") + .enabled(Boolean.FALSE) + .remark("测试应用") + .routes(List.of( + ApplicationRouteParams.builder().contextPath("/test/abc").url("http://localhost:8081").enabled(Boolean.TRUE).remark("测试路由").build() + )) + .build())) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + + mvc.perform(updateRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string(Matchers.not(Matchers.emptyString()))) + .andExpect(jsonPath("$.id").value(body.getId())) + .andExpect(jsonPath("$.code").value(body.getCode())) + .andExpect(jsonPath("$.name").value(body.getName())) + .andExpect(jsonPath("$.logo").value(body.getLogo())) + .andExpect(jsonPath("$.contextPath").value(body.getContextPath())) + .andExpect(jsonPath("$.url").value(body.getUrl())) + .andExpect(jsonPath("$.secret").value(body.getSecret())) + .andExpect(jsonPath("$.enabled").value(Boolean.FALSE)) + .andExpect(jsonPath("$.remark").value(body.getRemark())) + .andExpect(jsonPath("$.routes[0].contextPath").value(body.getRoutes().get(0).getContextPath())) + .andExpect(jsonPath("$.routes[0].url").value(body.getRoutes().get(0).getUrl())) + .andExpect(jsonPath("$.routes[0].enabled").value(body.getRoutes().get(0).getEnabled())) + .andExpect(jsonPath("$.routes[0].remark").value(body.getRoutes().get(0).getRemark())); + + // 详情查询 + var detailsRequest = MockMvcRequestBuilders.get(PATH + "/details") + .cookie(this.getSessionCookie(PATH + "/details", mvc, cookieStore)) + .queryParam("id", body.getId()) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + + mvc.perform(detailsRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string(Matchers.not(Matchers.emptyString()))) + .andExpect(jsonPath("$.id").value(body.getId())) + .andExpect(jsonPath("$.code").value(body.getCode())) + .andExpect(jsonPath("$.name").value(body.getName())) + .andExpect(jsonPath("$.logo").value(body.getLogo())) + .andExpect(jsonPath("$.contextPath").value(body.getContextPath())) + .andExpect(jsonPath("$.url").value(body.getUrl())) + .andExpect(jsonPath("$.secret").value(body.getSecret())) + .andExpect(jsonPath("$.enabled").value(Boolean.FALSE)) + .andExpect(jsonPath("$.remark").value(body.getRemark())) + .andExpect(jsonPath("$.routes[0].contextPath").value(body.getRoutes().get(0).getContextPath())) + .andExpect(jsonPath("$.routes[0].url").value(body.getRoutes().get(0).getUrl())) + .andExpect(jsonPath("$.routes[0].enabled").value(body.getRoutes().get(0).getEnabled())) + .andExpect(jsonPath("$.routes[0].remark").value(body.getRoutes().get(0).getRemark())); + + // 删除数据 + var deleteRequest = MockMvcRequestBuilders.delete(PATH) + .cookie(this.getSessionCookie(PATH, mvc, cookieStore)) + .queryParam("ids", body.getId()) + .accept(MediaType.APPLICATION_JSON) + .header(XForwardedHeaders.TENANT, "master"); + + mvc.perform(deleteRequest) + .andExpect(status().is2xxSuccessful()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(content().string("1")); + } +} diff --git a/central-dashboard/src/test/resources/images/logo-80x80.png b/central-dashboard/src/test/resources/images/logo-80x80.png new file mode 100644 index 0000000000000000000000000000000000000000..17c2d30e17a34df0683ca53d82298152ed770167 GIT binary patch literal 6036 zcmZ`-cRU?0;N;5Xw+sNTFaTIJ0sxU@0J!CtUaKm4 z6$nIW%bP1H0qj>855UGC2QaS?#?=X6&;Zxjt`P7DgZ3}{7~}4r91sA6SOHjna&)ik z^&xk)t~I|cW){ZZ8M8otv5{Grf8%Re%Q&OrmBDwE({Tm>Fva!408-Pb007iwrLOIw zt)wVo>R`uhZ02Bs;`Xp}yjB6C9wJxJ4&`DD@vyVCcNXywgZ{w~xx&|O9w_7wii?dH zR9guNk#=xGK?JyA+%Tv(0R#dObuu#-d5n1Yr~K+p3~K4(;wZwyUx?as&T;AFwW zD=aL`1B3Ix;apb?E@w}B7h?}DduOKKN&b@ufpRu=vT}5>aMqSwhpbRMIe9c*2% z+Y%Rqi~dpJ|2hBe@3-J@zJ|S(i}-&e|8oCZrTusO?=t^%{#&5pWQDqVkbm^W`)6DK z^!J)H>B$^&Jqjj*yq**jm)!Ycq1<@v9Xe=DUOY#p4`9F0v;;#YxoWQpk9Wx~{yxvzDM?XTzOcH>KfmZ1jMPGqL|W@^HuFjyLJp{{G_mfTlW z&SF#amE&)xzv)*vjsm2c4&N&{IfXsoQ|?QvPVhKvEzAVtsRQQ;e0dv0SSvhW3 z3LyPhcfN*((FQ!*JfY?zAKYEa08V$_MG>tAO&o612q3LI+wTwVguBUL)`^=U!^&c1>x8p-r|Vsw?(y;Qabd=ZLOYlT@0T( zVc4zwaBYm3t(5kL6@4&L<-d$?d|S9kR5Np%yf0lAt5*kY{>1&$!Ax%;&I}Wdn_-|; zOC(vO*jdmCp76(kHtvd2q2?;xr)~Nur)?<^Pg@s*zwEhtjQCNwFq$KH)s7QF7*1z? zYxgY{<19Hs?KEw(Cncu3@W~C0{8at5yrEU*9D~xrw+lCUkm)6f7`~?)`KkNW1R$Ls z%XM$N3E#+*@AAtea}k=e))?2ZCNFM&GQJ=lJ$!F?*CA16aee92AfI^u^BG2(O*GCE zH_mRoln1jYfrp>7?*x;1ysL3`Se$%9y;X$|y~S{+5=@|5E1SOiyl}$>VaK_Ore&{w z^t6|Hd}c!ErOshxawqn{0_hf``0zxYi^E3D<*)|JP1|v1PXch%*4cw+4o?n>dC-){ zTslu91zaxqa6dYH62vRkA{kvb&hI9yYyz)vobz1V-xu(W_?aLjFTI4bWTd%lv4G9z z;$XN^lQ>G`|7(x5dfi7UAamb)C4=xt3E|ljcj-Z8&^KD_tjddcun@nv#{-R;0L@UjpZ4k4<&bU4)hpH z)um-e^?1z8zqR12zZ(cQvcUB23*0ZFS?>#bIMFj3m$tc~bYC^|wG!)IYDCCyh~1E( z3@%L5ZQz#Ya;z+PEotqeT5~tFTV7Lf=uCAedS68*&6_{xiWn6DF8i=#&{$vQ5#d`2Gi()u=fgsr>r!3_8MzJ9fb22XjnVumI^HbLoY<7Y>j zA@dU#$*cRiCJMXj2nVVrHeG z$Hu*)k{vhL{+-+&2as242A<1`$h+x!v&^YRR9$~^o7Z^hH>nf6Q4q`>Km0l1t5}ad zYb@COnT`(btjNU=WN1cIxZ9pw*!^-Fghy*a)mc;DeFg@NZ1Xk`H0`i<&28SVx6!CZ zyFYp;DM5EB1u@loH*W4Ke8SaHOEVcuq@NUR*! zyZQV{e~yT#ytUuBnV_aOiHJ+kPp3%uJ^E(}DkW*P-_z=7Y`M6;J$8<8!>FVy1fQHQ zO7@&gm|!#1L)m#@uGFqUvp?rl9)V0lyy;(_vgV2zEn7UVh2Ql_-xPUzkD;&YE2U!S zb1F%xJJ}1xNxZJs-Wu`gq?h{jRZ4>QUi^?IQivDzv$R=K$f$}3? zn{DX&3Dlj7#SPbtRjMhHS4TS9-P`$Rapy^G97&@xr)c@WpoXRvyD4;!qEWhQ3V&KYJ!ozkJ$50w=0 zL(Kxes^FXbW+7_+CtfC(2T?pP`MgbD(6|m%Jq-=Vo5&bDVK1_8H=7+a!r>p3VsSKc zN`H}Z(Nz7*nPJ*w^uxs1O~Im)c@b5UQ>7_7P^*cmq7xfbjTxgUE`TtUc+6i}g8Uv^ zo`A)G#jxynQGU7n)HddQdVC$Tige_1RP0w= zNJA|0=oT!P*-bG?&|I+OjOH6t|625y7$&4Ke{}PWR1`Itu5m;pwRq34o_8Ar)GTFJ zmXj9#f$2MRC98K5B=Q&)V;$p`G^%p>zz4%ecZ74RvVycJYC1 z#kO$ln@QlECZVyt6}?}R5sfl9So;M!$#*`=WR7cBG0cmMIz=F58D`^+2LwkgxGt3A z3tMzFG1)wwcjq`8&8ceT>zjO9-Q*|^8xJPa$}8*UJfRfkl4iy+yFjUtn&XGyl<{@s z(d|}1G98g${qfi1I#ZS>uNJW2Z7|NRJ%foH-`eV$;VoR^mYi-!D>F60Xv{72J7Rx# ziUVhAi$4D`$lcNM={s*X$ELAjI>>2(f%3QgrYluqW2XYOdxeOEG;vw#qCa1 zX=vMlyk>3uW))Col4*c+9g)Z$AB;>n&jr`z=hDaNp_B`oEiN*^dU?>8=EN|Ckt


{i5%(%Z+JhK{c+;Hhm#BHgcw?bYNLQn!50})0L$a(RvZgi2 z@F-%@rT19GO3$rL_aBv6`MVKt5a;B)81Y&Y0v`?9I1l&Po?8gU)Uo=;_;vVn*h#M4 zpduRddXiv!!C>J~nEALCVsiJ36E=<$42+cpEQWL|Gg1k}EA$ z)9_VQo6;d;E4cvs_dZf^M>NW;YAF9k)I!dzOa=nWgH#AenG>3ikFo4Nn1<7h2ub^z zu(!{i zmb3xPVz9i19b5)YON7YS-Xq#%KT;%-zC^USG9^>KB#Sm(TAZORw!)l{d)cxW)rO4V z`aQr3fknJhQLE?Uf&~?d>1vXzU{jQsivC7*Da?h*#d^O@yYNMuyeP@K$DDMiBjXzB ziU{cTT^u8cHh6K+Qv46w+jKb(>*Jou;=bmim?-!}%Te9D-80m8r1WVx7~Y>}L|<3R zy_+r1s4vIWdJ@}YWp9v6rmgK=Ji709LmENEd4f=iZBI)z&~t~~j9YTfCv8~Qz!}u* z{LB=QK81{9Sr(<`phS}LBly4WS@{g`-_+R`?GKvOG=py8rMtV?eg`%*Ocx%y%573- zl?NyVXaO5Y6DY4hgQ-bVF>Jb?ZU z)-2MMrArm``f$yMEB6}_#o07 zZV5uKD9Xf%EosTxJ|$q3mKw7cbr}PycKMq^XItg0V*;`C|Z-9+!j+HZh_Y9BF}ZC zP2-ot5sCi`NOI^@b!OH^HxL&|K<_IFXwlKY+O*K6w71axzC2Nb-zU zl_IldS{XD9$CxJz-0v*FW6X_*lF-Vc0}84+SAmX6Es@pjru%cYdtu%@CIniHpV%?J z@Y(t$PsKLwsqAs)9$2QYB$S~$OCJ1uO_@w+L$E~U6S=TxY(a3}wclCoVI=k8beh*| zdqz@~^sN?4$Uq6?tf96i4Re$^ZzRCmJ;w#``93g6B=5#d(s)3-o>_dnLQ6lcI>C^i z4DWZ+gGsvUe+l{7M7(+3`bz4D_4}+ir*=A@i(!(Iq zQ&!8D^ay5wA*apKGJ_SN#RIPiqKXOELmED^-mhjOI41@3Y&V1o<7BLf^pZjvj?Qm4 zdO3MDIGPj{#*yGERRsm)7)?G6-8~nQs@)ngz1)^}k`HsLs2Mx^`5k?)^>bu*fLsjW z>j*w2L@otNO0ng`t)PyF*|W>4@5;(z@363hO9vl$OtyvX+~*NH?9dqX`C(0!Xg1W3 zXGFY*>zDDel*+SpH)_IQPj6QG3=L+eionNQm#c84Yi%14Y)wevd_7NW@#wq<96b=h z2Pc^S+KqdGF*cXn9PZbm)quvPoikFGQUEi>RqDj2tHBjDD>1cyd1Iq&K}n&wjLQO{yx9Fy$Z{|aCa!nZzRP;a zv%^8(Y9`(zm29m!1nVjdk5$RkmNH@mcCz!jo>|A$O#9nqYl=YqFE%l~gh%gI$vwa@@kPd|Z74*6HrEPtZi1)#BRk!}* zTZIampvU-ayK= zytAORb=W~;=YQ_%aKx$|{`xhKn$AOoh+Vsww^M^s{NM4I`p3T8vE(oGd4V`0gPt|T z+yX9TQ+Kl^;;^-&h9?nMG49giN=*YkQz4oHuJ-3LLuf+nr!FQd! z2(Id}5J{^Vx}_)4+B2DRGbnz=qitMD+&A?m=u&&aFo7 zT18B9Xw*K@Ig_;e8^KKjXE>hY7NWg<-z90}mR{q~GxmhWNB)CTF;Q&>8z5V{fq>Oa zd{NNI3yZj@7YapR;=zk-k*FHZ3iGf2Dj%>xqI55bW4%nlzDVnVSJ?M>iLJ@Mei*1O z{dr?n4zHJ#AS{PYJNV|Eq{X^fn207Mkv7q+)SXDjr)@t^N*a`zS=fOy$RWUyyF;!p zEbLX3G*JE#zwBp;grVE`@I-0bb`2I7USFRGBVT^K<3tBF(Hz51@VU`wl(WQyoE~3= z1u`18xl2RWN}l;txew$IYbn*bUaE=O^o4uR8OU$SNVMnl*+;?I6@*o!FxXJZGQ0B2 z^=_TbjVgyD7`bJRs`A6+BCqK>gzh-$EWkksXqk#VdSs1^e literal 0 HcmV?d00001 diff --git a/central-gateway/src/main/java/central/studio/gateway/core/attribute/ExchangeAttributes.java b/central-gateway/src/main/java/central/studio/gateway/core/attribute/ExchangeAttributes.java index a3cda2a1..af3877b7 100644 --- a/central-gateway/src/main/java/central/studio/gateway/core/attribute/ExchangeAttributes.java +++ b/central-gateway/src/main/java/central/studio/gateway/core/attribute/ExchangeAttributes.java @@ -25,7 +25,7 @@ package central.studio.gateway.core.attribute; import central.data.saas.Application; -import central.data.saas.ApplicationModule; +import central.data.saas.ApplicationRoute; import central.data.saas.Tenant; import central.studio.gateway.core.body.EmptyBody; import central.studio.gateway.core.body.HttpResponseBody; @@ -80,9 +80,9 @@ public interface ExchangeAttributes { Attribute RESPONSE_BODY = Attribute.of(ExchangeAttributes.class.getName() + ".response_body", EmptyBody::new); /** - * 网关转发的目标应用模块 + * 网关转发的目标应用路由 */ - Attribute TARGET_APPLICATION_MODULE = Attribute.of(ExchangeAttributes.class.getName() + ".target_application_module"); + Attribute TARGET_APPLICATION_ROUTE = Attribute.of(ExchangeAttributes.class.getName() + ".target_application_route"); /** * 网关实际转发地址 diff --git a/central-gateway/src/main/java/central/studio/gateway/core/filter/global/ApplicationDispatcherFilter.java b/central-gateway/src/main/java/central/studio/gateway/core/filter/global/ApplicationDispatcherFilter.java index 476f8c7e..b0f9768d 100644 --- a/central-gateway/src/main/java/central/studio/gateway/core/filter/global/ApplicationDispatcherFilter.java +++ b/central-gateway/src/main/java/central/studio/gateway/core/filter/global/ApplicationDispatcherFilter.java @@ -25,7 +25,7 @@ package central.studio.gateway.core.filter.global; import central.bean.Orderable; -import central.data.saas.ApplicationModule; +import central.data.saas.ApplicationRoute; import central.data.saas.Tenant; import central.studio.gateway.core.filter.FilterChain; import central.studio.gateway.core.filter.GlobalFilter; @@ -112,11 +112,11 @@ public Mono filter(ServerWebExchange exchange, FilterChain chain) { var target = application.getApplication(); - ApplicationModule module = null; + ApplicationRoute route = null; - if (Listx.isNotEmpty(target.getModules())) { - // 是否有模块 - module = target.getModules() + if (Listx.isNotEmpty(target.getRoutes())) { + // 是否有路由 + route = target.getRoutes() .stream() .map(it -> { // 子应用的 contextPath 已经以应用的 contextPath 开头了 @@ -148,16 +148,16 @@ public Mono filter(ServerWebExchange exchange, FilterChain chain) { // 上下文路径 String contextPath; - if (module == null) { - // 没有子模块匹配上,那么就转发到主应用 + if (route == null) { + // 没有子路由匹配上,那么就转发到主应用 log.info("匹配应用成功[code: {}, name: {}, contextPath: {}, url: {}]", target.getCode(), target.getName(), target.getContextPath(), target.getUrl()); contextPath = target.getContextPath(); url = target.getUrl(); } else { - // 子模块匹配上了 - log.info("匹配应用模块成功[code: {}, name: {}, contextPath: {}, url: {}]", target.getCode(), target.getName(), module.getContextPath(), module.getUrl()); - contextPath = module.getContextPath(); - url = module.getUrl(); + // 子路由匹配上了 + log.info("匹配应用路由成功[code: {}, name: {}, contextPath: {}, url: {}]", target.getCode(), target.getName(), route.getContextPath(), route.getUrl()); + contextPath = route.getContextPath(); + url = route.getUrl(); } if (exchange.getRequest().getPath().value().equals(contextPath) && !exchange.getRequest().getPath().value().endsWith("/")) { @@ -189,8 +189,8 @@ public Mono filter(ServerWebExchange exchange, FilterChain chain) { // 将目标应用放到 Attributes,后面的 Filter 可以通过 Attributes 获取 exchange.setAttribute(ExchangeAttributes.TARGET_APPLICATION, target); - if (module != null) { - exchange.setAttribute(ExchangeAttributes.TARGET_APPLICATION_MODULE, module); + if (route != null) { + exchange.setAttribute(ExchangeAttributes.TARGET_APPLICATION_ROUTE, route); } exchange.getRequiredAttribute(ExchangeAttributes.TOKEN).withClaim(RegisteredClaims.ISSUER, "gateway"); diff --git a/central-gateway/src/main/java/central/studio/gateway/core/filter/global/routing/HttpRoutingFilter.java b/central-gateway/src/main/java/central/studio/gateway/core/filter/global/routing/HttpRoutingFilter.java index 09e5077c..2919f718 100644 --- a/central-gateway/src/main/java/central/studio/gateway/core/filter/global/routing/HttpRoutingFilter.java +++ b/central-gateway/src/main/java/central/studio/gateway/core/filter/global/routing/HttpRoutingFilter.java @@ -25,12 +25,12 @@ package central.studio.gateway.core.filter.global.routing; import central.data.saas.Application; -import central.studio.gateway.core.filter.Filter; -import central.studio.gateway.core.filter.FilterChain; +import central.starter.web.reactive.extension.ServerWebExchangex; import central.studio.gateway.core.attribute.ExchangeAttributes; import central.studio.gateway.core.body.ConnectionBody; +import central.studio.gateway.core.filter.Filter; +import central.studio.gateway.core.filter.FilterChain; import central.web.XForwardedHeaders; -import central.starter.web.reactive.extension.ServerWebExchangex; import com.auth0.jwt.algorithms.Algorithm; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; diff --git a/central-provider/src/main/java/central/studio/provider/database/initialization/MasterTenantInitializer.java b/central-provider/src/main/java/central/studio/provider/database/initialization/MasterTenantInitializer.java index 792962c4..11b8f279 100644 --- a/central-provider/src/main/java/central/studio/provider/database/initialization/MasterTenantInitializer.java +++ b/central-provider/src/main/java/central/studio/provider/database/initialization/MasterTenantInitializer.java @@ -82,6 +82,7 @@ private Map initApplications() throws IOException { dashboardApp.setSecret("glngxOUCye6fndsaiQI"); dashboardApp.setEnabled(Boolean.TRUE); dashboardApp.setRemark("用于提供套件中所有应用的管理界面"); + dashboardApp.setRoutesJson("[]"); dashboardApp.updateCreator("syssa"); // Saas中心 @@ -95,6 +96,7 @@ private Map initApplications() throws IOException { saasApp.setSecret("btdHv1HdTTWzCEbiRdg"); saasApp.setEnabled(Boolean.TRUE); saasApp.setRemark("用于维护租户、应用系统以及其租用关系等"); + saasApp.setRoutesJson("[]"); saasApp.updateCreator("syssa"); // 认证中心 @@ -108,6 +110,7 @@ private Map initApplications() throws IOException { identityApp.setSecret("AkJSi2kmH7vSO5lJcvY"); identityApp.setEnabled(Boolean.TRUE); identityApp.setRemark("用于统一管理全局会话"); + identityApp.setRoutesJson("[]"); identityApp.updateCreator("syssa"); // 存储中心 @@ -121,6 +124,7 @@ private Map initApplications() throws IOException { storageApp.setSecret("IKJuAKOiG7Vx9tMMqUf"); storageApp.setEnabled(Boolean.TRUE); storageApp.setRemark("用于统一管理文件存储"); + storageApp.setRoutesJson("[]"); storageApp.updateCreator("syssa"); // 广播中心 @@ -134,6 +138,7 @@ private Map initApplications() throws IOException { multicastApp.setSecret("QHO85BzFQq8hqDzREJ"); multicastApp.setEnabled(Boolean.TRUE); multicastApp.setRemark("用于统一消息推送"); + multicastApp.setRoutesJson("[]"); multicastApp.updateCreator("syssa"); // 网关中心 @@ -147,6 +152,7 @@ private Map initApplications() throws IOException { gatewayApp.setSecret("TT6cdfpHIPastoipuDg"); gatewayApp.setEnabled(Boolean.TRUE); gatewayApp.setRemark("用于统一管理网关"); + gatewayApp.setRoutesJson("[]"); gatewayApp.updateCreator("syssa"); var applications = List.of(dashboardApp, saasApp, identityApp, storageApp, multicastApp, gatewayApp); diff --git a/central-provider/src/main/java/central/studio/provider/database/migration/v0/v0_0_1_initial.java b/central-provider/src/main/java/central/studio/provider/database/migration/v0/v0_0_1_initial.java index 0cce4c23..79561af6 100644 --- a/central-provider/src/main/java/central/studio/provider/database/migration/v0/v0_0_1_initial.java +++ b/central-provider/src/main/java/central/studio/provider/database/migration/v0/v0_0_1_initial.java @@ -403,6 +403,7 @@ public void upgrade(Database database) throws SQLException { Column.of("SECRET", SqlType.STRING, 128, "密钥"), Column.of("ENABLED", SqlType.BOOLEAN, "是否启用"), Column.of("REMARK", SqlType.STRING, 1024, "备注"), + Column.of("ROUTES_JSON", SqlType.CLOB, "路由"), Column.of("CREATOR_ID", SqlType.STRING, 36, "创建人主键"), Column.of("CREATE_DATE", SqlType.DATETIME, "创建时间"), Column.of("MODIFIER_ID", SqlType.STRING, 36, "更新人主键"), @@ -417,29 +418,6 @@ public void upgrade(Database database) throws SQLException { database.addTable(table); } - { - // 应用模块 - var columns = List.of( - Column.of("ID", true, SqlType.STRING, 32, "主键"), - Column.of("APPLICATION_ID", SqlType.STRING, 32, "所属应用主键"), - Column.of("URL", SqlType.STRING, 1024, "服务地址"), - Column.of("CONTEXT_PATH", SqlType.STRING, 64, "上下文地址"), - Column.of("ENABLED", SqlType.BOOLEAN, "是否启用"), - Column.of("REMARK", SqlType.STRING, 1024, "备注"), - Column.of("CREATOR_ID", SqlType.STRING, 36, "创建人主键"), - Column.of("CREATE_DATE", SqlType.DATETIME, "创建时间"), - Column.of("MODIFIER_ID", SqlType.STRING, 36, "更新人主键"), - Column.of("MODIFY_DATE", SqlType.DATETIME, "更新时间") - ); - - var indies = List.of( - Index.of("X_TAM_AI", false, "APPLICATION_ID") - ); - - var table = Table.of("X_SAAS_APPLICATION_MODULE", "应用模块", columns, indies); - - database.addTable(table); - } { // 租户 var columns = List.of( @@ -584,11 +562,6 @@ public void downgrade(Database database) throws SQLException { application.drop(); } - var applicationModule = database.getTable("X_SAAS_APPLICATION_MODULE"); - if (applicationModule != null) { - applicationModule.drop(); - } - var tenant = database.getTable("X_SAAS_TENANT"); if (tenant != null) { tenant.drop(); diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationDTO.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationDTO.java index fe2a6cde..85e0f6e4 100644 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationDTO.java +++ b/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationDTO.java @@ -24,24 +24,22 @@ package central.studio.provider.graphql.saas.dto; -import central.provider.graphql.DTO; +import central.data.saas.ApplicationRoute; import central.lang.Arrayx; -import central.studio.provider.graphql.saas.entity.ApplicationEntity; -import central.studio.provider.graphql.organization.dto.AccountDTO; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.studio.provider.graphql.saas.query.ApplicationModuleQuery; -import central.sql.query.Conditions; -import central.sql.query.Orders; +import central.lang.Stringx; +import central.lang.reflect.TypeRef; +import central.provider.graphql.DTO; import central.starter.graphql.annotation.GraphQLGetter; import central.starter.graphql.annotation.GraphQLType; -import central.web.XForwardedHeaders; +import central.studio.provider.graphql.organization.dto.AccountDTO; +import central.studio.provider.graphql.saas.entity.ApplicationEntity; +import central.util.Jsonx; import lombok.EqualsAndHashCode; import org.dataloader.DataLoader; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestHeader; import java.io.Serial; import java.util.Base64; +import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -71,12 +69,15 @@ public String getLogo() { } /** - * 获取模块 + * 获取路由 */ @GraphQLGetter - public List getModules(@Autowired ApplicationModuleQuery query, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - return query.findBy(null, null, Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getApplicationId, this.getId()), Orders.of(ApplicationModuleEntity.class).asc(ApplicationModuleEntity::getContextPath), tenant); + public List getRoutes() { + if (Stringx.isNullOrEmpty(this.getRoutesJson())) { + return Collections.emptyList(); + } + + return Jsonx.Default().deserialize(this.getRoutesJson(), TypeRef.ofList(ApplicationRoute.class)); } /** diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationModuleDTO.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationModuleDTO.java deleted file mode 100644 index 0738cbbb..00000000 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/dto/ApplicationModuleDTO.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-present Alan Yeh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package central.studio.provider.graphql.saas.dto; - -import central.provider.graphql.DTO; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.studio.provider.graphql.organization.dto.AccountDTO; -import central.starter.graphql.annotation.GraphQLGetter; -import central.starter.graphql.annotation.GraphQLType; -import lombok.EqualsAndHashCode; -import org.dataloader.DataLoader; - -import java.io.Serial; -import java.util.concurrent.CompletableFuture; - -/** - * 应用模块 - * - * @author Alan Yeh - * @see central.data.saas.ApplicationModule - * @since 2022/09/25 - */ -@GraphQLType("ApplicationModule") -@EqualsAndHashCode(callSuper = true) -public class ApplicationModuleDTO extends ApplicationModuleEntity implements DTO { - @Serial - private static final long serialVersionUID = 5867692886591067864L; - - /** - * 获取应用 - */ - @GraphQLGetter - public CompletableFuture getApplication(DataLoader loader) { - return loader.load(this.getApplicationId()); - } - - /** - * 创建人信息 - */ - @GraphQLGetter - public CompletableFuture getCreator(DataLoader loader) { - return loader.load(this.getCreatorId()); - } - - /** - * 修改人信息 - */ - @GraphQLGetter - public CompletableFuture getModifier(DataLoader loader) { - return loader.load(this.getModifierId()); - } -} diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationEntity.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationEntity.java index dc012e67..d916ab53 100644 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationEntity.java +++ b/central-provider/src/main/java/central/studio/provider/graphql/saas/entity/ApplicationEntity.java @@ -27,6 +27,9 @@ import central.data.saas.ApplicationInput; import central.lang.Stringx; import central.sql.data.ModifiableEntity; +import central.util.Collectionx; +import central.util.Jsonx; +import central.util.Objectx; import central.validation.Label; import jakarta.persistence.Id; import jakarta.persistence.Table; @@ -105,6 +108,10 @@ public class ApplicationEntity extends ModifiableEntity { @Size(max = 1024) private String remark; + @Label("路由") + @Size(max = 5 * 1024 * 1024) + private String routesJson; + public void fromInput(ApplicationInput input) { this.setId(input.getId()); this.setCode(input.getCode()); @@ -122,5 +129,6 @@ public void fromInput(ApplicationInput input) { this.setSecret(input.getSecret()); this.setEnabled(input.getEnabled()); this.setRemark(input.getRemark()); + this.setRoutesJson(Jsonx.Default().serialize(Objectx.getOrDefault(input.getRoutes(), Collectionx.emptyList()))); } } diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/mapper/ApplicationModuleMapper.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/mapper/ApplicationModuleMapper.java deleted file mode 100644 index a6e95e3b..00000000 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/mapper/ApplicationModuleMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-present Alan Yeh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package central.studio.provider.graphql.saas.mapper; - -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.sql.proxy.Mapper; -import org.springframework.stereotype.Repository; - -/** - * 应用模块 - * - * @author Alan Yeh - * @since 2022/09/25 - */ -@Repository -public interface ApplicationModuleMapper extends Mapper { -} diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationModuleMutation.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationModuleMutation.java deleted file mode 100644 index 1806b57b..00000000 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationModuleMutation.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-present Alan Yeh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package central.studio.provider.graphql.saas.mutation; - -import central.provider.graphql.DTO; -import central.data.saas.ApplicationModuleInput; -import central.lang.Assertx; -import central.lang.Stringx; -import central.studio.provider.graphql.saas.dto.ApplicationModuleDTO; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.studio.provider.graphql.saas.mapper.ApplicationModuleMapper; -import central.sql.query.Conditions; -import central.starter.graphql.annotation.GraphQLFetcher; -import central.starter.graphql.annotation.GraphQLSchema; -import central.web.XForwardedHeaders; -import central.util.Listx; -import central.validation.group.Insert; -import central.validation.group.Update; -import jakarta.annotation.Nonnull; -import jakarta.validation.groups.Default; -import lombok.Setter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Component; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.server.ResponseStatusException; - -import java.util.List; - -/** - * ApplicationModule Mutation - *

- * 应用模块修改 - * - * @author Alan Yeh - * @since 2022/10/03 - */ -@Component -@GraphQLSchema(path = "saas/mutation", types = ApplicationModuleDTO.class) -public class ApplicationModuleMutation { - @Setter(onMethod_ = @Autowired) - private ApplicationModuleMapper mapper; - - /** - * 保存数据 - * - * @param input 数据输入 - * @param operator 操作人 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull ApplicationModuleDTO insert(@RequestParam @Validated({Insert.class, Default.class}) ApplicationModuleInput input, - @RequestParam String operator, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - - var entity = new ApplicationModuleEntity(); - entity.fromInput(input); - entity.updateCreator(operator); - this.mapper.insert(entity); - - return DTO.wrap(entity, ApplicationModuleDTO.class); - } - - /** - * 批量保存数据 - * - * @param inputs 数据输入 - * @param operator 操作人 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull List insertBatch(@RequestParam @Validated({Insert.class, Default.class}) List inputs, - @RequestParam String operator, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - return Listx.asStream(inputs).map(it -> this.insert(it, operator, tenant)).toList(); - } - - /** - * 更新数据 - * - * @param input 数据输入 - * @param operator 操作人 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull ApplicationModuleDTO update(@RequestParam @Validated({Update.class, Default.class}) ApplicationModuleInput input, - @RequestParam String operator, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - var entity = this.mapper.findFirstBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getId, input.getId())); - if (entity == null) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, Stringx.format("数据[id={}]不存在", input.getId())); - } - - entity.fromInput(input); - entity.updateModifier(operator); - this.mapper.update(entity); - - return DTO.wrap(entity, ApplicationModuleDTO.class); - } - - /** - * 批量更新数据 - * - * @param inputs 数据输入 - * @param operator 操作人 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull List updateBatch(@RequestParam @Validated({Update.class, Default.class}) List inputs, - @RequestParam String operator, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - return Listx.asStream(inputs).map(it -> this.update(it, operator, tenant)).toList(); - } - - /** - * 根据主键删除数据 - * - * @param ids 主键 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public long deleteByIds(@RequestParam List ids, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - if (Listx.isNullOrEmpty(ids)) { - return 0; - } - - return this.mapper.deleteByIds(ids); - } - - /** - * 根据条件删除数据 - * - * @param conditions 条件 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public long deleteBy(@RequestParam Conditions conditions, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - return this.mapper.deleteBy(conditions); - } -} diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationMutation.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationMutation.java index 19f9d467..5a119e17 100644 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationMutation.java +++ b/central-provider/src/main/java/central/studio/provider/graphql/saas/mutation/ApplicationMutation.java @@ -24,23 +24,20 @@ package central.studio.provider.graphql.saas.mutation; -import central.provider.graphql.DTO; import central.data.saas.ApplicationInput; import central.lang.Assertx; import central.lang.Stringx; -import central.studio.provider.graphql.saas.dto.ApplicationDTO; -import central.studio.provider.graphql.saas.entity.ApplicationEntity; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.studio.provider.graphql.saas.entity.TenantApplicationEntity; -import central.studio.provider.graphql.saas.mapper.ApplicationMapper; +import central.provider.graphql.DTO; import central.sql.query.Conditions; import central.starter.graphql.annotation.GraphQLFetcher; -import central.starter.graphql.annotation.GraphQLGetter; import central.starter.graphql.annotation.GraphQLSchema; -import central.web.XForwardedHeaders; +import central.studio.provider.graphql.saas.dto.ApplicationDTO; +import central.studio.provider.graphql.saas.entity.ApplicationEntity; +import central.studio.provider.graphql.saas.mapper.ApplicationMapper; import central.util.Listx; import central.validation.group.Insert; import central.validation.group.Update; +import central.web.XForwardedHeaders; import jakarta.annotation.Nonnull; import jakarta.validation.groups.Default; import lombok.Setter; @@ -64,8 +61,9 @@ * @since 2022/10/03 */ @Component -@GraphQLSchema(path = "saas/mutation", types = {ApplicationDTO.class, ApplicationModuleMutation.class}) +@GraphQLSchema(path = "saas/mutation", types = ApplicationDTO.class) public class ApplicationMutation { + @Setter(onMethod_ = @Autowired) private ApplicationMapper mapper; @@ -164,20 +162,13 @@ public class ApplicationMutation { @GraphQLFetcher public long deleteByIds(@RequestParam List ids, @RequestHeader(XForwardedHeaders.TENANT) String tenant, - @Autowired ApplicationModuleMutation moduleMutation, @Autowired TenantApplicationMutation mutation) { Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); if (Listx.isNullOrEmpty(ids)) { return 0L; } - var effected = this.mapper.deleteByIds(ids); - if (effected > 0L) { - // 级联删除 - moduleMutation.deleteBy(Conditions.of(ApplicationModuleEntity.class).in(ApplicationModuleEntity::getApplicationId, ids), tenant); - mutation.deleteBy(Conditions.of(TenantApplicationEntity.class).in(TenantApplicationEntity::getApplicationId, ids), tenant); - } - return effected; + return this.mapper.deleteByIds(ids); } /** @@ -188,32 +179,12 @@ public long deleteByIds(@RequestParam List ids, */ @GraphQLFetcher public long deleteBy(@RequestParam Conditions conditions, - @RequestHeader(XForwardedHeaders.TENANT) String tenant, - @Autowired ApplicationModuleMutation moduleMutation, - @Autowired TenantApplicationMutation mutation) { + @RequestHeader(XForwardedHeaders.TENANT) String tenant) { Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); var entities = this.mapper.findBy(conditions); if (entities.isEmpty()) { return 0L; } - var effected = this.mapper.deleteBy(conditions); - // 级联删除 - var ids = entities.stream().map(ApplicationEntity::getId).toList(); - moduleMutation.deleteBy(Conditions.of(ApplicationModuleEntity.class).in(ApplicationModuleEntity::getApplicationId, ids), tenant); - mutation.deleteBy(Conditions.of(TenantApplicationEntity.class).in(TenantApplicationEntity::getApplicationId, ids), tenant); - return effected; - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // 关联查询 - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /** - * Application Module Mutation - * 模块修改 - */ - @GraphQLGetter - public ApplicationModuleMutation getModules(@Autowired ApplicationModuleMutation mutation) { - return mutation; + return this.mapper.deleteBy(conditions); } } diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationModuleQuery.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationModuleQuery.java deleted file mode 100644 index ec398cb7..00000000 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationModuleQuery.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-present Alan Yeh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package central.studio.provider.graphql.saas.query; - -import central.bean.Page; -import central.lang.Assertx; -import central.provider.graphql.DTO; -import central.studio.provider.graphql.saas.dto.ApplicationModuleDTO; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.studio.provider.graphql.saas.mapper.ApplicationModuleMapper; -import central.sql.query.Conditions; -import central.sql.query.Orders; -import central.starter.graphql.annotation.GraphQLBatchLoader; -import central.starter.graphql.annotation.GraphQLFetcher; -import central.starter.graphql.annotation.GraphQLSchema; -import central.web.XForwardedHeaders; -import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; -import lombok.Setter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * ApplicationModule Query - *

- * 应用模块查询 - * - * @author Alan Yeh - * @since 2022/10/03 - */ -@Component -@GraphQLSchema(path = "saas/query", types = ApplicationModuleDTO.class) -public class ApplicationModuleQuery { - @Setter(onMethod_ = @Autowired) - private ApplicationModuleMapper mapper; - - /** - * 批量数据加载器 - * - * @param ids 主键 - * @param tenant 租户标识 - */ - @GraphQLBatchLoader - public @Nonnull Map batchLoader(@RequestParam List ids, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - return this.mapper.findByIds(ids) - .stream() - .map(it -> DTO.wrap(it, ApplicationModuleDTO.class)) - .collect(Collectors.toMap(ApplicationModuleDTO::getId, it -> it)); - } - - /** - * 根据主键查询数据 - * - * @param id 主键 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nullable ApplicationModuleDTO findById(@RequestParam String id, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - var entity = this.mapper.findById(id); - return DTO.wrap(entity, ApplicationModuleDTO.class); - } - - - /** - * 查询数据 - * - * @param ids 主键 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull List findByIds(@RequestParam List ids, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - var entities = this.mapper.findByIds(ids); - - return DTO.wrap(entities, ApplicationModuleDTO.class); - } - - /** - * 查询数据 - * - * @param limit 获取前 N 条数据 - * @param offset 偏移量 - * @param conditions 过滤条件 - * @param orders 排序条件 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull List findBy(@RequestParam(required = false) Long limit, - @RequestParam(required = false) Long offset, - @RequestParam Conditions conditions, - @RequestParam Orders orders, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - var list = this.mapper.findBy(limit, offset, conditions, orders); - return DTO.wrap(list, ApplicationModuleDTO.class); - } - - /** - * 分页查询数据 - * - * @param pageIndex 分页下标 - * @param pageSize 分页大小 - * @param conditions 过滤条件 - * @param orders 排序条件 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public @Nonnull Page pageBy(@RequestParam long pageIndex, - @RequestParam long pageSize, - @RequestParam Conditions conditions, - @RequestParam Orders orders, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - var page = this.mapper.findPageBy(pageIndex, pageSize, conditions, orders); - return DTO.wrap(page, ApplicationModuleDTO.class); - } - - /** - * 查询符合条件的数据数量 - * - * @param conditions 筛选条件 - * @param tenant 租户标识 - */ - @GraphQLFetcher - public Long countBy(@RequestParam Conditions conditions, - @RequestHeader(XForwardedHeaders.TENANT) String tenant) { - Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); - return this.mapper.countBy(conditions); - } -} diff --git a/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationQuery.java b/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationQuery.java index 97225730..27bba764 100644 --- a/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationQuery.java +++ b/central-provider/src/main/java/central/studio/provider/graphql/saas/query/ApplicationQuery.java @@ -27,15 +27,14 @@ import central.bean.Page; import central.lang.Assertx; import central.provider.graphql.DTO; -import central.studio.provider.graphql.saas.dto.ApplicationDTO; -import central.studio.provider.graphql.saas.entity.ApplicationEntity; -import central.studio.provider.graphql.saas.mapper.ApplicationMapper; import central.sql.query.Conditions; import central.sql.query.Orders; import central.starter.graphql.annotation.GraphQLBatchLoader; import central.starter.graphql.annotation.GraphQLFetcher; -import central.starter.graphql.annotation.GraphQLGetter; import central.starter.graphql.annotation.GraphQLSchema; +import central.studio.provider.graphql.saas.dto.ApplicationDTO; +import central.studio.provider.graphql.saas.entity.ApplicationEntity; +import central.studio.provider.graphql.saas.mapper.ApplicationMapper; import central.web.XForwardedHeaders; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; @@ -58,7 +57,7 @@ * @since 2022/10/03 */ @Component -@GraphQLSchema(path = "saas/query", types = {ApplicationDTO.class, ApplicationModuleQuery.class}) +@GraphQLSchema(path = "saas/query", types = ApplicationDTO.class) public class ApplicationQuery { @Setter(onMethod_ = @Autowired) private ApplicationMapper mapper; @@ -161,17 +160,4 @@ public Long countBy(@RequestParam Conditions conditions, Assertx.mustEquals("master", tenant, "只有主租户[master]才允许访问本接口"); return this.mapper.countBy(conditions); } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // 关联查询 - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /** - * Application Module Query - * 模块查询 - */ - @GraphQLGetter - public ApplicationModuleQuery getModules(@Autowired ApplicationModuleQuery query) { - return query; - } } diff --git a/central-provider/src/main/resources/central/graphql/saas/mutation/applicationModuleMutation.graphql b/central-provider/src/main/resources/central/graphql/saas/mutation/applicationModuleMutation.graphql deleted file mode 100644 index 9baff1cf..00000000 --- a/central-provider/src/main/resources/central/graphql/saas/mutation/applicationModuleMutation.graphql +++ /dev/null @@ -1,79 +0,0 @@ -""" -应用模块输入 -""" -input ApplicationModuleInput { - "主键" - id: ID - "应用主键" - applicationId: String - "服务地址" - url: String - "上下文路径" - contextPath: String - "是否启用" - enabled: String - "备注" - remark: String -} - -""" -应用模块修改 -""" -type ApplicationModuleMutation { - - """ - 保存数据 - """ - insert( - "数据输入" - input: ApplicationModuleInput, - "操作人" - operator: String - ): ApplicationModule - - """ - 批量保存数据 - """ - insertBatch( - "数据输入" - inputs: [ApplicationModuleInput], - "操作人" - operator: String - ): [ApplicationModule] - - """ - 更新数据 - """ - update( - "数据输入" - input: ApplicationModuleInput, - "操作人" - operator: String - ): ApplicationModule - - """ - 批量更新数据 - """ - updateBatch( - "数据输入" - inputs: [ApplicationModuleInput], - "操作人" - operator: String - ): [ApplicationModule] - - """ - 删除数据 - """ - deleteByIds( - "主键" - ids: [String] - ): Long - - """ - 删除数据 - """ - deleteBy( - "筛选条件" - conditions: [ConditionInput] = [] - ): Long -} \ No newline at end of file diff --git a/central-provider/src/main/resources/central/graphql/saas/mutation/applicationMutation.graphql b/central-provider/src/main/resources/central/graphql/saas/mutation/applicationMutation.graphql index 1a69cefc..57ec4b9c 100644 --- a/central-provider/src/main/resources/central/graphql/saas/mutation/applicationMutation.graphql +++ b/central-provider/src/main/resources/central/graphql/saas/mutation/applicationMutation.graphql @@ -10,28 +10,38 @@ input ApplicationInput { name: String "图标(Base64)" logo: String - "服务地址" - url: String "上下文路径" contextPath: String + "服务地址" + url: String "密钥" secret: String "是否启用" enabled: Boolean "备注" remark: String - "应用模块" - modules: [ApplicationModuleInput] + "应用路由" + routes: [ApplicationRouteInput] +} + +""" +应用路由输入 +""" +input ApplicationRouteInput { + "上下文路径" + contextPath: String + "服务地址" + url: String + "是否启用" + enabled: String + "备注" + remark: String } """ 应用修改 """ type ApplicationMutation { - """ - 模块修改 - """ - modules: ApplicationModuleMutation """ 保存数据 diff --git a/central-provider/src/main/resources/central/graphql/saas/query/applicationModuleQuery.graphql b/central-provider/src/main/resources/central/graphql/saas/query/applicationModuleQuery.graphql deleted file mode 100644 index 742cb9a4..00000000 --- a/central-provider/src/main/resources/central/graphql/saas/query/applicationModuleQuery.graphql +++ /dev/null @@ -1,89 +0,0 @@ -""" -应用模块 -""" -type ApplicationModule implements Entity & Modifiable { - "主键" - id: ID! - "应用主键" - applicationId: String! - "应用" - application: Application! - "服务地址" - url: String! - "上下文路径" - contextPath: String! - "是否启用" - enabled: Boolean! - "备注" - remark: String - - "创建帐户信息" - creator: Account! - "创建帐户主键" - creatorId: String! - "创建时间" - createDate: Timestamp! - "修改帐户信息" - modifier: Account! - "修改帐户主键" - modifierId: String! - "修改时间" - modifyDate: Timestamp! -} - -""" -应用模块查询 -""" -type ApplicationModuleQuery { - """ - 查询数据 - """ - findById( - "主键" - id: String - ): ApplicationModule - - """ - 查询数据 - """ - findByIds( - "主键" - ids: [String] - ): [ApplicationModule] - - """ - 查询数据 - """ - findBy( - "数据量(不传的话,就返回所有数据)" - limit: Long, - "偏移量(跳过前 N 条数据)" - offset: Long, - "筛选条件" - conditions: [ConditionInput] = [], - "数据列表" - orders: [OrderInput] = [] - ): [ApplicationModule] - - """ - 查询数据 - """ - pageBy( - "分页下标,从 1 开始" - pageIndex: Long, - "分页大小,最小值为 1,最大值为 100" - pageSize: Long, - "筛选条件" - conditions: [ConditionInput] = [], - "排序条件" - orders: [OrderInput] = [] - ): Page - - """ - 查询符合条件的数据数量 - """ - countBy( - "筛选条件" - conditions: [ConditionInput] = [] - ): Long -} \ No newline at end of file diff --git a/central-provider/src/main/resources/central/graphql/saas/query/applicationQuery.graphql b/central-provider/src/main/resources/central/graphql/saas/query/applicationQuery.graphql index 5315803d..e3115787 100644 --- a/central-provider/src/main/resources/central/graphql/saas/query/applicationQuery.graphql +++ b/central-provider/src/main/resources/central/graphql/saas/query/applicationQuery.graphql @@ -10,18 +10,18 @@ type Application implements Entity & Modifiable & Codeable & Available { name: String! "图标(Base64)" logo: String - "服务地址" - url: String "上下文路径" contextPath: String! + "服务地址" + url: String "密钥" secret: String! "是否启用" enabled: Boolean! "备注" remark: String - "应用模块" - modules: [ApplicationModule] + "应用路由" + routes: [ApplicationRoute] "创建帐户信息" creator: Account! @@ -37,14 +37,24 @@ type Application implements Entity & Modifiable & Codeable & Available { modifyDate: Timestamp! } +""" +应用路由 +""" +type ApplicationRoute { + "上下文路径" + contextPath: String! + "服务地址" + url: String! + "是否启用" + enabled: Boolean! + "备注" + remark: String +} + """ 应用查询 """ type ApplicationQuery { - """ - 模块查询 - """ - modules: ApplicationModuleQuery """ 查询数据 diff --git a/central-provider/src/test/java/central/studio/provider/graphql/authority/TestMenuProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/authority/TestMenuProvider.java index 9e73d75e..ad47c732 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/authority/TestMenuProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/authority/TestMenuProvider.java @@ -100,6 +100,7 @@ public void case1() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -183,6 +184,7 @@ public void case2() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -270,6 +272,7 @@ public void case3() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -357,6 +360,7 @@ public void case4() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -448,6 +452,7 @@ public void case5() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -516,6 +521,7 @@ public void case6() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -558,6 +564,7 @@ public void case7() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -601,6 +608,7 @@ public void case8() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -651,6 +659,7 @@ public void case9() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -705,6 +714,7 @@ public void case10() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -744,6 +754,7 @@ public void case11() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/authority/TestPermissionProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/authority/TestPermissionProvider.java index ec1fcd6f..6b6b61b6 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/authority/TestPermissionProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/authority/TestPermissionProvider.java @@ -99,6 +99,7 @@ public void case1() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -157,6 +158,7 @@ public void case2() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -219,6 +221,7 @@ public void case4() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -285,6 +288,7 @@ public void case5() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -332,6 +336,7 @@ public void case6() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -381,6 +386,7 @@ public void case7() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -433,6 +439,7 @@ public void case8() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -492,6 +499,7 @@ public void case9() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -555,6 +563,7 @@ public void case10() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -603,6 +612,7 @@ public void case11() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/authority/TestRoleProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/authority/TestRoleProvider.java index 5f5d3c3a..3e1a8fd9 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/authority/TestRoleProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/authority/TestRoleProvider.java @@ -106,6 +106,7 @@ public void case1() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -171,6 +172,7 @@ public void case2() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -240,6 +242,7 @@ public void case3() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -309,6 +312,7 @@ public void case4() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -382,6 +386,7 @@ public void case5() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -436,6 +441,7 @@ public void case6() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -502,6 +508,7 @@ public void case7() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -572,6 +579,7 @@ public void case8() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -649,6 +657,7 @@ public void case9() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -728,6 +737,7 @@ public void case10() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -784,6 +794,7 @@ public void case11() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastBroadcasterProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastBroadcasterProvider.java index 4cd6cb1c..b10a91f9 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastBroadcasterProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastBroadcasterProvider.java @@ -101,6 +101,7 @@ public void clear() throws Exception { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastMessageProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastMessageProvider.java index 15eb291d..0f342876 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastMessageProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/multicast/TestMulticastMessageProvider.java @@ -105,6 +105,7 @@ public void clear() throws Exception { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationModuleProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationModuleProvider.java deleted file mode 100644 index 9af21a4f..00000000 --- a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationModuleProvider.java +++ /dev/null @@ -1,656 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-present Alan Yeh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package central.studio.provider.graphql.saas; - -import central.data.saas.ApplicationModule; -import central.data.saas.ApplicationModuleInput; -import central.provider.graphql.saas.ApplicationModuleProvider; -import central.sql.query.Conditions; -import central.sql.query.Orders; -import central.studio.provider.ProviderApplication; -import central.studio.provider.ProviderProperties; -import central.studio.provider.graphql.TestProvider; -import central.studio.provider.graphql.saas.entity.ApplicationEntity; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; -import central.studio.provider.graphql.saas.mapper.ApplicationMapper; -import central.studio.provider.graphql.saas.mapper.ApplicationModuleMapper; -import central.util.Guidx; -import central.util.Listx; -import lombok.Setter; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * Application Module Provider Test Cases - * 应用模块 - * - * @author Alan Yeh - * @since 2022/10/06 - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = ProviderApplication.class) -public class TestApplicationModuleProvider extends TestProvider { - @Setter(onMethod_ = @Autowired) - private ApplicationModuleProvider provider; - - @Setter(onMethod_ = @Autowired) - private ProviderProperties properties; - - @Setter(onMethod_ = @Autowired) - private ApplicationMapper applicationMapper; - - @Setter(onMethod_ = @Autowired) - private ApplicationModuleMapper mapper; - - @BeforeEach - @AfterEach - public void clear() { - // 清空数据 - applicationMapper.deleteAll(); - mapper.deleteAll(); - } - - /** - * @see ApplicationModuleProvider#findById - */ - @Test - public void case1() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - // 查询数据 - var module = this.provider.findById(module1.getId(), "master"); - assertNotNull(module); - assertEquals(module1.getId(), module.getId()); - assertEquals(module1.getApplicationId(), module.getApplicationId()); - assertNotNull(module.getApplication()); - // 关联查询 - assertEquals(entity.getCode(), module.getApplication().getCode()); - assertEquals(entity.getName(), module.getApplication().getName()); - assertEquals(entity.getEnabled(), module.getApplication().getEnabled()); - - assertEquals(module1.getUrl(), module.getUrl()); - assertEquals(module1.getContextPath(), module.getContextPath()); - assertEquals(module1.getEnabled(), module.getEnabled()); - assertEquals(module1.getRemark(), module.getRemark()); - } - - /** - * @see ApplicationModuleProvider#findByIds - */ - @Test - public void case2() { - var entity = new ApplicationEntity(); - entity.setCode("central-security"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - // 查询数据 - var result = this.provider.findByIds(List.of(module1.getId()), "master"); - var module = Listx.getFirstOrNull(result); - assertNotNull(module); - assertEquals(module1.getId(), module.getId()); - assertEquals(module1.getApplicationId(), module.getApplicationId()); - assertNotNull(module.getApplication()); - // 关联查询 - assertEquals(entity.getCode(), module.getApplication().getCode()); - assertEquals(entity.getName(), module.getApplication().getName()); - assertEquals(entity.getEnabled(), module.getApplication().getEnabled()); - - assertEquals(module1.getUrl(), module.getUrl()); - assertEquals(module1.getContextPath(), module.getContextPath()); - assertEquals(module1.getEnabled(), module.getEnabled()); - assertEquals(module1.getRemark(), module.getRemark()); - } - - /** - * @see ApplicationModuleProvider#findBy - */ - @Test - public void case3() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - // 查询数据 - var result = this.provider.findBy(1L, 0L, Conditions.of(ApplicationModule.class).eq("application.code", "central-identity"), Orders.of(ApplicationModule.class).asc(ApplicationModule::getContextPath), "master"); - assertNotNull(result); - assertEquals(1, result.size()); - - var module = result.stream().filter(it -> Objects.equals(module2.getId(), it.getId())).findFirst().orElse(null); - assertNotNull(module); - assertEquals(module2.getId(), module.getId()); - assertEquals(module2.getApplicationId(), module.getApplicationId()); - assertNotNull(module.getApplication()); - // 关联查询 - assertEquals(entity.getCode(), module.getApplication().getCode()); - assertEquals(entity.getName(), module.getApplication().getName()); - assertEquals(entity.getEnabled(), module.getApplication().getEnabled()); - - assertEquals(module2.getUrl(), module.getUrl()); - assertEquals(module2.getContextPath(), module.getContextPath()); - assertEquals(module2.getEnabled(), module.getEnabled()); - assertEquals(module2.getRemark(), module.getRemark()); - } - - /** - * @see ApplicationModuleProvider#pageBy - */ - @Test - public void case4() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - // 查询数据 - var page = this.provider.pageBy(1L, 20L, Conditions.of(ApplicationModule.class).eq("application.code", "central-identity"), null, "master"); - assertNotNull(page); - assertNotNull(page.getPager()); - assertEquals(1L, page.getPager().getPageIndex()); - assertEquals(20L, page.getPager().getPageSize()); - assertEquals(1L, page.getPager().getPageCount()); - assertEquals(2L, page.getPager().getItemCount()); - assertNotNull(page.getData()); - - var module = page.getData().stream().filter(it -> Objects.equals(module1.getId(), it.getId())).findFirst().orElse(null); - assertNotNull(module); - assertEquals(module1.getId(), module.getId()); - assertEquals(module1.getApplicationId(), module.getApplicationId()); - assertNotNull(module.getApplication()); - // 关联查询 - assertEquals(entity.getCode(), module.getApplication().getCode()); - assertEquals(entity.getName(), module.getApplication().getName()); - assertEquals(entity.getEnabled(), module.getApplication().getEnabled()); - - assertEquals(module1.getUrl(), module.getUrl()); - assertEquals(module1.getContextPath(), module.getContextPath()); - assertEquals(module1.getEnabled(), module.getEnabled()); - assertEquals(module1.getRemark(), module.getRemark()); - } - - /** - * @see ApplicationModuleProvider#countBy - */ - @Test - public void case5() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - // 查询数据 - var count = this.provider.countBy(Conditions.of(ApplicationModule.class).eq("application.code", "central-identity"), "master"); - assertEquals(2L, count); - } - - /** - * @see ApplicationModuleProvider#insert - */ - @Test - public void case6() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var input = ApplicationModuleInput.builder() - .applicationId(entity.getId()) - .url("http://127.0.0.1:3110") - .contextPath("/identity/test") - .enabled(Boolean.TRUE) - .remark("测试模块1") - .build(); - - var inserted = this.provider.insert(input, properties.getSupervisor().getUsername(), "master"); - assertNotNull(inserted); - assertNotNull(inserted.getId()); - assertEquals(input.getApplicationId(), inserted.getApplicationId()); - assertNotNull(inserted.getApplication()); - // 关联查询 - assertEquals(entity.getCode(), inserted.getApplication().getCode()); - assertEquals(entity.getName(), inserted.getApplication().getName()); - assertEquals(entity.getEnabled(), inserted.getApplication().getEnabled()); - - assertEquals(input.getUrl(), inserted.getUrl()); - assertEquals(input.getContextPath(), inserted.getContextPath()); - assertEquals(input.getEnabled(), inserted.getEnabled()); - assertEquals(input.getRemark(), inserted.getRemark()); - - // 检查数据库 - assertTrue(this.mapper.existsBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getId, inserted.getId()))); - } - - /** - * @see ApplicationModuleProvider#insertBatch - */ - @Test - public void case7() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var input = ApplicationModuleInput.builder() - .applicationId(entity.getId()) - .url("http://127.0.0.1:3110") - .contextPath("/identity/test") - .enabled(Boolean.TRUE) - .remark("测试模块1") - .build(); - - var inserted = this.provider.insertBatch(List.of(input), properties.getSupervisor().getUsername(), "master"); - assertNotNull(inserted); - assertEquals(1, inserted.size()); - - var module = Listx.getFirstOrNull(inserted); - assertNotNull(module); - - assertNotNull(module.getId()); - assertEquals(input.getApplicationId(), module.getApplicationId()); - assertNotNull(module.getApplication()); - // 关联查询 - assertEquals(entity.getCode(), module.getApplication().getCode()); - assertEquals(entity.getName(), module.getApplication().getName()); - assertEquals(entity.getEnabled(), module.getApplication().getEnabled()); - - assertEquals(input.getUrl(), module.getUrl()); - assertEquals(input.getContextPath(), module.getContextPath()); - assertEquals(input.getEnabled(), module.getEnabled()); - assertEquals(input.getRemark(), module.getRemark()); - - // 检查数据库 - assertTrue(this.mapper.existsBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getId, module.getId()))); - } - - /** - * @see ApplicationModuleProvider#update - */ - @Test - public void case8() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - var module = this.provider.findById(module1.getId(), "master"); - assertNotNull(module); - - var input = module.toInput().toBuilder() - .url("http://127.0.0.1:4100") - .build(); - - module = this.provider.update(input, properties.getSupervisor().getUsername(), "master"); - assertEquals(input.getId(), module.getId()); - assertEquals(input.getApplicationId(), module.getApplicationId()); - assertEquals(input.getUrl(), module.getUrl()); - assertEquals(input.getContextPath(), module.getContextPath()); - assertEquals(input.getEnabled(), module.getEnabled()); - assertEquals(input.getRemark(), module.getRemark()); - } - - /** - * @see ApplicationModuleProvider#updateBatch - */ - @Test - public void case9() { - var entity = new ApplicationEntity(); - entity.setCode("central-security"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - var module = this.provider.findById(module1.getId(), "master"); - assertNotNull(module); - - var input = module.toInput().toBuilder() - .url("http://127.0.0.1:4100") - .build(); - - var updated = this.provider.updateBatch(List.of(input), properties.getSupervisor().getUsername(), "master"); - assertNotNull(updated); - assertEquals(1, updated.size()); - - module = Listx.getFirstOrNull(updated); - assertNotNull(module); - assertEquals(input.getId(), module.getId()); - assertEquals(input.getApplicationId(), module.getApplicationId()); - assertEquals(input.getUrl(), module.getUrl()); - assertEquals(input.getContextPath(), module.getContextPath()); - assertEquals(input.getEnabled(), module.getEnabled()); - assertEquals(input.getRemark(), module.getRemark()); - } - - /** - * @see ApplicationModuleProvider#deleteByIds - */ - @Test - public void case10() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - var deleted = this.provider.deleteByIds(List.of(module1.getId()), "master"); - assertNotNull(deleted); - assertEquals(1L, deleted); - - assertFalse(this.mapper.existsBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getId, entity.getId()))); - } - - /** - * @see ApplicationModuleProvider#deleteBy - */ - @Test - public void case11() { - var entity = new ApplicationEntity(); - entity.setCode("central-identity"); - entity.setName("统一认证中心"); - entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); - entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/identity"); - entity.setSecret(Guidx.nextID()); - entity.setEnabled(Boolean.TRUE); - entity.setRemark("用于所有应用的认证处理"); - entity.updateCreator(properties.getSupervisor().getUsername()); - this.applicationMapper.insert(entity); - - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.FALSE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.mapper.insertBatch(modules); - - var deleted = this.provider.deleteBy(Conditions.of(ApplicationModule.class).eq(ApplicationModule::getEnabled, Boolean.FALSE), "master"); - assertNotNull(deleted); - assertEquals(1L, deleted); - - assertFalse(this.mapper.existsBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getId, module2.getId()))); - } -} diff --git a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationProvider.java index 0cdf7991..5f39157e 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestApplicationProvider.java @@ -26,16 +26,16 @@ import central.data.saas.Application; import central.data.saas.ApplicationInput; +import central.data.saas.ApplicationRouteInput; import central.provider.graphql.saas.ApplicationProvider; import central.sql.query.Conditions; import central.studio.provider.ProviderApplication; import central.studio.provider.ProviderProperties; import central.studio.provider.graphql.TestProvider; import central.studio.provider.graphql.saas.entity.ApplicationEntity; -import central.studio.provider.graphql.saas.entity.ApplicationModuleEntity; import central.studio.provider.graphql.saas.mapper.ApplicationMapper; -import central.studio.provider.graphql.saas.mapper.ApplicationModuleMapper; import central.util.Guidx; +import central.util.Jsonx; import central.util.Listx; import lombok.Setter; import org.junit.jupiter.api.AfterEach; @@ -45,7 +45,6 @@ import org.springframework.boot.test.context.SpringBootTest; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.Objects; @@ -71,15 +70,11 @@ public class TestApplicationProvider extends TestProvider { @Setter(onMethod_ = @Autowired) private ApplicationMapper mapper; - @Setter(onMethod_ = @Autowired) - private ApplicationModuleMapper moduleMapper; - @BeforeEach @AfterEach public void clear() { // 清空数据 mapper.deleteAll(); - moduleMapper.deleteAll(); } /** @@ -96,30 +91,14 @@ public void case1() { entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - // 查询数据 var application = this.provider.findById(entity.getId(), "master"); assertNotNull(application); @@ -131,10 +110,10 @@ public void case1() { assertEquals(entity.getSecret(), application.getSecret()); assertEquals(entity.getEnabled(), application.getEnabled()); assertEquals(entity.getRemark(), application.getRemark()); - assertNotNull(application.getModules()); - assertEquals(2, application.getModules().size()); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module1.getId(), it.getId()))); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module2.getId(), it.getId()))); + assertNotNull(application.getRoutes()); + assertEquals(2, application.getRoutes().size()); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/test", it.getContextPath()))); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/example", it.getContextPath()))); } /** @@ -143,38 +122,22 @@ public void case1() { @Test public void case2() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - // 查询数据 var applications = this.provider.findByIds(List.of(entity.getId()), "master"); var application = Listx.getFirstOrNull(applications); @@ -187,10 +150,10 @@ public void case2() { assertEquals(entity.getSecret(), application.getSecret()); assertEquals(entity.getEnabled(), application.getEnabled()); assertEquals(entity.getRemark(), application.getRemark()); - assertNotNull(application.getModules()); - assertEquals(2, application.getModules().size()); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module1.getId(), it.getId()))); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module2.getId(), it.getId()))); + assertNotNull(application.getRoutes()); + assertEquals(2, application.getRoutes().size()); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/test", it.getContextPath()))); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/example", it.getContextPath()))); } /** @@ -199,40 +162,24 @@ public void case2() { @Test public void case3() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - // 查询数据 - var applications = this.provider.findBy(1L, 0L, Conditions.of(Application.class).eq(Application::getCode, "central-security"), null, "master"); + var applications = this.provider.findBy(1L, 0L, Conditions.of(Application.class).eq(Application::getCode, "central-identity"), null, "master"); var application = Listx.getFirstOrNull(applications); assertNotNull(application); assertEquals(entity.getId(), application.getId()); @@ -243,10 +190,10 @@ public void case3() { assertEquals(entity.getSecret(), application.getSecret()); assertEquals(entity.getEnabled(), application.getEnabled()); assertEquals(entity.getRemark(), application.getRemark()); - assertNotNull(application.getModules()); - assertEquals(2, application.getModules().size()); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module1.getId(), it.getId()))); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module2.getId(), it.getId()))); + assertNotNull(application.getRoutes()); + assertEquals(2, application.getRoutes().size()); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/test", it.getContextPath()))); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/example", it.getContextPath()))); } /** @@ -255,40 +202,24 @@ public void case3() { @Test public void case4() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - // 查询数据 - var page = this.provider.pageBy(1L, 20L, Conditions.of(Application.class).eq(Application::getCode, "central-security"), null, "master"); + var page = this.provider.pageBy(1L, 20L, Conditions.of(Application.class).eq(Application::getCode, "central-identity"), null, "master"); assertNotNull(page); assertNotNull(page.getPager()); assertEquals(1L, page.getPager().getPageIndex()); @@ -306,10 +237,10 @@ public void case4() { assertEquals(entity.getSecret(), application.getSecret()); assertEquals(entity.getEnabled(), application.getEnabled()); assertEquals(entity.getRemark(), application.getRemark()); - assertNotNull(application.getModules()); - assertEquals(2, application.getModules().size()); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module1.getId(), it.getId()))); - assertTrue(application.getModules().stream().anyMatch(it -> Objects.equals(module2.getId(), it.getId()))); + assertNotNull(application.getRoutes()); + assertEquals(2, application.getRoutes().size()); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/test", it.getContextPath()))); + assertTrue(application.getRoutes().stream().anyMatch(it -> Objects.equals("/identity/example", it.getContextPath()))); } /** @@ -318,40 +249,24 @@ public void case4() { @Test public void case5() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - // 查询数据 - var count = this.provider.countBy(Conditions.of(Application.class).eq(Application::getCode, "central-security"), "master"); + var count = this.provider.countBy(Conditions.of(Application.class).eq(Application::getCode, "central-identity"), "master"); assertEquals(1L, count); } @@ -369,6 +284,10 @@ public void case6() { .secret(Guidx.nextID()) .enabled(Boolean.TRUE) .remark("用于所有应用的认证处理") + .routes(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + )) .build(); var application = this.provider.insert(input, properties.getSupervisor().getUsername(), "master"); assertNotNull(application); @@ -407,6 +326,10 @@ public void case7() { .secret(Guidx.nextID()) .enabled(Boolean.TRUE) .remark("用于所有应用的认证处理") + .routes(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + )) .build(); var applications = this.provider.insertBatch(List.of(input), properties.getSupervisor().getUsername(), "master"); assertNotNull(applications); @@ -423,6 +346,7 @@ public void case7() { assertEquals(input.getSecret(), application.getSecret()); assertEquals(input.getEnabled(), application.getEnabled()); assertEquals(input.getRemark(), application.getRemark()); + assertEquals(2, application.getRoutes().size()); application = this.provider.findById(application.getId(), "master"); assertNotNull(application); @@ -434,6 +358,7 @@ public void case7() { assertEquals(input.getSecret(), application.getSecret()); assertEquals(input.getEnabled(), application.getEnabled()); assertEquals(input.getRemark(), application.getRemark()); + assertEquals(2, application.getRoutes().size()); } /** @@ -442,38 +367,22 @@ public void case7() { @Test public void case8() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - var application = this.provider.findById(entity.getId(), "master"); assertNotNull(application); @@ -499,38 +408,22 @@ public void case8() { @Test public void case9() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - var application = this.provider.findById(entity.getId(), "master"); assertNotNull(application); @@ -558,45 +451,27 @@ public void case9() { @Test public void case10() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - var deleted = this.provider.deleteByIds(List.of(entity.getId()), "master"); assertNotNull(deleted); assertEquals(1L, deleted); assertFalse(this.mapper.existsBy(Conditions.of(ApplicationEntity.class).eq(ApplicationEntity::getId, entity.getId()))); - // 模块需要关联删除 - assertFalse(this.moduleMapper.existsBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getApplicationId, entity.getId()))); } /** @@ -605,44 +480,26 @@ public void case10() { @Test public void case11() { var entity = new ApplicationEntity(); - entity.setCode("central-security"); + entity.setCode("central-identity"); entity.setName("统一认证中心"); entity.setLogoBytes("1234".getBytes(StandardCharsets.UTF_8)); entity.setUrl("http://127.0.0.1:3100"); - entity.setContextPath("/security"); + entity.setContextPath("/identity"); entity.setSecret(Guidx.nextID()); entity.setEnabled(Boolean.TRUE); entity.setRemark("用于所有应用的认证处理"); + entity.setRoutesJson(Jsonx.Default().serialize(List.of( + ApplicationRouteInput.builder().contextPath("/identity/test").url("http://127.0.0.1:3110").enabled(Boolean.TRUE).remark("测试路由1").build(), + ApplicationRouteInput.builder().contextPath("/identity/example").url("http://127.0.0.1:3120").enabled(Boolean.TRUE).remark("测试路由2").build() + ))); + entity.updateCreator(properties.getSupervisor().getUsername()); this.mapper.insert(entity); - var modules = new ArrayList(); - - var module1 = new ApplicationModuleEntity(); - module1.setApplicationId(entity.getId()); - module1.setUrl("http://127.0.0.1:3110"); - module1.setContextPath("/identity/test"); - module1.setEnabled(Boolean.TRUE); - module1.setRemark("测试模块1"); - module1.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module1); - - var module2 = new ApplicationModuleEntity(); - module2.setApplicationId(entity.getId()); - module2.setUrl("http://127.0.0.1:3120"); - module2.setContextPath("/identity/example"); - module2.setEnabled(Boolean.TRUE); - module2.setRemark("测试模块2"); - module2.updateCreator(properties.getSupervisor().getUsername()); - modules.add(module2); - this.moduleMapper.insertBatch(modules); - - var deleted = this.provider.deleteBy(Conditions.of(Application.class).eq(Application::getCode, "central-security"), "master"); + var deleted = this.provider.deleteBy(Conditions.of(Application.class).eq(Application::getCode, "central-identity"), "master"); assertNotNull(deleted); assertEquals(1L, deleted); assertFalse(this.mapper.existsBy(Conditions.of(ApplicationEntity.class).eq(ApplicationEntity::getId, entity.getId()))); - // 模块需要关联删除 - assertFalse(this.moduleMapper.existsBy(Conditions.of(ApplicationModuleEntity.class).eq(ApplicationModuleEntity::getApplicationId, entity.getId()))); } } diff --git a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantApplicationProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantApplicationProvider.java index e83ef342..52f242fb 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantApplicationProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantApplicationProvider.java @@ -104,6 +104,7 @@ private ApplicationEntity buildApplication() { application.setSecret(Guidx.nextID()); application.setEnabled(Boolean.TRUE); application.setRemark("统一认证"); + application.setRoutesJson("[]"); application.updateCreator(properties.getSupervisor().getUsername()); return application; } diff --git a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantProvider.java index 00702c70..429fca5d 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/saas/TestTenantProvider.java @@ -103,6 +103,7 @@ private ApplicationEntity buildApplication() { application.setSecret(Guidx.nextID()); application.setEnabled(Boolean.TRUE); application.setRemark("统一认证"); + application.setRoutesJson("[]"); application.updateCreator(properties.getSupervisor().getUsername()); return application; } diff --git a/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageBucketProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageBucketProvider.java index 78c183d4..61731086 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageBucketProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageBucketProvider.java @@ -104,6 +104,7 @@ public void clear() throws Exception { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageObjectProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageObjectProvider.java index ee58640e..4acb9521 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageObjectProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/storage/TestStorageObjectProvider.java @@ -109,6 +109,7 @@ public void clear() throws Exception { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("用于所有应用的认证处理"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/system/TestDatabaseProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/system/TestDatabaseProvider.java index 4e4c71c4..895c2d85 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/system/TestDatabaseProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/system/TestDatabaseProvider.java @@ -96,7 +96,8 @@ public void clear() throws Exception { applicationEntity.setContextPath("/security"); applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); - applicationEntity.setRemark("统一认班上"); + applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-provider/src/test/java/central/studio/provider/graphql/system/TestDictionaryProvider.java b/central-provider/src/test/java/central/studio/provider/graphql/system/TestDictionaryProvider.java index 67aab690..785197c4 100644 --- a/central-provider/src/test/java/central/studio/provider/graphql/system/TestDictionaryProvider.java +++ b/central-provider/src/test/java/central/studio/provider/graphql/system/TestDictionaryProvider.java @@ -94,6 +94,7 @@ public void case1() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -151,6 +152,7 @@ public void case2() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -213,6 +215,7 @@ public void case3() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -275,6 +278,7 @@ public void case4() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -342,6 +346,7 @@ public void case5() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -383,6 +388,7 @@ public void case6() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -419,6 +425,7 @@ public void case7() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -456,6 +463,7 @@ public void case8() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -505,6 +513,7 @@ public void case9() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -555,6 +564,7 @@ public void case10() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); @@ -597,6 +607,7 @@ public void case11() { applicationEntity.setSecret(Guidx.nextID()); applicationEntity.setEnabled(Boolean.TRUE); applicationEntity.setRemark("统一认证"); + applicationEntity.setRoutesJson("[]"); applicationEntity.updateCreator(properties.getSupervisor().getUsername()); this.applicationMapper.insert(applicationEntity); diff --git a/central-studio-library/src/main/java/central/data/saas/Application.java b/central-studio-library/src/main/java/central/data/saas/Application.java index a6fc9ca7..826b31f4 100644 --- a/central-studio-library/src/main/java/central/data/saas/Application.java +++ b/central-studio-library/src/main/java/central/data/saas/Application.java @@ -100,11 +100,10 @@ public class Application extends ModifiableEntity implements Codeable, Available private String remark; /** - * 应用模块 + * 路由 */ @Nonnull - @JsonInclude(JsonInclude.Include.NON_NULL) - private List modules; + private List routes; /** * 创建人信息 @@ -131,7 +130,7 @@ public ApplicationInput toInput() { .secret(this.getSecret()) .enabled(this.getEnabled()) .remark(this.getRemark()) - .modules(Listx.asStream(this.getModules()).map(ApplicationModule::toInput).toList()) + .routes(Listx.asStream(this.getRoutes()).map(ApplicationRoute::toInput).toList()) .build(); } } diff --git a/central-studio-library/src/main/java/central/data/saas/ApplicationInput.java b/central-studio-library/src/main/java/central/data/saas/ApplicationInput.java index 42bc276c..4ef0fe0d 100644 --- a/central-studio-library/src/main/java/central/data/saas/ApplicationInput.java +++ b/central-studio-library/src/main/java/central/data/saas/ApplicationInput.java @@ -101,6 +101,6 @@ public class ApplicationInput implements Serializable { private String remark; @Valid - @Label("模块") - private List modules; + @Label("路由") + private List routes; } diff --git a/central-studio-library/src/main/java/central/data/saas/ApplicationModule.java b/central-studio-library/src/main/java/central/data/saas/ApplicationRoute.java similarity index 66% rename from central-studio-library/src/main/java/central/data/saas/ApplicationModule.java rename to central-studio-library/src/main/java/central/data/saas/ApplicationRoute.java index 5c19d083..f48c1931 100644 --- a/central-studio-library/src/main/java/central/data/saas/ApplicationModule.java +++ b/central-studio-library/src/main/java/central/data/saas/ApplicationRoute.java @@ -24,44 +24,39 @@ package central.data.saas; -import central.bean.*; -import central.data.organization.Account; -import central.sql.data.ModifiableEntity; -import com.fasterxml.jackson.annotation.JsonInclude; +import central.bean.Available; +import central.bean.Nonnull; +import central.bean.Remarkable; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import java.io.Serial; +import java.io.Serializable; /** - * 应用模块 + * Application Route + *

+ * 应用路由 * * @author Alan Yeh * @since 2022/09/25 */ @Data +@Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class ApplicationModule extends ModifiableEntity implements Available, Remarkable { +public class ApplicationRoute implements Serializable, Available, Remarkable { @Serial private static final long serialVersionUID = -4968804715373126621L; /** - * 应用主键 - */ - @Nonnull - private String applicationId; - - /** - * 应用信息 + * 上下文路径 */ @Nonnull - @JsonInclude(JsonInclude.Include.NON_NULL) - private Application application; + private String contextPath; /** * 服务地址 @@ -69,12 +64,6 @@ public class ApplicationModule extends ModifiableEntity implements Available, Re @Nonnull private String url; - /** - * 上下文路径 - */ - @Nonnull - private String contextPath; - /** * 是否启用 */ @@ -84,29 +73,13 @@ public class ApplicationModule extends ModifiableEntity implements Available, Re /** * 备注 */ - @Nullable - private String remark; - - /** - * 创建人信息 - */ @Nonnull - @JsonInclude(JsonInclude.Include.NON_NULL) - private Account creator; - - /** - * 修改人信息 - */ - @Nonnull - @JsonInclude(JsonInclude.Include.NON_NULL) - private Account modifier; + private String remark; - public ApplicationModuleInput toInput() { - return ApplicationModuleInput.builder() - .id(this.getId()) - .url(this.getUrl()) + public ApplicationRouteInput toInput() { + return ApplicationRouteInput.builder() .contextPath(this.getContextPath()) - .applicationId(this.getApplicationId()) + .url(this.getUrl()) .enabled(this.getEnabled()) .remark(this.getRemark()) .build(); diff --git a/central-studio-library/src/main/java/central/data/saas/ApplicationModuleInput.java b/central-studio-library/src/main/java/central/data/saas/ApplicationRouteInput.java similarity index 72% rename from central-studio-library/src/main/java/central/data/saas/ApplicationModuleInput.java rename to central-studio-library/src/main/java/central/data/saas/ApplicationRouteInput.java index db0c54a1..fbf8531f 100644 --- a/central-studio-library/src/main/java/central/data/saas/ApplicationModuleInput.java +++ b/central-studio-library/src/main/java/central/data/saas/ApplicationRouteInput.java @@ -25,54 +25,59 @@ package central.data.saas; import central.validation.Label; -import central.validation.group.Insert; -import central.validation.group.Update; -import jakarta.validation.constraints.*; -import lombok.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; import java.io.Serial; import java.io.Serializable; /** - * 应用模块输入 + * Application Route + *

+ * 应用路由 * * @author Alan Yeh - * @since 2022/09/25 + * @since 2024/12/10 */ @Data -@Builder(toBuilder = true) -@EqualsAndHashCode +@Builder @NoArgsConstructor @AllArgsConstructor -public class ApplicationModuleInput implements Serializable { +public class ApplicationRouteInput implements Serializable { @Serial - private static final long serialVersionUID = -5378855445379690625L; + private static final long serialVersionUID = 2736131525653405558L; - @Label("主键") - @Null(groups = Insert.class) - @NotBlank(groups = Update.class) - @Size(min = 1, max = 32, groups = Insert.class) - private String id; - - @Label("所属应用主键") + /** + * 上下文路径 + */ + @Label("上下文路径") @NotBlank - @Size(min = 1, max = 32) - private String applicationId; + @Size(min = 1, max = 64) + private String contextPath; + /** + * 服务地址 + */ @Label("服务地址") @NotBlank @Size(min = 1, max = 1024) private String url; - @Label("上下文路径") - @NotBlank - @Size(min = 1, max = 64) - private String contextPath; - + /** + * 是否启用 + */ @Label("是否启用") @NotNull private Boolean enabled; + /** + * 备注 + */ @Label("备注") @Size(max = 1024) private String remark; diff --git a/central-studio-library/src/main/java/central/provider/graphql/saas/ApplicationModuleProvider.java b/central-studio-library/src/main/java/central/provider/graphql/saas/ApplicationModuleProvider.java deleted file mode 100644 index 98358ea0..00000000 --- a/central-studio-library/src/main/java/central/provider/graphql/saas/ApplicationModuleProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-present Alan Yeh - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package central.provider.graphql.saas; - -import central.data.saas.ApplicationModule; -import central.data.saas.ApplicationModuleInput; -import central.starter.graphql.stub.ModifiableProvider; -import central.starter.graphql.stub.annotation.BodyPath; -import central.starter.graphql.stub.annotation.GraphQLStub; -import org.springframework.stereotype.Repository; - -/** - * 应用模块 - * - * @author Alan Yeh - * @since 2022/09/28 - */ -@Repository -@BodyPath("saas.applications.modules") -@GraphQLStub(path = "saas", client = "masterProviderClient") -public interface ApplicationModuleProvider extends ModifiableProvider { -} diff --git a/central-studio-library/src/main/resources/central/graphql/stub/authority/authorizationProvider.md b/central-studio-library/src/main/resources/central/graphql/stub/authority/authorizationProvider.md index 2287320c..a2b4a709 100644 --- a/central-studio-library/src/main/resources/central/graphql/stub/authority/authorizationProvider.md +++ b/central-studio-library/src/main/resources/central/graphql/stub/authority/authorizationProvider.md @@ -17,9 +17,7 @@ query AuthorizationProvider($code: String, $secret: String) { secret enabled remark - modules { - id - applicationId + routes { url contextPath enabled diff --git a/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationModuleProvider.md b/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationModuleProvider.md deleted file mode 100644 index ef98f973..00000000 --- a/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationModuleProvider.md +++ /dev/null @@ -1,460 +0,0 @@ -findById -=== - -* 根据主键查询数据 - -```graphql -query ApplicationModuleProvider($id: String) { - saas { - applications { - modules { - findById(id: $id) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -findByIds -=== - -* 根据主键查询数据 - -```graphql -query ApplicationModuleProvider($ids: [String]) { - saas { - applications { - modules { - findByIds(ids: $ids) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -findBy -=== - -* 根据条件查询数据 - -```graphql -query ApplicationModuleProvider($limit: Long, $offset: Long, $conditions: [ConditionInput], $orders: [OrderInput]) { - saas { - applications { - modules { - findBy(limit: $limit, offset: $offset, conditions: $conditions, orders: $orders) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -pageBy -=== - -* 分页查询数据 - -```graphql -query ApplicationModuleProvider($pageIndex: Long, $pageSize: Long, $conditions: [ConditionInput], $orders: [OrderInput]) { - saas { - applications { - modules { - pageBy(pageIndex: $pageIndex, pageSize: $pageSize, conditions: $conditions, orders: $orders){ - pager { - pageIndex - pageSize - pageCount - itemCount - } - data { - ... on ApplicationModule { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } - } - } -} -``` - -countBy -=== - -* 查询符合条件的数据数量 - -```graphql -query ApplicationModuleProvider($conditions: [ConditionInput]) { - saas { - applications { - modules { - countBy(conditions: $conditions) - } - } - } -} -``` - -insert -=== - -* 保存数据 - -```graphql -mutation ApplicationModuleProvider($input: ApplicationModuleInput, $operator: String) { - saas { - applications { - modules { - insert(input: $input, operator: $operator) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -insertBatch -=== - -* 批量保存数据 - -```graphql -mutation ApplicationModuleProvider($inputs: [ApplicationModuleInput], $operator: String) { - saas { - applications { - modules { - insertBatch(inputs: $inputs, operator: $operator) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -update -=== - -* 更新数据 - -```graphql -mutation ApplicationModuleProvider($input: ApplicationModuleInput, $operator: String) { - saas { - applications { - modules { - update(input: $input, operator: $operator) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -updateBatch -=== - -* 批量更新数据 - -```graphql -mutation ApplicationModuleProvider($inputs: [ApplicationModuleInput], $operator: String) { - saas { - applications { - modules { - updateBatch(inputs: $inputs, operator: $operator) { - id - applicationId - application { - id - code - name - logo - url - contextPath - secret - enabled - } - url - contextPath - enabled - remark - - creatorId - createDate - creator { - id - username - name - } - - modifierId - modifyDate - modifier { - id - username - name - } - } - } - } - } -} -``` - -deleteByIds -=== - -* 删除数据 - -```graphql -mutation ApplicationModuleProvider($ids: [String]) { - saas { - applications { - modules { - deleteByIds(ids: $ids) - } - } - } -} -``` - -deleteBy -=== - -* 删除数据 - -```graphql -mutation ApplicationModuleProvider($conditions: [ConditionInput]) { - saas { - applications { - modules { - deleteBy(conditions: $conditions) - } - } - } -} -``` \ No newline at end of file diff --git a/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationProvider.md b/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationProvider.md index c35c6f9d..141e583f 100644 --- a/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationProvider.md +++ b/central-studio-library/src/main/resources/central/graphql/stub/saas/applicationProvider.md @@ -17,11 +17,9 @@ query ApplicationProvider($id: String) { secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } @@ -66,15 +64,13 @@ query ApplicationProvider($ids: [String]) { secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } - + creatorId createDate creator { @@ -115,11 +111,9 @@ query ApplicationProvider($limit: Long, $offset: Long, $conditions: [ConditionIn secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } @@ -172,11 +166,9 @@ query ApplicationProvider($pageIndex: Long, $pageSize: Long, $conditions: [Condi secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } @@ -238,11 +230,9 @@ mutation ApplicationProvider($input: ApplicationInput, $operator: String) { secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } @@ -287,11 +277,9 @@ mutation ApplicationProvider($inputs: [ApplicationInput], $operator: String) { secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } @@ -336,11 +324,9 @@ mutation ApplicationProvider($input: ApplicationInput, $operator: String) { secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } @@ -385,11 +371,9 @@ mutation ApplicationProvider($inputs: [ApplicationInput], $operator: String) { secret enabled remark - modules { - id - applicationId - url + routes { contextPath + url enabled remark } diff --git a/central-studio-library/src/main/resources/central/graphql/stub/saas/tenantProvider.md b/central-studio-library/src/main/resources/central/graphql/stub/saas/tenantProvider.md index 771e3209..7b27ac6c 100644 --- a/central-studio-library/src/main/resources/central/graphql/stub/saas/tenantProvider.md +++ b/central-studio-library/src/main/resources/central/graphql/stub/saas/tenantProvider.md @@ -37,9 +37,7 @@ query TenantProvider($id: String) { contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled @@ -107,12 +105,11 @@ query TenantProvider($ids: [String]) { contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } } @@ -177,12 +174,11 @@ query TenantProvider($limit: Long, $offset: Long, $conditions: [ConditionInput], contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } } @@ -255,12 +251,11 @@ query TenantProvider($pageIndex: Long, $pageSize: Long, $conditions: [ConditionI contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } } @@ -342,12 +337,11 @@ mutation TenantProvider($input: TenantInput, $operator: String) { contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } } @@ -412,12 +406,11 @@ mutation TenantProvider($inputs: [TenantInput], $operator: String) { contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } } @@ -482,12 +475,11 @@ mutation TenantProvider($input: TenantInput, $operator: String) { contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } } @@ -552,12 +544,11 @@ mutation TenantProvider($inputs: [TenantInput], $operator: String) { contextPath secret enabled - modules { - id - applicationId + routes { url contextPath enabled + remark } } }