Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs/@v1/guides/lint-asyncapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ some of the built-in rules. The currently-supported rules are:

- `info-contact`: the `Info` section must contain a valid `Contact` field.
- `operation-operationId`: every operation must have a valid `operationId`.
- `asyncapi-operation-security-defined`: every scheme referenced from an operation or server `security` array must be defined in `components.securitySchemes`.
- `channels-kebab-case`: channel address should be `kebab-case` (lowercase with hyphens).
- `no-channel-trailing-slash`: channel names must not have trailing slashes in their address.
- `tag-description`: all tags require a description.
Expand Down
1 change: 1 addition & 0 deletions docs/@v1/rules/built-in-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ The rules list is split into sections.
Use the rules in this section for AsyncAPI-specific linting.
Other rules such as the `spec` and `info.*` rules also apply to AsyncAPI.

- [asyncapi-operation-security-defined](./async/asyncapi-operation-security-defined.md): Security scheme names referenced from operations or servers must be defined in `components.securitySchemes`
- [channels-kebab-case](./async/channels-kebab-case.md): Channels must be in `kebab-case` format
- [no-channel-trailing-slash](./async/no-channel-trailing-slash.md): No trailing slashes on channels

Expand Down
2 changes: 2 additions & 0 deletions docs/@v1/rules/ruleset-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ rules:
info-contact: off
info-license-strict: off
operation-operationId: warn
asyncapi-operation-security-defined: warn
tag-description: warn
tags-alphabetical: off
channels-kebab-case: off
Expand Down Expand Up @@ -438,6 +439,7 @@ rules:
info-contact: off
info-license-strict: warn
operation-operationId: warn
asyncapi-operation-security-defined: error
tag-description: warn
tags-alphabetical: off
channels-kebab-case: off
Expand Down
1 change: 1 addition & 0 deletions docs/@v1/v1.sidebars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
- page: rules/oas/tag-description.md
- page: rules/oas/tags-alphabetical.md
- separator: AsyncAPI
- page: rules/async/asyncapi-operation-security-defined.md
- page: rules/async/channels-kebab-case.md
- page: rules/async/no-channel-trailing-slash.md
- separator: Arazzo
Expand Down
1 change: 1 addition & 0 deletions docs/@v2/guides/lint-asyncapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ The currently supported rules are:

- `info-contact`: the `Info` section must contain a valid `Contact` field.
- `operation-operationId`: every operation must have a valid `operationId`.
- `asyncapi-operation-security-defined`: every scheme referenced from an operation or server `security` array must be defined in `components.securitySchemes`.
- `channels-kebab-case`: channel address should be `kebab-case` (lowercase with hyphens).
- `no-channel-trailing-slash`: channel names must not have trailing slashes in their address.
- `tag-description`: all tags require a description.
Expand Down
1 change: 1 addition & 0 deletions docs/@v2/rules/built-in-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ The rules list is split into sections.
Use the rules in this section for AsyncAPI-specific linting.
Other rules, such as the `struct` and `info.*`, also apply to AsyncAPI.

- [asyncapi-operation-security-defined](./async/asyncapi-operation-security-defined.md): Security scheme names referenced from operations or servers must be defined in `components.securitySchemes`
- [channels-kebab-case](./async/channels-kebab-case.md): Channels must be in `kebab-case` format
- [no-channel-trailing-slash](./async/no-channel-trailing-slash.md): No trailing slashes on channels

Expand Down
2 changes: 2 additions & 0 deletions docs/@v2/rules/ruleset-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ rules:

