Skip to content
Merged
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Rename Portal user management contracts from `Portal User Management` to `User Management`.

### Added

- Add Consumer Token support notes to user management contracts, including `ManageUsers`-guarded user lookup and mutation operations.
- Add typed consumer management request, detail, and summary schemas with `allowManageUsers` and `rateLimitEnabled` flags.

## [0.3.5] - 2026-05-31

### Added
Expand Down
211 changes: 193 additions & 18 deletions apollo-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ info:
<pre><code class="language-bash">curl -X GET "http://localhost:8070/openapi/v1/apps" \
-H "Authorization: your_token_here"</code></pre>

version: 0.3.5
version: 0.3.6
security:
- ApiKeyAuth: []
tags:
Expand Down Expand Up @@ -48,8 +48,8 @@ tags:
description: AccessKey管理相关接口,包括AccessKey的创建、查询、删除、启用、禁用等操作
- name: Permission Management
description: 权限管理相关接口,包括权限查询等功能
- name: Portal User Management
description: Portal用户管理相关接口,主要供Portal UI在用户登录态下调用
- name: User Management
description: 用户管理相关接口,支持Portal用户登录态和具备用户管理权限的Consumer Token调用
- name: Portal Management
description: Portal UI 登录态管理接口,主要供当前版本 Portal 前端调用
paths:
Expand Down Expand Up @@ -4869,7 +4869,7 @@ paths:
deprecated: false
description: GET /openapi/v1/user
tags:
- Portal User Management
- User Management
responses:
'200':
description: 成功获取当前用户
Expand All @@ -4891,12 +4891,12 @@ paths:
$ref: '#/components/schemas/ExceptionResponse'
/openapi/v1/users:
get:
summary: 搜索Portal用户(new added)
summary: 搜索用户(new added)
operationId: searchUsers
deprecated: false
description: GET /openapi/v1/users
description: GET /openapi/v1/users,支持Portal用户登录态或具备ManageUsers权限的Consumer Token访问
tags:
- Portal User Management
- User Management
parameters:
- name: keyword
in: query
Expand Down Expand Up @@ -4943,18 +4943,18 @@ paths:
schema:
$ref: '#/components/schemas/ExceptionResponse'
'403':
description: 仅支持Portal用户登录态访问
description: 权限不足
content:
application/json:
schema:
$ref: '#/components/schemas/ExceptionResponse'
post:
summary: 创建或更新Portal用户(new added)
summary: 创建或更新用户(new added)
operationId: createOrUpdateUser
deprecated: false
description: POST /openapi/v1/users
description: POST /openapi/v1/users,Portal用户登录态使用当前登录用户作为operator;Consumer Token访问时需要具备ManageUsers权限并传入有效operator
tags:
- Portal User Management
- User Management
parameters:
- name: isCreate
in: query
Expand All @@ -4963,6 +4963,12 @@ paths:
schema:
type: boolean
default: false
- name: operator
in: query
description: 操作人用户名,Consumer Token访问时必填且必须是已存在用户;Portal用户登录态会忽略该参数
required: false
schema:
type: string
requestBody:
content:
application/json:
Expand All @@ -4984,14 +4990,61 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ExceptionResponse'
/openapi/v1/users/{userId}:
get:
summary: 获取指定用户(new added)
operationId: getUserByUserId
deprecated: false
description: GET /openapi/v1/users/{userId},支持Portal用户登录态或具备ManageUsers权限的Consumer Token访问
tags:
- User Management
parameters:
- name: userId
in: path
description: 用户ID
required: true
schema:
type: string
responses:
'200':
description: 成功获取用户
content:
application/json:
schema:
$ref: '#/components/schemas/OpenUserInfoDTO'
'400':
description: 请求参数错误或用户不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ExceptionResponse'
'401':
description: 未登录或未认证
content:
application/json:
schema:
$ref: '#/components/schemas/ExceptionResponse'
'403':
description: 权限不足
content:
application/json:
schema:
$ref: '#/components/schemas/ExceptionResponse'
/openapi/v1/users/enabled:
put:
summary: 修改Portal用户启用状态(new added)
summary: 修改用户启用状态(new added)
operationId: changeUserEnabled
deprecated: false
description: PUT /openapi/v1/users/enabled
description: PUT /openapi/v1/users/enabled,Portal用户登录态使用当前登录用户作为operator;Consumer Token访问时需要具备ManageUsers权限并传入有效operator
tags:
- Portal User Management
- User Management
parameters:
- name: operator
in: query
description: 操作人用户名,Consumer Token访问时必填且必须是已存在用户;Portal用户登录态会忽略该参数
required: false
schema:
type: string
requestBody:
content:
application/json:
Expand Down Expand Up @@ -5295,15 +5348,15 @@ paths:
content:
application/json:
schema:
type: object
$ref: '#/components/schemas/OpenConsumerCreateRequestDTO'
required: true
responses:
'200':
description: 成功创建消费者
content:
application/json:
schema:
type: object
$ref: '#/components/schemas/OpenConsumerInfoDTO'
get:
summary: 查询开放平台消费者列表(new added)
operationId: getConsumerList
Expand Down Expand Up @@ -5332,7 +5385,7 @@ paths:
schema:
type: array
items:
type: object
$ref: '#/components/schemas/OpenConsumerSummaryDTO'
/openapi/v1/consumer-tokens/by-appId:
get:
summary: 按应用ID查询消费者Token(new added)
Expand All @@ -5353,7 +5406,7 @@ paths:
content:
application/json:
schema:
type: object
$ref: '#/components/schemas/OpenConsumerInfoDTO'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use a token schema for the token lookup

