Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions mateclaw-server/src/main/java/vip/mate/config/OpenApiConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package vip.mate.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
* SpringDoc OpenAPI 全局配置。
* <p>
* 项目已依赖 springdoc-openapi-starter-webmvc-ui(见根 pom 的
* {@code springdoc.version}),但此前没有任何 OpenAPI 配置 Bean,导致
* Swagger UI 缺少标题/描述、缺少安全方案(Authorize 按钮不可用)。
* 本类补齐这些全局元信息,让现有 Controller 上已有的
* {@code @Tag} / {@code @Operation} 注解直接可用。
*
* <h3>安全方案</h3>
* 两种 token 都通过标准 {@code Authorization: Bearer <token>} 头传入,
* {@link JwtAuthFilter} 按 token 前缀分发:JWT 以 {@code eyJ} 开头,
* Personal Access Token 以 {@code mc_} 开头(PAT_PREFIX)。因此 Swagger
* UI 的 Authorize 按钮只需填入任意一种 token 即可。
*
* <h3>注意:Swagger 当前公开可访问</h3>
* {@link SecurityConfig#filterChain} 中 {@code /api/**} 要求认证,但
* {@code /swagger-ui*}、{@code /v3/api-docs*}、{@code /webjars/**} 落到
* {@code .anyRequest().permitAll()},即 Swagger UI 当前是公开的。如生产环境
* 需要收口,应在 SecurityConfig 显式加规则,而不是改本类。
*
* <h3>未做的事(与「全局配置 + 安全方案」范围一致)</h3>
* 不逐个 Controller 补 {@code @Parameter} / {@code @ApiResponse} /
* {@code @Schema} / 公开端点的 {@code @SecurityRequirements({})} opt-out。
* 这些属于「关键端点注解」增强档,留作后续。
*
* @author MateClaw Team
*/
@Configuration
public class OpenApiConfig {

/** HTTP Bearer 安全方案的引用键,与 {@link Components#getSecuritySchemes()} 中的登记名一致。 */
public static final String BEARER_AUTH = "bearerAuth";

@Bean
public OpenAPI mateclawOpenAPI(
@Value("${mateclaw.openapi.title:MateClaw REST API}") String title,
@Value("${mateclaw.openapi.description:#{null}}") String description,
@Value("${mateclaw.openapi.version:1.0}") String version,
@Value("${mateclaw.openapi.server-url:}") String serverUrl) {

Info info = new Info()
.title(title)
.version(version)
.description(defaultIfBlank(description, ""
+ "MateClaw 多用户 AI Agent 平台的 REST API。"
+ "所有业务端点使用 /api/v1 前缀,绝大多数 JSON 响应走 {code,msg,data} 统一信封。"
+ "点击右上角 Authorize 并粘贴 JWT 或 Personal Access Token (mc_) 即可调试受保护端点。"
+ "完整人读文档见部署地址的 /docs 页面。"));

Components components = new Components()
.addSecuritySchemes(BEARER_AUTH, bearerScheme(
"JWT 或 Personal Access Token。两种都通过 Authorization: Bearer <token> 头传入,"
+ "服务端按前缀分发:JWT 以 eyJ 开头,PAT 以 mc_ 开头。"
+ "EventSource 不支持自定义请求头,SSE 流式端点可用 ?token=<token> 查询参数替代。"));

OpenAPI openAPI = new OpenAPI()
.info(info)
.components(components)
// 默认所有端点需要鉴权;公开端点(登录、SSE 等)在 SecurityConfig 中放行,
// Swagger 上会仍标注锁图标,但不影响实际调用。
.addSecurityItem(new SecurityRequirement().addList(BEARER_AUTH));

if (serverUrl != null && !serverUrl.isBlank()) {
openAPI.servers(List.of(new Server().url(serverUrl)));
}
// serverUrl 为空时不显式配置 —— SpringDoc 默认从请求 host 推导,
// 避免「Try it out」打到错误地址。

return openAPI;
}

private SecurityScheme bearerScheme(String description) {
return new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description(description);
}

private static String defaultIfBlank(String value, String fallback) {
return (value == null || value.isBlank()) ? fallback : value;
}
}
14 changes: 14 additions & 0 deletions mateclaw-server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,16 @@ mybatis-plus:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl

# SpringDoc OpenAPI
# 注意:/swagger-ui*、/v3/api-docs*、/webjars/** 落在 SecurityConfig 的
# .anyRequest().permitAll(),即 Swagger UI 当前公开可访问。如生产需要收口,
# 在 SecurityConfig 加显式规则(不要在此处配)。
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
# 把单个嵌套 query 参数对象(如分页 wrapper)拍平成独立字段,减少 schema 噪音
default-flat-param-object: true

# MateClaw 自定义配置
mateclaw:
Expand All @@ -131,6 +136,15 @@ mateclaw:
# Set this when agents deliver download links to channels/clients that cannot
# resolve a relative URL (IM messages, copied links, external downloads).
public-base-url: ${MATECLAW_PUBLIC_BASE_URL:}
openapi:
# SpringDoc OpenAPI 元信息(驱动 /swagger-ui.html 与 /v3/api-docs)。
# server-url 留空时由 SpringDoc 从请求 host 推导,避免 Try it out 打到错误地址。
# 生产若需固定,通过 MATECLAW_OPENAPI_SERVER_URL 覆盖(如 https://mate.example.com)。
title: ${MATECLAW_OPENAPI_TITLE:MateClaw REST API}
version: ${MATECLAW_OPENAPI_VERSION:1.0}
server-url: ${MATECLAW_OPENAPI_SERVER_URL:}
# description 留空则使用 OpenApiConfig 中的内置默认描述
description: ${MATECLAW_OPENAPI_DESCRIPTION:}
jwt:
secret: ${JWT_SECRET:MateClaw-JWT-Secret-Key-2024-Please-Change-In-Production}
expiration: 86400000
Expand Down
Loading