diff --git a/pjcloud-app-server/pjcloud-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports b/pjcloud-app-server/pjcloud-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports index 2c1b7d427..dd3586702 100644 --- a/pjcloud-app-server/pjcloud-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports +++ b/pjcloud-app-server/pjcloud-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports @@ -1 +1,2 @@ com.bsd.pjcloud.app.api.feign.RemoteAppUserService +com.bsd.pjcloud.app.api.feign.RemoteAppMenuService diff --git a/pjcloud-app-server/pjcloud-app-server-biz/src/main/java/com/bsd/pjcloud/app/controller/AppMenuController.java b/pjcloud-app-server/pjcloud-app-server-biz/src/main/java/com/bsd/pjcloud/app/controller/AppMenuController.java index cc276df23..a66f201d8 100755 --- a/pjcloud-app-server/pjcloud-app-server-biz/src/main/java/com/bsd/pjcloud/app/controller/AppMenuController.java +++ b/pjcloud-app-server/pjcloud-app-server-biz/src/main/java/com/bsd/pjcloud/app/controller/AppMenuController.java @@ -13,6 +13,7 @@ import com.bsd.pjcloud.app.api.entity.AppMenuEntity; import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum; import com.bsd.pjcloud.common.core.util.R; import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.common.security.annotation.Inner; import com.bsd.pjcloud.app.service.AppMenuService; import org.springframework.security.access.prepost.PreAuthorize; import com.bsd.pjcloud.common.excel.annotation.ResponseExcel; @@ -25,7 +26,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; -import java.util.Objects; /** * 菜单管理 @@ -47,6 +47,20 @@ public class AppMenuController { @Operation(summary = "分页查询", description = "分页查询") @GetMapping("/app/list") public R> appList(@ParameterObject AppMenuDto dto) { + return listVisibleAppMenus(dto); + } + + /** + * 服务间调用:与 {@link #appList} 数据一致,需 Feign 携带内部调用头(见 {@code @NoToken} 与 {@link Inner})。 + */ + @Inner(value = true) + @Operation(summary = "内部-App菜单列表", description = "供 integrated 等经 Feign 拉取,与 /app-menu/app/list 一致") + @GetMapping("/inner/app/list") + public R> innerAppList(@ParameterObject AppMenuDto dto) { + return listVisibleAppMenus(dto); + } + + private R> listVisibleAppMenus(AppMenuDto dto) { dto.setVisible(YesNoEnum.YES.getCode()); if (ObjectUtil.isNotEmpty(dto.getPlatformEnum())) { dto.setPlatform(dto.getPlatformEnum().getType()); diff --git a/pjcloud-integrated/pjcloud-integrated-biz/pom.xml b/pjcloud-integrated/pjcloud-integrated-biz/pom.xml index c64626fdd..35a41449b 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/pom.xml +++ b/pjcloud-integrated/pjcloud-integrated-biz/pom.xml @@ -91,6 +91,11 @@ pjcloud-thirdparty-api 5.7.0 + + com.bsd + pjcloud-app-server-api + 5.7.0 + com.bsd diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java new file mode 100644 index 000000000..5148dbadd --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java @@ -0,0 +1,73 @@ +package com.bsd.pjcloud.integrated.controller; + +import cn.hutool.core.util.StrUtil; +import com.bsd.pjcloud.app.api.constant.menu.AppMenuPlatformEnum; +import com.bsd.pjcloud.app.api.constant.menu.AppMenuTypeEnum; +import com.bsd.pjcloud.app.api.entity.AppMenuEntity; +import com.bsd.pjcloud.app.api.feign.RemoteAppMenuService; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.security.annotation.Inner; +import com.bsd.pjcloud.integrated.config.ExternalAppConfig; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * App 端菜单:开放路径凭 X-App-Id/Secret;已登录路径与 {@code /app-menu/app/list} 数据一致,经 Feign 调 app-server(租户头随 Feign 传递)。 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/appMenu") +@Tag(description = "appMenuOpen", name = "开放-App菜单") +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class AppMenuOpenController { + + private final ExternalAppConfig externalAppConfig; + private final RemoteAppMenuService remoteAppMenuService; + + /** + * 已登录(Bearer):与 app-server GET /app-menu/app/list 一致,走 integrated 统一前缀。 + */ + @Operation(summary = "App菜单列表", description = "需登录,转发 app-server 内部菜单接口") + @GetMapping("/app/list") + public R> appList( + @RequestParam(value = "typeEnum", required = false) AppMenuTypeEnum typeEnum, + @RequestParam(value = "platformEnum", required = false) AppMenuPlatformEnum platformEnum) { + return remoteAppMenuService.innerAppList(typeEnum, platformEnum); + } + + @Operation(summary = "开放-App菜单列表", description = "凭应用凭证访问,与 app-server /app-menu/app/list 数据一致") + @GetMapping("/open/app/list") + @Inner(value = false) + public R> openAppList( + @RequestHeader(value = "X-App-Id", required = false) String appId, + @RequestHeader(value = "X-App-Secret", required = false) String appSecret, + @RequestParam(value = "typeEnum", required = false) AppMenuTypeEnum typeEnum, + @RequestParam(value = "platformEnum", required = false) AppMenuPlatformEnum platformEnum) { + if (!isValidAppCredentials(appId, appSecret)) { + return R.failed("无效的应用ID或密钥"); + } + return remoteAppMenuService.innerAppList(typeEnum, platformEnum); + } + + private boolean isValidAppCredentials(String appId, String appSecret) { + if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) { + return false; + } + if (externalAppConfig.getApps() != null) { + return externalAppConfig.getApps().stream() + .filter(ExternalAppConfig.AppCredential::getEnabled) + .anyMatch(app -> appId.equals(app.getAppId()) && appSecret.equals(app.getAppSecret())); + } + return false; + } +}