For /openapi/v1/consumer-tokens/by-appId, the Apollo Portal controller's getConsumerTokenByAppId returns a ConsumerToken (token, consumerId, rateLimit, expires, audit fields), not a consumer detail object. With this $ref, generated clients deserialize the token endpoint as OpenConsumerInfoDTO, so callers lose fields such as expires and see unrelated app/owner fields instead; please model this response as a token DTO (or point the consumer-detail schema at the separate consumer-info endpoint).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is valid. I fixed it in follow-up PR #31 by introducing OpenConsumerTokenDTO for /openapi/v1/consumer-tokens/by-appId and regenerating the SDK/server artifacts. The Apollo implementation is also being aligned to call consumerService.getConsumerTokenByAppId(appId) and return the token DTO, matching the legacy WebAPI behavior.

/openapi/v1/consumers/{token}/assign-role:
post:
summary: 给消费者授权(new added)
Expand Down Expand Up @@ -6777,6 +6830,128 @@ components:
hasPermission:
type: boolean
description: ''
OpenConsumerCreateRequestDTO:
type: object
properties:
Comment on lines +6833 to +6835

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require the consumer fields the server validates

For POST /openapi/v1/consumers, Apollo rejects blank appId, name, ownerName, and orgId before creating the consumer, but this new typed request schema has no required list, so all of those fields become optional in generated clients and docs. Callers can now build a supposedly valid OpenConsumerCreateRequestDTO that only fails at runtime with 400; please mark the server-required fields as required in the schema.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed in #31. OpenConsumerCreateRequestDTO now marks the fields the server validates as required: appId, name, orgId, and ownerName. I intentionally did not mark orgName required because the Apollo controller does not reject it when blank.

appId:
type: string
description: 第三方应用ID
allowCreateApplication:
type: boolean
description: 是否允许该Consumer Token创建应用
default: false
allowManageUsers:
type: boolean
description: 是否允许该Consumer Token管理用户
default: false
Comment on lines +6843 to +6846

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove unsupported manage-users grants

When a client creates a consumer with allowManageUsers=true, this contract implies the token will be granted access to the user-management endpoints, but there is no corresponding manage-users role assignment path in the spec and Apollo's consumer creation flow only handles the existing create-application grant. The flag will therefore be ignored or omitted by current servers while generated clients/docs tell callers it enables user management; please either wire the grant end-to-end or leave this field out until it is supported.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this was a valid concern for the old server state. I am keeping allowManageUsers in the contract because the paired Apollo implementation wires it end to end: consumer creation now calls assignManageUsersRoleToConsumer(...), and consumer tokens with the new ManageUsers permission can access the user-management endpoints. This is covered by the follow-up Apollo work rather than by removing the field from the OpenAPI schema.

name:
type: string
description: 第三方应用名称
orgId:
type: string
description: 部门ID
orgName:
type: string
description: 部门名称
ownerName:
type: string
description: 负责人用户名
rateLimitEnabled:
type: boolean
description: 是否开启限流
default: false
rateLimit:
type: integer
description: 限流QPS,0表示不限流
minimum: 0
default: 0
Comment on lines +6863 to +6867

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require positive QPS when rate limiting is enabled

When callers create a consumer with rateLimitEnabled=true, Apollo's ConsumerController.create rejects rateLimit <= 0 before saving the token, but this request schema advertises 0 as valid and as the default for the same property. Generated clients and docs therefore accept a payload that fails whenever a caller enables rate limiting without also overriding the default; please express the enabled case as requiring a positive QPS, or avoid advertising 0 as the default on that path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed in #31. OpenConsumerCreateRequestDTO.rateLimit no longer advertises default: 0, and the schema description now states that rateLimitEnabled=true requires a positive QPS while 0 means unlimited only when rate limiting is disabled. I avoided a oneOf shape here because it changes generated request DTO types in a way that would unnecessarily break the Apollo portal implementation.

