优化
This commit is contained in:
@@ -886,7 +886,7 @@ components:
|
||||
TenantCreationSuccess: {description: Enterprise tenant and one-time owner credentials returned / 返回企业客户及一次性管理员凭据, content: {application/json: {schema: {$ref: '#/components/schemas/TenantCreationApiResponse'}}}}
|
||||
BadRequest: {description: Invalid request / 请求参数错误, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
Unauthorized: {description: Authentication required / 需要登录, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
Forbidden: {description: Permission, customer scope or platform technical scope rejected / 权限、客户范围或平台技术作用域不匹配, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
Forbidden: {description: 'Permission, customer scope or platform technical scope rejected / 权限、客户范围或平台技术作用域不匹配', content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
NotFound: {description: Resource not found / 资源不存在, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
Conflict: {description: Resource conflict / 资源冲突, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
ServiceUnavailable: {description: Authentication service unavailable / 认证服务不可用, content: {application/json: {schema: {$ref: '#/components/schemas/ApiResponse'}}}}
|
||||
|
||||
@@ -60,7 +60,7 @@ paths:
|
||||
- {$ref: '#/components/parameters/Size'}
|
||||
- {name: templateCode, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: category, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: title, in: query, description: Fuzzy match template name or title template, schema: {type: string, maxLength: 128}}
|
||||
- {name: title, in: query, description: 'Fuzzy match template name or title template', schema: {type: string, maxLength: 128}}
|
||||
- {name: status, in: query, schema: {type: string, enum: [DRAFT, ACTIVE, DISABLED]}}
|
||||
responses: {'200': {$ref: '#/components/responses/TemplatePage'}}
|
||||
post:
|
||||
@@ -92,7 +92,7 @@ paths:
|
||||
- {$ref: '#/components/parameters/Size'}
|
||||
- {name: taskNo, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: category, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: title, in: query, description: Fuzzy match rendered title, schema: {type: string, maxLength: 128}}
|
||||
- {name: title, in: query, description: 'Fuzzy match rendered title', schema: {type: string, maxLength: 128}}
|
||||
- {name: status, in: query, schema: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}}
|
||||
responses: {'200': {$ref: '#/components/responses/TaskPage'}}
|
||||
/platform/v1/notification-tasks/{id}:
|
||||
@@ -145,17 +145,27 @@ components:
|
||||
tenantId: {type: integer, format: int64, minimum: 0}
|
||||
templateCode: {type: string, maxLength: 64}
|
||||
recipientType: {type: string, enum: [USER, MEMBERSHIP, TENANT_ROLE, TENANT_ALL, PLATFORM_ROLE]}
|
||||
recipientIds: {type: array, maxItems: 1000, items: {type: integer, format: int64}, description: Required for USER or MEMBERSHIP; forbidden for role/all recipient types.}
|
||||
roleCode: {type: string, maxLength: 64, description: Required for TENANT_ROLE or PLATFORM_ROLE; forbidden otherwise.}
|
||||
recipientIds: {type: array, minItems: 1, maxItems: 1000, items: {type: integer, format: int64}, description: Required for USER or MEMBERSHIP; forbidden for role/all recipient types.}
|
||||
roleCode: {type: string, minLength: 1, maxLength: 64, description: Required for TENANT_ROLE or PLATFORM_ROLE; forbidden otherwise.}
|
||||
variables: {type: object, maxProperties: 32, additionalProperties: {type: string, maxLength: 2000}}
|
||||
scheduledAt: {type: string, format: date-time, nullable: true}
|
||||
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
|
||||
sourceEventId: {type: string, maxLength: 128, nullable: true}
|
||||
allOf:
|
||||
- if: {properties: {recipientType: {enum: [USER, MEMBERSHIP]}}}
|
||||
then: {required: [recipientIds]}
|
||||
- if: {properties: {recipientType: {enum: [TENANT_ROLE, PLATFORM_ROLE]}}}
|
||||
then: {required: [roleCode]}
|
||||
oneOf:
|
||||
- required: [recipientIds]
|
||||
properties:
|
||||
recipientType: {type: string, enum: [USER, MEMBERSHIP]}
|
||||
not: {required: [roleCode]}
|
||||
- required: [roleCode]
|
||||
properties:
|
||||
recipientType: {type: string, enum: [TENANT_ROLE, PLATFORM_ROLE]}
|
||||
not: {required: [recipientIds]}
|
||||
- properties:
|
||||
recipientType: {type: string, enum: [TENANT_ALL]}
|
||||
not:
|
||||
anyOf:
|
||||
- required: [recipientIds]
|
||||
- required: [roleCode]
|
||||
CreateTemplateRequest:
|
||||
type: object
|
||||
required: [templateCode, templateName, category, titleTemplate, bodyTemplate, variableWhitelist]
|
||||
|
||||
@@ -69,6 +69,33 @@ class NotificationOpenApiContractTest {
|
||||
assertThat(map(map(taskDetail.get("properties")).get("attemptCount")))
|
||||
.containsEntry("minimum", 0).containsEntry("maximum", 3);
|
||||
assertThat(document).contains("scheduler delivery starts after the retry delay");
|
||||
|
||||
Map<String, Object> createNotification = map(schemas.get("CreateNotificationRequest"));
|
||||
Map<String, Object> selectorProperties = map(createNotification.get("properties"));
|
||||
assertThat(map(selectorProperties.get("recipientIds"))).containsEntry("minItems", 1);
|
||||
assertThat(map(selectorProperties.get("roleCode"))).containsEntry("minLength", 1);
|
||||
List<Object> selectorBranches = list(createNotification.get("oneOf"));
|
||||
assertThat(selectorBranches).hasSize(3);
|
||||
|
||||
Map<String, Object> directRecipients = map(selectorBranches.get(0));
|
||||
assertThat(list(directRecipients.get("required"))).containsExactly("recipientIds");
|
||||
assertThat(list(map(directRecipients.get("not")).get("required"))).containsExactly("roleCode");
|
||||
assertThat(list(map(map(directRecipients.get("properties")).get("recipientType")).get("enum")))
|
||||
.containsExactly("USER", "MEMBERSHIP");
|
||||
|
||||
Map<String, Object> roleRecipients = map(selectorBranches.get(1));
|
||||
assertThat(list(roleRecipients.get("required"))).containsExactly("roleCode");
|
||||
assertThat(list(map(roleRecipients.get("not")).get("required"))).containsExactly("recipientIds");
|
||||
assertThat(list(map(map(roleRecipients.get("properties")).get("recipientType")).get("enum")))
|
||||
.containsExactly("TENANT_ROLE", "PLATFORM_ROLE");
|
||||
|
||||
Map<String, Object> allRecipients = map(selectorBranches.get(2));
|
||||
assertThat(list(map(map(allRecipients.get("properties")).get("recipientType")).get("enum")))
|
||||
.containsExactly("TENANT_ALL");
|
||||
assertThat(list(map(allRecipients.get("not")).get("anyOf")))
|
||||
.extracting(value -> list(map(value).get("required")))
|
||||
.containsExactly(List.of("recipientIds"), List.of("roleCode"));
|
||||
assertThat(document).doesNotContain("if:").doesNotContain("then:");
|
||||
}
|
||||
|
||||
private void assertRequestBody(Map<String, Object> paths, String path, String method) {
|
||||
|
||||
Reference in New Issue
Block a user