diff --git a/packages/apidom-ls/src/config/codes.ts b/packages/apidom-ls/src/config/codes.ts index fd1eb0586..b351a276b 100644 --- a/packages/apidom-ls/src/config/codes.ts +++ b/packages/apidom-ls/src/config/codes.ts @@ -794,6 +794,22 @@ enum ApilintCodes { OPENAPI2_SECURITY_REQUIREMENT = 3210000, OPENAPI2_SECURITY_REQUIREMENT_KEYS_DEFINED, + OPENAPI2_SECURITY_SCHEME = 3220000, + OPENAPI2_SECURITY_SCHEME_FIELD_TYPE_EQUALS = 3220100, + OPENAPI2_SECURITY_SCHEME_FIELD_DESCRIPTION_TYPE = 3220200, + OPENAPI2_SECURITY_SCHEME_FIELD_NAME_TYPE = 3220300, + OPENAPI2_SECURITY_SCHEME_FIELD_NAME_REQUIRED, + OPENAPI2_SECURITY_SCHEME_FIELD_IN_EQUALS = 3220400, + OPENAPI2_SECURITY_SCHEME_FIELD_IN_REQUIRED, + OPENAPI2_SECURITY_SCHEME_FIELD_FLOW_EQUALS = 3220500, + OPENAPI2_SECURITY_SCHEME_FIELD_FLOW_REQUIRED, + OPENAPI2_SECURITY_SCHEME_FIELD_AUTHORIZATION_URL_FORMAT_URI = 3220600, + OPENAPI2_SECURITY_SCHEME_FIELD_AUTHORIZATION_URL_REQUIRED, + OPENAPI2_SECURITY_SCHEME_FIELD_TOKEN_URL_FORMAT_URI = 3220700, + OPENAPI2_SECURITY_SCHEME_FIELD_TOKEN_URL_REQUIRED, + OPENAPI2_SECURITY_SCHEME_FIELD_SCOPES_TYPE = 3220800, + OPENAPI2_SECURITY_SCHEME_FIELD_SCOPES_REQUIRED, + OPENAPI3_0 = 5000000, OPENAPI3_0_OPENAPI_VALUE_PATTERN_3_0_0 = 5000100, diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/completion.ts b/packages/apidom-ls/src/config/openapi/security-scheme/completion.ts index 46b41fc9e..1b719b5fb 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/completion.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/completion.ts @@ -3,7 +3,7 @@ import { CompletionFormat, CompletionType, } from '../../../apidom-language-types'; -import { OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; +import { OpenAPI2, OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; const completion: ApidomCompletionItem[] = [ { @@ -17,7 +17,21 @@ const completion: ApidomCompletionItem[] = [ kind: 'markdown', value: 'A reference to a Security Scheme.', }, - targetSpecs: OpenAPI3, + targetSpecs: OpenAPI2, + }, + { + label: 'type', + insertText: 'type', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + '**Required.** The type of the security scheme. Valid values are `"basic"`, `"apiKey"` or `"oauth2"`.', + }, + targetSpecs: OpenAPI2, }, { label: 'type', @@ -47,6 +61,19 @@ const completion: ApidomCompletionItem[] = [ }, targetSpecs: OpenAPI31, }, + { + label: 'description', + insertText: 'description', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'A short description for security scheme.', + }, + targetSpecs: OpenAPI2, + }, { label: 'description', insertText: 'description', @@ -71,7 +98,21 @@ const completion: ApidomCompletionItem[] = [ documentation: { kind: 'markdown', value: - '**REQUIRED**. Applies to `apiKey`. **REQUIRED**. The name of the header, query or cookie parameter to be used.', + 'Valid for `apiKey`. **Required**. The name of the header or query parameter to be used.', + }, + targetSpecs: OpenAPI3, + }, + { + label: 'name', + insertText: 'name', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Applies to `apiKey`. **REQUIRED**. The name of the header, query or cookie parameter to be used.', }, targetSpecs: OpenAPI3, }, @@ -85,7 +126,21 @@ const completion: ApidomCompletionItem[] = [ documentation: { kind: 'markdown', value: - '**REQUIRED**. Applies to `apiKey`. **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"` or `"cookie"`.', + 'Valid for `apiKey`. **Required**. The location of the API key. Valid values are `"query"` or `"header"`.', + }, + targetSpecs: OpenAPI2, + }, + { + label: 'in', + insertText: 'in', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Applies to `apiKey`. **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"` or `"cookie"`.', }, targetSpecs: OpenAPI3, }, @@ -117,6 +172,20 @@ const completion: ApidomCompletionItem[] = [ }, targetSpecs: OpenAPI3, }, + { + label: 'flow', + insertText: 'flow', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Valid for `oauth2`. **Required**. The flow used by the OAuth2 security scheme. Valid values are `"implicit"`, `"password"`, `"application"` or `"accessCode"`.', + }, + targetSpecs: OpenAPI2, + }, { label: 'flows', insertText: 'flows', @@ -145,6 +214,34 @@ const completion: ApidomCompletionItem[] = [ }, targetSpecs: OpenAPI31, }, + { + label: 'authorizationUrl', + insertText: 'authorizationUrl', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Valid for oauth2 (`"implicit"`, `"accessCode"`). **Required**. The authorization URL to be used for this flow. This SHOULD be in the form of a URL.', + }, + targetSpecs: OpenAPI2, + }, + { + label: 'tokenUrl', + insertText: 'tokenUrl', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Valid for oauth2 (`"password"`, `"application"`, `"accessCode"`). **Required**. The token URL to be used for this flow. This SHOULD be in the form of a URL.', + }, + targetSpecs: OpenAPI2, + }, { label: 'openIdConnectUrl', insertText: 'openIdConnectUrl', @@ -155,7 +252,7 @@ const completion: ApidomCompletionItem[] = [ documentation: { kind: 'markdown', value: - '**REQUIRED**. Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL.', + 'Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL.', }, targetSpecs: OpenAPI30, }, @@ -169,10 +266,34 @@ const completion: ApidomCompletionItem[] = [ documentation: { kind: 'markdown', value: - '**REQUIRED**. Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL. The OpenID Connect standard requires the use of TLS.', + 'Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL. The OpenID Connect standard requires the use of TLS.', }, targetSpecs: OpenAPI31, }, + { + label: 'scopes', + insertText: 'scopes', + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + '[Scopes Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#scopes-object)\n\\\n\\\nValid for `oauth2`. **Required**. The available scopes for the OAuth2 security scheme.', + }, + targetSpecs: OpenAPI2, + }, + { + target: 'type', + label: 'basic', + insertText: 'basic', + kind: 12, + format: CompletionFormat.QUOTED, + type: CompletionType.VALUE, + insertTextFormat: 2, + targetSpecs: OpenAPI2, + }, { target: 'type', label: 'apiKey', @@ -181,7 +302,7 @@ const completion: ApidomCompletionItem[] = [ format: CompletionFormat.QUOTED, type: CompletionType.VALUE, insertTextFormat: 2, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }, { target: 'type', @@ -201,7 +322,7 @@ const completion: ApidomCompletionItem[] = [ format: CompletionFormat.QUOTED, type: CompletionType.VALUE, insertTextFormat: 2, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }, { target: 'type', @@ -221,7 +342,7 @@ const completion: ApidomCompletionItem[] = [ format: CompletionFormat.QUOTED, type: CompletionType.VALUE, insertTextFormat: 2, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }, { target: 'in', @@ -231,7 +352,7 @@ const completion: ApidomCompletionItem[] = [ format: CompletionFormat.QUOTED, type: CompletionType.VALUE, insertTextFormat: 2, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }, { target: 'in', @@ -243,6 +364,46 @@ const completion: ApidomCompletionItem[] = [ insertTextFormat: 2, targetSpecs: OpenAPI3, }, + { + target: 'flow', + label: 'implicit', + insertText: 'implicit', + kind: 12, + format: CompletionFormat.QUOTED, + type: CompletionType.VALUE, + insertTextFormat: 2, + targetSpecs: OpenAPI2, + }, + { + target: 'flow', + label: 'password', + insertText: 'password', + kind: 12, + format: CompletionFormat.QUOTED, + type: CompletionType.VALUE, + insertTextFormat: 2, + targetSpecs: OpenAPI2, + }, + { + target: 'flow', + label: 'application', + insertText: 'application', + kind: 12, + format: CompletionFormat.QUOTED, + type: CompletionType.VALUE, + insertTextFormat: 2, + targetSpecs: OpenAPI2, + }, + { + target: 'flow', + label: 'accessCode', + insertText: 'accessCode', + kind: 12, + format: CompletionFormat.QUOTED, + type: CompletionType.VALUE, + insertTextFormat: 2, + targetSpecs: OpenAPI2, + }, ]; export default completion; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/documentation.ts b/packages/apidom-ls/src/config/openapi/security-scheme/documentation.ts index 53922a73f..1d9f256c1 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/documentation.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/documentation.ts @@ -1,6 +1,11 @@ -import { OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; +import { OpenAPI2, OpenAPI30, OpenAPI31, OpenAPI3 } from '../target-specs'; const documentation = [ + { + target: 'type', + docs: '**Required.** The type of the security scheme. Valid values are `"basic"`, `"apiKey"` or `"oauth2"`.', + targetSpecs: OpenAPI2, + }, { target: 'type', docs: '**REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`.', @@ -11,6 +16,11 @@ const documentation = [ docs: '**REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"mutualTLS"`, `"oauth2"`, `"openIdConnect"`.', targetSpecs: OpenAPI31, }, + { + target: 'description', + docs: 'A short description for security scheme.', + targetSpecs: OpenAPI2, + }, { target: 'description', docs: 'A description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.', @@ -18,17 +28,27 @@ const documentation = [ }, { target: 'name', - docs: '**REQUIRED**. Applies to `apiKey`. **REQUIRED**. The name of the header, query or cookie parameter to be used.', + docs: 'Valid for `apiKey`. **Required**. The name of the header or query parameter to be used.', + targetSpecs: OpenAPI2, + }, + { + target: 'name', + docs: 'Applies to `apiKey`. **REQUIRED**. The name of the header, query or cookie parameter to be used.', targetSpecs: OpenAPI3, }, { target: 'in', - docs: '**REQUIRED**. Applies to `apiKey`. **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"` or `"cookie"`.', + docs: 'Valid for `apiKey`. **Required**. The location of the API key. Valid values are `"query"` or `"header"`.', + targetSpecs: OpenAPI2, + }, + { + target: 'in', + docs: 'Applies to `apiKey`. **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"` or `"cookie"`.', targetSpecs: OpenAPI3, }, { target: 'scheme', - docs: '**REQUIRED**. Applies to `http`. **REQUIRED**. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml).', + docs: 'Applies to `http`. **REQUIRED**. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml).', targetSpecs: OpenAPI3, }, { @@ -36,6 +56,11 @@ const documentation = [ docs: 'Applies to `http` (`"bearer"`). A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes.', targetSpecs: OpenAPI3, }, + { + target: 'flow', + docs: 'Valid for `oauth2`. **Required**. The flow used by the OAuth2 security scheme. Valid values are `"implicit"`, `"password"`, `"application"` or `"accessCode"`.', + targetSpecs: OpenAPI2, + }, { target: 'flows', docs: '[OAuth Flows Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauthFlowsObject)\n\\\nApplies to `oauth2`. **REQUIRED**. An object containing configuration information for the flow types supported.', @@ -46,15 +71,34 @@ const documentation = [ docs: '[OAuth Flows Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oauthFlowsObject)\n\\\nApplies to `oauth2`. **REQUIRED**. An object containing configuration information for the flow types supported.', targetSpecs: OpenAPI31, }, + { + target: 'authorizationUrl', + docs: 'Valid for oauth2 (`"implicit"`, `"accessCode"`). **Required**. The authorization URL to be used for this flow. This SHOULD be in the form of a URL.', + targetSpecs: OpenAPI2, + }, + { + target: 'tokenUrl', + docs: 'Valid for oauth2 (`"password"`, `"application"`, `"accessCode"`). **Required**. The token URL to be used for this flow. This SHOULD be in the form of a URL.', + targetSpecs: OpenAPI2, + }, { target: 'openIdConnectUrl', - docs: '**REQUIRED**. Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL.', + docs: 'Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL.', targetSpecs: OpenAPI30, }, + { + target: 'scopes', + docs: '[Scopes Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#scopes-object)\n\\\n\\\nValid for `oauth2`. **Required**. The available scopes for the OAuth2 security scheme.', + targetSpecs: OpenAPI2, + }, { target: 'openIdConnectUrl', - docs: '**REQUIRED**. Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL. The OpenID Connect standard requires the use of TLS.', - targetSpecs: OpenAPI31, + docs: 'Applies to `openIdConnect`. **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL. The OpenID Connect standard requires the use of TLS.', + targetSpecs: OpenAPI2, + }, + { + docs: '#### [Security Scheme Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#securitySchemeObject)\n\nAllows the definition of a security scheme that can be used by the operations. Supported schemes are basic authentication, an API key (either as a header or as a query parameter) and OAuth2\'s common flows (implicit, password, application and access code).\n\n##### Fixed Fields\nField Name | Type | Validity | Description\n---|:---:|---|---\ntype | `string` | Any | **Required.** The type of the security scheme. Valid values are `"basic"`, `"apiKey"` or `"oauth2"`.\ndescription | `string` | Any | A short description for security scheme.\nname | `string` | `apiKey` | **Required.** The name of the header or query parameter to be used.\nin | `string` | `apiKey` | **Required** The location of the API key. Valid values are `"query"` or `"header"`.\nflow | `string` | `oauth2` | **Required.** The flow used by the OAuth2 security scheme. Valid values are `"implicit"`, `"password"`, `"application"` or `"accessCode"`.\nauthorizationUrl | `string` | `oauth2` (`"implicit"`, `"accessCode"`) | **Required.** The authorization URL to be used for this flow. This SHOULD be in the form of a URL.\ntokenUrl | `string` | `oauth2` (`"password"`, `"application"`, `"accessCode"`) | **Required.** The token URL to be used for this flow. This SHOULD be in the form of a URL.\nscopes | [Scopes Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#scopesObject) | `oauth2` | **Required.** The available scopes for the OAuth2 security scheme.\n\n##### Patterned Fields\n\nField Name | Type | Description\n---|:---:|---\n^x- | Any | Allows extensions to the Swagger Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. The value can be `null`, a primitive, an array or an object. See [Vendor Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#vendorExtensions) for further details.\n\n##### Security Scheme Object Example\n\n###### Basic Authentication Sample\n\n```js\n{\n "type": "basic"\n}\n```\n\n\n\\\nYAML\n```yaml\ntype: basic\n```\n\n###### API Key Sample\n\n```js\n{\n "type": "apiKey",\n "name": "api_key",\n "in": "header"\n}\n```\n\n```yaml\ntype: apiKey\nname: api_key\nin: header\n```\n\n###### Implicit OAuth2 Sample\n\n```js\n{\n "type": "oauth2",\n "authorizationUrl": "http://swagger.io/api/oauth/dialog",\n "flow": "implicit",\n "scopes": {\n "write:pets": "modify pets in your account",\n "read:pets": "read your pets"\n }\n}\n```\n\n```yaml\ntype: oauth2\nauthorizationUrl: http://swagger.io/api/oauth/dialog\nflow: implicit\nscopes:\n write:pets: modify pets in your account\n read:pets: read your pets\n```', + targetSpecs: OpenAPI2, }, { docs: '#### [Security Scheme Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securitySchemeObject)\n\nDefines a security scheme that can be used by the operations.\nSupported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query parameter), OAuth2\'s common flows (implicit, password, client credentials and authorization code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749), and [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06).\n\n##### Fixed Fields\nField Name | Type | Applies To | Description\n---|:---:|---|---\ntype | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`.\ndescription | `string` | Any | A short description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.\nname | `string` | `apiKey` | **REQUIRED**. The name of the header, query or cookie parameter to be used.\nin | `string` | `apiKey` | **REQUIRED**. The location of the API key. Valid values are `"query"`, `"header"` or `"cookie"`.\nscheme | `string` | `http` | **REQUIRED**. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml).\nbearerFormat | `string` | `http` (`"bearer"`) | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes.\nflows | [OAuth Flows Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauthFlowsObject) | `oauth2` | **REQUIRED**. An object containing configuration information for the flow types supported.\nopenIdConnectUrl | `string` | `openIdConnect` | **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL.\n\nThis object MAY be extended with [Specification Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions).\n\n##### Security Scheme Object Example\n\n###### Basic Authentication Sample\n\n\n\\\nJSON\n```json\n{\n "type": "http",\n "scheme": "basic"\n}\n```\n\n\n\\\nYAML\n```yaml\ntype: http\nscheme: basic\n```\n\n###### API Key Sample\n\n```json\n{\n "type": "apiKey",\n "name": "api_key",\n "in": "header"\n}\n```\n\n```yaml\ntype: apiKey\nname: api_key\nin: header\n```\n\n###### JWT Bearer Sample\n\n```json\n{\n "type": "http",\n "scheme": "bearer",\n "bearerFormat": "JWT",\n}\n```\n\n```yaml\ntype: http\nscheme: bearer\nbearerFormat: JWT\n```\n\n###### Implicit OAuth2 Sample\n\n```json\n{\n "type": "oauth2",\n "flows": {\n "implicit": {\n "authorizationUrl": "https://example.com/api/oauth/dialog",\n "scopes": {\n "write:pets": "modify pets in your account",\n "read:pets": "read your pets"\n }\n }\n }\n}\n```\n\n```yaml\ntype: oauth2\nflows:\n implicit:\n authorizationUrl: https://example.com/api/oauth/dialog\n scopes:\n write:pets: modify pets in your account\n read:pets: read your pets\n```', diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/allowed-fields-2-0.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/allowed-fields-2-0.ts new file mode 100644 index 000000000..de36d5c51 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/allowed-fields-2-0.ts @@ -0,0 +1,22 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const allowedFields2_0Lint: LinterMeta = { + code: ApilintCodes.NOT_ALLOWED_FIELDS, + source: 'apilint', + message: 'Object includes not allowed fields', + severity: DiagnosticSeverity.Error, + linterFunction: 'allowedFields', + linterParams: [ + ['type', 'description', 'name', 'in', 'flow', 'authorizationUrl', 'tokenUrl', 'scopes'], + 'x-', + ], + marker: 'key', + targetSpecs: OpenAPI2, +}; + +export default allowedFields2_0Lint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/authorization-url--format-uri.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/authorization-url--format-uri.ts new file mode 100644 index 000000000..1ee7b56a0 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/authorization-url--format-uri.ts @@ -0,0 +1,20 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const authorizationUrlFormatURILint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_AUTHORIZATION_URL_FORMAT_URI, + source: 'apilint', + message: 'authorizationUrl MUST be in the format of an absolute URL.', + severity: DiagnosticSeverity.Error, + linterFunction: 'apilintValidURI', + linterParams: [true], + marker: 'value', + target: 'authorizationUrl', + data: {}, + targetSpecs: OpenAPI2, +}; + +export default authorizationUrlFormatURILint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/authorization-url--required.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/authorization-url--required.ts new file mode 100644 index 000000000..17c05fbd5 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/authorization-url--required.ts @@ -0,0 +1,41 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const authorizationUrlRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_AUTHORIZATION_URL_REQUIRED, + source: 'apilint', + message: + "should always have a 'authorizationUrl' when 'type' is 'oauth2' and 'flow' is 'implicit' or 'accessCode'", + severity: DiagnosticSeverity.Error, + linterFunction: 'hasRequiredField', + linterParams: ['authorizationUrl'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'authorizationUrl' field", + action: 'addChild', + snippetYaml: 'authorizationUrl: \n ', + snippetJson: '"authorizationUrl": "",\n ', + }, + ], + }, + conditions: [ + { + targets: [{ path: 'type' }], + function: 'apilintContainsValue', + params: ['oauth2'], + }, + { + targets: [{ path: 'flow' }], + function: 'apilintValueOrArray', + params: [['implicit', 'accessCode']], + }, + ], + targetSpecs: OpenAPI2, +}; + +export default authorizationUrlRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/description--type.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/description--type.ts index e22d50986..179317277 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/lint/description--type.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/description--type.ts @@ -2,10 +2,10 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const descriptionTypeLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_SECURITY_SCHEME_FIELD_DESCRIPTION_TYPE, + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_DESCRIPTION_TYPE, source: 'apilint', message: 'description must be a string', severity: DiagnosticSeverity.Error, @@ -14,7 +14,7 @@ const descriptionTypeLint: LinterMeta = { marker: 'value', target: 'description', data: {}, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default descriptionTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/flow--equals.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/flow--equals.ts new file mode 100644 index 000000000..fa2c13520 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/flow--equals.ts @@ -0,0 +1,20 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const flowEqualsLint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_FLOW_EQUALS, + source: 'apilint', + message: "'flow' must be one of allowed values", + severity: DiagnosticSeverity.Error, + linterFunction: 'apilintValueOrArray', + linterParams: [['implicit', 'password', 'application', 'accessCode']], + marker: 'value', + target: 'flow', + data: {}, + targetSpecs: OpenAPI2, +}; + +export default flowEqualsLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/flow--required.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/flow--required.ts new file mode 100644 index 000000000..cf314e7fb --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/flow--required.ts @@ -0,0 +1,35 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const flowRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_FLOW_REQUIRED, + source: 'apilint', + message: "should always have a 'flow' when type='oauth2'", + severity: DiagnosticSeverity.Error, + linterFunction: 'hasRequiredField', + linterParams: ['flow'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'in' field", + action: 'addChild', + snippetYaml: 'flow: \n ', + snippetJson: '"flow": "",\n ', + }, + ], + }, + conditions: [ + { + targets: [{ path: 'type' }], + function: 'apilintContainsValue', + params: ['oauth2'], + }, + ], + targetSpecs: OpenAPI2, +}; + +export default flowRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals-2-0.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals-2-0.ts new file mode 100644 index 000000000..227ed0c7a --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals-2-0.ts @@ -0,0 +1,21 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const inEquals2_0Lint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_IN_EQUALS, + source: 'apilint', + message: "'in' must be one of allowed values", + severity: DiagnosticSeverity.Error, + linterFunction: 'apilintValueOrArray', + linterParams: [['query', 'header']], + marker: 'value', + target: 'in', + data: {}, + targetSpecs: OpenAPI2, +}; + +export default inEquals2_0Lint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals-3-0--3-1.ts similarity index 79% rename from packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals.ts rename to packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals-3-0--3-1.ts index 51408e994..0d9195a3b 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--equals-3-0--3-1.ts @@ -4,7 +4,8 @@ import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; import { OpenAPI3 } from '../../target-specs'; -const inEqualsLint: LinterMeta = { +// eslint-disable-next-line @typescript-eslint/naming-convention +const inEquals3_0__3_1Lint: LinterMeta = { code: ApilintCodes.OPENAPI3_0_SECURITY_SCHEME_FIELD_IN_EQUALS, source: 'apilint', message: "'in' must be one of allowed values", @@ -17,4 +18,4 @@ const inEqualsLint: LinterMeta = { targetSpecs: OpenAPI3, }; -export default inEqualsLint; +export default inEquals3_0__3_1Lint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--required.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--required.ts index 7386e5c31..e901e768d 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--required.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/in--required.ts @@ -2,12 +2,12 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const inRequiredLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_SECURITY_SCHEME_FIELD_IN_REQUIRED, + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_IN_REQUIRED, source: 'apilint', - message: "should always have a 'in'", + message: "should always have a 'in' when type='apiKey'", severity: DiagnosticSeverity.Error, linterFunction: 'hasRequiredField', linterParams: ['in'], @@ -29,7 +29,7 @@ const inRequiredLint: LinterMeta = { params: ['apiKey'], }, ], - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default inRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/index.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/index.ts index e14086688..b3889441e 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/lint/index.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/index.ts @@ -1,13 +1,24 @@ +import allowedFields2_0Lint from './allowed-fields-2-0'; import allowedFields3_0Lint from './allowed-fields-3-0'; import allowedFields3_1Lint from './allowed-fields-3-1'; +import typeEquals2_0Lint from './type--equals-2-0'; import typeEquals3_0Lint from './type--equals-3-0'; import typeEquals3_1Lint from './type--equals-3-1'; import typeRequiredLint from './type--required'; import descriptionTypeLint from './description--type'; import nameTypeLint from './name--type'; import nameRequiredLint from './name--required'; -import inEqualsLint from './in--equals'; +import inEquals2_0Lint from './in--equals-2-0'; +import inEquals3_0__3_1Lint from './in--equals-3-0--3-1'; import inRequiredLint from './in--required'; +import flowEqualsLint from './flow--equals'; +import flowRequiredLint from './flow--required'; +import authorizationUrlFormatURILint from './authorization-url--format-uri'; +import authorizationUrlRequiredLint from './authorization-url--required'; +import tokenUrlFormatURILint from './token-url--format-uri'; +import tokenUrlRequiredLint from './token-url--required'; +import scopesTypeLint from './scopes--type'; +import scopesRequiredLint from './scopes--required'; import schemeTypeLint from './scheme--type'; import schemeRequiredLint from './scheme--required'; import bearerFormatTypeLint from './bearer-format--type'; @@ -17,14 +28,25 @@ import openIdConnectUrlFormatURILint from './open-id-connect-url--format-uri'; import openIdConnectUrlRequiredLint from './open-id-connect-url--required'; const lints = [ + typeEquals2_0Lint, typeEquals3_0Lint, typeEquals3_1Lint, typeRequiredLint, descriptionTypeLint, nameTypeLint, nameRequiredLint, - inEqualsLint, + inEquals2_0Lint, + inEquals3_0__3_1Lint, inRequiredLint, + flowEqualsLint, + flowRequiredLint, + authorizationUrlFormatURILint, + authorizationUrlRequiredLint, + tokenUrlFormatURILint, + tokenUrlRequiredLint, + scopesTypeLint, + scopesRequiredLint, + schemeRequiredLint, schemeTypeLint, schemeRequiredLint, bearerFormatTypeLint, @@ -32,6 +54,7 @@ const lints = [ flowsRequiredLint, openIdConnectUrlFormatURILint, openIdConnectUrlRequiredLint, + allowedFields2_0Lint, allowedFields3_0Lint, allowedFields3_1Lint, ]; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--required.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--required.ts index 436f3a6fe..ef3bffe3a 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--required.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--required.ts @@ -2,12 +2,12 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const nameRequiredLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_SECURITY_SCHEME_FIELD_NAME_REQUIRED, + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_NAME_REQUIRED, source: 'apilint', - message: "should always have a 'name'", + message: "should always have a 'name' when type='apiKey'", severity: DiagnosticSeverity.Error, linterFunction: 'hasRequiredField', linterParams: ['name'], @@ -33,7 +33,7 @@ const nameRequiredLint: LinterMeta = { params: ['$ref'], }, ], - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default nameRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--type.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--type.ts index 2b40f287c..d8ecf1155 100644 --- a/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--type.ts +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/name--type.ts @@ -2,10 +2,10 @@ import { DiagnosticSeverity } from 'vscode-languageserver-types'; import ApilintCodes from '../../../codes'; import { LinterMeta } from '../../../../apidom-language-types'; -import { OpenAPI3 } from '../../target-specs'; +import { OpenAPI2, OpenAPI3 } from '../../target-specs'; const nameTypeLint: LinterMeta = { - code: ApilintCodes.OPENAPI3_0_SECURITY_SCHEME_FIELD_NAME_TYPE, + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_NAME_TYPE, source: 'apilint', message: 'name must be a string', severity: DiagnosticSeverity.Error, @@ -14,7 +14,7 @@ const nameTypeLint: LinterMeta = { marker: 'value', target: 'name', data: {}, - targetSpecs: OpenAPI3, + targetSpecs: [...OpenAPI2, ...OpenAPI3], }; export default nameTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/scopes--required.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/scopes--required.ts new file mode 100644 index 000000000..ed8bff08b --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/scopes--required.ts @@ -0,0 +1,35 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const scopesRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_SCOPES_REQUIRED, + source: 'apilint', + message: "should always have a 'scopes' when type='oauth2'", + severity: DiagnosticSeverity.Error, + linterFunction: 'hasRequiredField', + linterParams: ['scopes'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'scopes' field", + action: 'addChild', + snippetYaml: 'scopes: \n \n', + snippetJson: '"scopes": {\n \n },\n', + }, + ], + }, + conditions: [ + { + targets: [{ path: 'type' }], + function: 'apilintContainsValue', + params: ['oauth2'], + }, + ], + targetSpecs: OpenAPI2, +}; + +export default scopesRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/scopes--type.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/scopes--type.ts new file mode 100644 index 000000000..c8f17d79f --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/scopes--type.ts @@ -0,0 +1,20 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const scopesTypeLint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_SCOPES_TYPE, + source: 'apilint', + message: "'scopes' must be an object", + severity: DiagnosticSeverity.Error, + linterFunction: 'apilintElementOrClass', + linterParams: ['scopes'], + marker: 'value', + target: 'scopes', + data: {}, + targetSpecs: OpenAPI2, +}; + +export default scopesTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/token-url--format-uri.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/token-url--format-uri.ts new file mode 100644 index 000000000..5654e9be1 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/token-url--format-uri.ts @@ -0,0 +1,20 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const tokenUrlFormatURILint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_TOKEN_URL_FORMAT_URI, + source: 'apilint', + message: 'tokenUrl MUST be in the format of an absolute URL.', + severity: DiagnosticSeverity.Error, + linterFunction: 'apilintValidURI', + linterParams: [true], + marker: 'value', + target: 'tokenUrl', + data: {}, + targetSpecs: OpenAPI2, +}; + +export default tokenUrlFormatURILint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/token-url--required.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/token-url--required.ts new file mode 100644 index 000000000..8262f21e5 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/token-url--required.ts @@ -0,0 +1,41 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +const tokenUrlRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_TOKEN_URL_REQUIRED, + source: 'apilint', + message: + "should always have a 'tokenUrl' when 'type' is 'oauth2' and 'flow' is 'password', 'application' or 'accessCode'", + severity: DiagnosticSeverity.Error, + linterFunction: 'hasRequiredField', + linterParams: ['tokenUrl'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'tokenUrl' field", + action: 'addChild', + snippetYaml: 'tokenUrl: \n ', + snippetJson: '"tokenUrl": "",\n ', + }, + ], + }, + conditions: [ + { + targets: [{ path: 'type' }], + function: 'apilintContainsValue', + params: ['oauth2'], + }, + { + targets: [{ path: 'flow' }], + function: 'apilintValueOrArray', + params: [['password', 'application', 'accessCode']], + }, + ], + targetSpecs: OpenAPI2, +}; + +export default tokenUrlRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/security-scheme/lint/type--equals-2-0.ts b/packages/apidom-ls/src/config/openapi/security-scheme/lint/type--equals-2-0.ts new file mode 100644 index 000000000..61e184203 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/security-scheme/lint/type--equals-2-0.ts @@ -0,0 +1,20 @@ +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; +import { OpenAPI2 } from '../../target-specs'; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const typeEquals2_0Lint: LinterMeta = { + code: ApilintCodes.OPENAPI2_SECURITY_SCHEME_FIELD_TYPE_EQUALS, + source: 'apilint', + message: 'type must be one of allowed values: apiKey, http, oauth2, openIdConnect', + severity: DiagnosticSeverity.Error, + linterFunction: 'apilintValueOrArray', + linterParams: [['basic', 'apiKey', 'oauth2']], + marker: 'value', + target: 'type', + targetSpecs: OpenAPI2, +}; + +export default typeEquals2_0Lint;