OpenConsumerInfoDTO:
type: object
properties:
appId:
type: string
description: 第三方应用ID
name:
type: string
description: 第三方应用名称
orgId:
type: string
description: 部门ID
orgName:
type: string
description: 部门名称
ownerName:
type: string
description: 负责人用户名
ownerEmail:
type: string
description: 负责人邮箱
consumerId:
type: integer
format: int64
description: Consumer ID
token:
type: string
description: Consumer Token,仅在创建或按应用查询详情时返回
Comment thread
nobodyiam marked this conversation as resolved.
allowCreateApplication:
type: boolean
description: 是否允许该Consumer Token创建应用
default: false
allowManageUsers:
type: boolean
description: 是否允许该Consumer Token管理用户
default: false
rateLimit:
type: integer
description: 限流QPS,0表示不限流
Comment thread
nobodyiam marked this conversation as resolved.
minimum: 0
default: 0
rateLimitEnabled:
type: boolean
description: 是否开启限流
default: false
OpenConsumerSummaryDTO:
type: object
properties:
appId:
type: string
description: 第三方应用ID
name:
type: string
description: 第三方应用名称
orgId:
type: string
description: 部门ID
orgName:
type: string
description: 部门名称
ownerName:
type: string
description: 负责人用户名
ownerEmail:
type: string
description: 负责人邮箱
consumerId:
type: integer
format: int64
description: Consumer ID
allowCreateApplication:
type: boolean
description: 是否允许该Consumer Token创建应用
default: false
allowManageUsers:
type: boolean
description: 是否允许该Consumer Token管理用户
default: false
rateLimit:
type: integer
description: 限流QPS,0表示不限流
minimum: 0
default: 0
rateLimitEnabled:
type: boolean
description: 是否开启限流
default: false
OpenUserInfoDTO:
type: object
properties:
Expand Down
10 changes: 5 additions & 5 deletions generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,30 @@ echo "🚀 Generating Python SDK..."
-o "$PYTHON_DIR" \
-t "$PYTHON_TEMPLATE_DIR" \
--package-name apollo_openapi \
--additional-properties=projectName=apollo-openapi,packageVersion=0.3.5
--additional-properties=projectName=apollo-openapi,packageVersion=0.3.6

echo "🚀 Generating TypeScript SDK..."
"${OPENAPI_GENERATOR[@]}" generate \
-i "$SPEC_FILE" \
-g typescript-fetch \
-o "$TS_DIR" \
--additional-properties=npmName=apollo-openapi,npmVersion=0.3.5,typescriptThreePlus=true
--additional-properties=npmName=apollo-openapi,npmVersion=0.3.6,typescriptThreePlus=true

echo "🚀 Generating Java Client SDK..."
"${OPENAPI_GENERATOR[@]}" generate \
-i "$SPEC_FILE" \
-g java \
-o "$JAVA_CLIENT_DIR" \
--additional-properties hideGenerationTimestamp=true \
--additional-properties=groupId=com.apollo,artifactId=apollo-openapi-client,artifactVersion=0.3.5,packageName=com.apollo.openapi.client
--additional-properties=groupId=com.apollo,artifactId=apollo-openapi-client,artifactVersion=0.3.6,packageName=com.apollo.openapi.client

echo "🚀 Generating Spring Boot 2 Server..."
"${OPENAPI_GENERATOR[@]}" generate \
-i "$SPEC_FILE" \
-g spring \
-o "$SPRING_BOOT2_DIR" \
--additional-properties hideGenerationTimestamp=true \
--additional-properties=groupId=com.apollo,artifactId=apollo-openapi-server,artifactVersion=0.3.5,packageName=com.apollo.openapi.server,basePackage=com.apollo.openapi.server,configPackage=com.apollo.openapi.server.config,modelPackage=com.apollo.openapi.server.model,apiPackage=com.apollo.openapi.server.api,library=spring-boot,java8=true,interfaceOnly=false,delegatePattern=true,useTags=true
--additional-properties=groupId=com.apollo,artifactId=apollo-openapi-server,artifactVersion=0.3.6,packageName=com.apollo.openapi.server,basePackage=com.apollo.openapi.server,configPackage=com.apollo.openapi.server.config,modelPackage=com.apollo.openapi.server.model,apiPackage=com.apollo.openapi.server.api,library=spring-boot,java8=true,interfaceOnly=false,delegatePattern=true,useTags=true

echo "📦 Adding Maven Wrapper to Spring Boot 2 project..."
cd "$SPRING_BOOT2_DIR"
Expand All @@ -90,7 +90,7 @@ echo "🚀 Generating Rust SDK..."
-g rust \
-o "$RUST_DIR" \
--global-property models,supportingFiles \
--additional-properties=packageName=apollo-openapi,packageVersion=0.3.5
--additional-properties=packageName=apollo-openapi,packageVersion=0.3.6

echo "✅ SDK generation complete."

Expand Down
Loading
Loading