diff --git a/README.md b/README.md index 00260b4..244d042 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,8 @@ Remove the `webhooks` object, if present. ### ⤓ JSON Schema related changes -OAS 3.0 uses an earlier JSON Schema version (Draft 7). The tool converts `examples` +OAS 3.0 uses an earlier JSON Schema version +([JSON Schema Specification Wright Draft 00](https://datatracker.ietf.org/doc/html/draft-wright-json-schema-00)). The tool converts `examples` in schemas to a single `example`. As a special case, if the resulting `example` includes an `id`, it is diff --git a/src/converter.ts b/src/converter.ts index 07c3358..3868dc5 100644 --- a/src/converter.ts +++ b/src/converter.ts @@ -370,7 +370,7 @@ export class Converter { private json(x) { return JSON.stringify(x, null, 2); } - + static readonly METHODS = ['delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace' ]; /** * OpenAPI 3.1 defines a new `openIdConnect` security scheme. * Down-convert the scheme to `oauth2` / authorization code flow. @@ -383,12 +383,11 @@ export class Converter { const scopes = {}; const paths = this.openapi30?.paths; for (const path in paths) { - for (const op in paths[path]) { - if (op === 'parameters') { - continue; - } - const operation = paths[path][op]; - const sec = operation?.security as object[]; + // filter out path.{$ref, summary, description, parameters, servers} and x-* specification extensions + const methods = Object.keys(paths[path]).filter((op) => Converter.METHODS.includes(op)); + methods.forEach(method => { + const operation = paths[path][method]; + const sec = (operation?.security || []) as object[]; sec.forEach((s) => { const requirement = s?.[schemeName] as string[]; if (requirement) { @@ -397,7 +396,7 @@ export class Converter { }); } }); - } + }); } return scopes; }; diff --git a/test/converter.spec.ts b/test/converter.spec.ts index 0b2f582..915eb57 100644 --- a/test/converter.spec.ts +++ b/test/converter.spec.ts @@ -773,6 +773,8 @@ describe('resolver test suite', () => { const scopes = converted.components.securitySchemes.accessToken.flows.authorizationCode.scopes; expect(scopes['scope1']).toEqual('Allow the application to access your personal profile data.'); expect(scopes['scope3']).toEqual(`TODO: describe the 'scope3' scope`); + const publicOp = (converted.paths['/users/{appId}/public-preferences'] as object)['get']; + expect(publicOp['security']).toBeFalsy(); done(); }); }); @@ -950,4 +952,3 @@ test('contentMediaType with existing unexpected format', (done) => { // TODO how to check that Converter logged to console.warn ? done(); }); - diff --git a/test/data/openapi.yaml b/test/data/openapi.yaml index e8f77a2..c209bdb 100644 --- a/test/data/openapi.yaml +++ b/test/data/openapi.yaml @@ -1,6 +1,6 @@ openapi: 3.1.0 info: - title: Transactions + title: Application Preferences (Example OpenAPI) description: ... version: 0.1.2 contact: @@ -18,10 +18,12 @@ tags: description: Application Preferences paths: /users/{appId}/preferences: + summary: Application preferences + description: A user's preferences for an application parameters: - $ref: '#/components/parameters/appIdPathParam' get: - summary: Return preferences for a application + summary: Return preferences for an application description: ... operationId: listPreferences tags: @@ -66,7 +68,7 @@ paths: application/pdf: schema: type: string - contentMediaType: application/json + contentMediaType: application/pdf contentEncoding: base64 maxLength: 5000000 '400': @@ -92,6 +94,58 @@ paths: - scope2 - scope3 - scope4 + /users/{appId}/public-preferences: + parameters: + - $ref: '#/components/parameters/appIdPathParam' + get: + summary: Return public preferences for an application, without auth + description: ... + operationId: listPublicPreferences + tags: + - Preferences + parameters: + - name: categories + description: >- + Filter preferences to only those whose `category` is in this + pipe-separated list. + in: query + style: pipeDelimited + schema: + type: array + minItems: 1 + maxItems: 16 + examples: + - - Presentation + - - Presentation + - Notifications + items: + type: string + - name: type + description: >- + Filter preferences only those whose `type` is in this pipe-separated + list. + in: query + style: pipeDelimited + schema: + type: array + minItems: 1 + maxItems: 4 + uniqueItems: true + items: + type: string + responses: + '200': + description: OK. + content: + application/json: + schema: + $ref: '#/components/schemas/preferences' + application/pdf: + schema: + type: string + contentMediaType: application/pdf + contentEncoding: base64 + maxLength: 5000000 components: securitySchemes: accessToken: @@ -437,4 +491,4 @@ components: minlength is for no milliseconds, such as '2021-10-30T19:06:00Z' maxLength is for '.' plus up to 9 digits for milliseconds, - such as '2021-10-30T19:06:04.999000999Z' \ No newline at end of file + such as '2021-10-30T19:06:04.999000999Z'