```yaml
rules:
asyncapi-operation-security-defined: warn
no-enum-type-mismatch: warn
no-required-schema-properties-undefined: warn
no-schema-type-mismatch: warn
Expand Down Expand Up @@ -365,6 +366,7 @@ rules:

```yaml
rules:
asyncapi-operation-security-defined: error
info-license-strict: warn
no-duplicated-tag-names: warn
no-enum-type-mismatch: error
Expand Down
1 change: 1 addition & 0 deletions docs/@v2/v2.sidebars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
- page: rules/oas/tag-description.md
- page: rules/oas/tags-alphabetical.md
- separator: AsyncAPI
- page: rules/async/asyncapi-operation-security-defined.md
- page: rules/async/channels-kebab-case.md
- page: rules/async/no-channel-trailing-slash.md
- separator: Open-RPC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ exports[`resolveConfig > should ignore minimal from the root and read local file
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "error",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "warn",
Expand Down Expand Up @@ -418,6 +419,7 @@ exports[`resolveConfig > should resolve extends with local file config which con
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "error",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "warn",
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/config/__tests__/load.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ describe('loadConfig', () => {
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "warn",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "off",
Expand Down Expand Up @@ -477,6 +478,7 @@ describe('loadConfig', () => {
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "error",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "warn",
Expand Down Expand Up @@ -806,6 +808,7 @@ describe('loadConfig', () => {
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "warn",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "off",
Expand Down Expand Up @@ -1219,6 +1222,7 @@ describe('loadConfig', () => {
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "warn",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "off",
Expand Down Expand Up @@ -1543,6 +1547,7 @@ describe('loadConfig', () => {
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "error",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "warn",
Expand Down Expand Up @@ -1872,6 +1877,7 @@ describe('loadConfig', () => {
"async2Decorators": {},
"async2Preprocessors": {},
"async2Rules": {
"asyncapi-operation-security-defined": "warn",
"channels-kebab-case": "off",
"info-contact": "off",
"info-license-strict": "off",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/config/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ const all: RawGovernanceConfig<'built-in'> = {
'spec-querystring-parameters': 'error',
},
async2Rules: {
'asyncapi-operation-security-defined': 'error',
'channels-kebab-case': 'error',
'info-contact': 'error',
'info-license-strict': 'error',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/config/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const minimal: RawGovernanceConfig<'built-in'> = {
'tags-alphabetical': 'off',
},
async2Rules: {
'asyncapi-operation-security-defined': 'warn',
'channels-kebab-case': 'off',
'info-contact': 'off',
'info-license-strict': 'off',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/config/recommended-strict.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const recommendedStrict: RawGovernanceConfig<'built-in'> = {
'tags-alphabetical': 'off',
},
async2Rules: {
'asyncapi-operation-security-defined': 'error',
'channels-kebab-case': 'off',
'info-contact': 'off',
'info-license-strict': 'error',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/config/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const recommended: RawGovernanceConfig<'built-in'> = {
'tags-alphabetical': 'off',
},
async2Rules: {
'asyncapi-operation-security-defined': 'error',
'channels-kebab-case': 'off',
'info-contact': 'off',
'info-license-strict': 'warn',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/config/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const spec: RawGovernanceConfig<'built-in'> = {
'tags-alphabetical': 'off',
},
async2Rules: {
'asyncapi-operation-security-defined': 'off',
'channels-kebab-case': 'off',
'info-contact': 'off',
'info-license-strict': 'off',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { outdent } from 'outdent';

import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils.js';
import { createConfig } from '../../../config/index.js';
import { lintDocument } from '../../../lint.js';
import { BaseResolver } from '../../../resolve.js';

describe('Async2 asyncapi-operation-security-defined', () => {
it('should report when an operation references an undefined security scheme', async () => {
const document = parseYamlToDocument(
outdent`
asyncapi: '2.6.0'
info:
title: Cool API
version: 1.0.0
channels:
some/channel:
subscribe:
security:
- undefinedScheme: []
message:
messageId: Message1
components:
securitySchemes:
knownScheme:
type: apiKey
in: user
`,
'asyncapi.yaml'
);

const results = await lintDocument({
externalRefResolver: new BaseResolver(),
document,
config: await createConfig({
rules: { 'asyncapi-operation-security-defined': 'error' },
}),
});

expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
[
{
"location": [
{
"pointer": "#/channels/some~1channel/subscribe/security/0/undefinedScheme",
"reportOnKey": true,
"source": "asyncapi.yaml",
},
],
"message": "There is no \`undefinedScheme\` security scheme defined.",
"ruleId": "asyncapi-operation-security-defined",
"severity": "error",
"suggest": [],
},
]
`);
});

it('should report when a server references an undefined security scheme', async () => {
const document = parseYamlToDocument(
outdent`
asyncapi: '2.6.0'
info:
title: Cool API
version: 1.0.0
servers:
production:
url: kafka.example.com
protocol: kafka
security:
- missingScheme: []
channels:
some/channel: {}
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: user
`,
'asyncapi.yaml'
);

const results = await lintDocument({
externalRefResolver: new BaseResolver(),
document,
config: await createConfig({
rules: { 'asyncapi-operation-security-defined': 'error' },
}),
});

expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
[
{
"location": [
{
"pointer": "#/servers/production/security/0/missingScheme",
"reportOnKey": true,
"source": "asyncapi.yaml",
},
],
"message": "There is no \`missingScheme\` security scheme defined.",
"ruleId": "asyncapi-operation-security-defined",
"severity": "error",
"suggest": [],
},
]
`);
});

it('should not report when all referenced schemes are defined', async () => {
const document = parseYamlToDocument(
outdent`
asyncapi: '2.6.0'
info:
title: Cool API
version: 1.0.0
servers:
production:
url: kafka.example.com
protocol: kafka
security:
- apiKeyAuth: []
channels:
some/channel:
subscribe:
security:
- apiKeyAuth: []
message:
messageId: Message1
components:
securitySchemes:
apiKeyAuth:
type: apiKey
in: user
`,
'asyncapi.yaml'
);

const results = await lintDocument({
externalRefResolver: new BaseResolver(),
document,
config: await createConfig({
rules: { 'asyncapi-operation-security-defined': 'error' },
}),
});

expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
});

it('should not report when security array is empty', async () => {
const document = parseYamlToDocument(
outdent`
asyncapi: '2.6.0'
info:
title: Cool API
version: 1.0.0
channels:
some/channel:
subscribe:
security: []
message:
messageId: Message1
`,
'asyncapi.yaml'
);

const results = await lintDocument({
externalRefResolver: new BaseResolver(),
document,
config: await createConfig({
rules: { 'asyncapi-operation-security-defined': 'error' },
}),
});

expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
});
});
Loading
Loading