From 04493ba9339e68ceaa22917e8f14452ae9680162 Mon Sep 17 00:00:00 2001 From: adamsosterics Date: Fri, 29 Aug 2025 17:09:50 +0200 Subject: [PATCH] feat: show sets of required scopes correctly It is possible to define alternative required scopes for an operation and in the security header of the operation it is rendered correctly. However, in the "Required scopes" part it looks like that all these scopes are required. With these changes, the "Required scopes" part shows the required scopes per set. See: https://github.com/OAI/OpenAPI-Specification/discussions/3001#discussioncomment-3456275 --- .../SecurityRequirement/RequiredScopesRow.tsx | 17 ++++++++++++----- .../SecurityRequirement/SecurityRequirement.tsx | 10 +++++----- .../SecurityRequirement.test.tsx.snap | 8 +++++--- .../fixtures/simple-security-fixture.json | 6 +++++- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/components/SecurityRequirement/RequiredScopesRow.tsx b/src/components/SecurityRequirement/RequiredScopesRow.tsx index 8f899b6058..c802f7305f 100644 --- a/src/components/SecurityRequirement/RequiredScopesRow.tsx +++ b/src/components/SecurityRequirement/RequiredScopesRow.tsx @@ -1,15 +1,22 @@ import * as React from 'react'; -export const RequiredScopesRow = ({ scopes }: { scopes: string[] }): JSX.Element | null => { - if (!scopes.length) return null; +export const RequiredScopesRow = ({ scopeSets }: { scopeSets: string[][] }): JSX.Element | null => { + if (!scopeSets.length) return null; return (
Required scopes: - {scopes.map((scope, idx) => { + {scopeSets.map((scopeSet, ssIdx) => { return ( - - {scope}{' '} + + {scopeSet.map((scope, idx) => { + return ( + + {scope}{' '} + + ); + })} + {ssIdx + 1 < scopeSets.length && ' or '} ); })} diff --git a/src/components/SecurityRequirement/SecurityRequirement.tsx b/src/components/SecurityRequirement/SecurityRequirement.tsx index d578284e54..7cb38f6205 100644 --- a/src/components/SecurityRequirement/SecurityRequirement.tsx +++ b/src/components/SecurityRequirement/SecurityRequirement.tsx @@ -65,7 +65,7 @@ export function SecurityRequirements(props: SecurityRequirementsProps) { key={scheme.id} scheme={scheme} RequiredScopes={ - + } /> @@ -83,8 +83,8 @@ const LockIcon = () => ( ); -function getRequiredScopes(id: string, securities: SecurityRequirementModel[]): string[] { - const allScopes: string[] = []; +function getRequiredScopeSets(id: string, securities: SecurityRequirementModel[]): string[][] { + const allScopes: string[][] = []; let securitiesLength = securities.length; while (securitiesLength--) { @@ -92,8 +92,8 @@ function getRequiredScopes(id: string, securities: SecurityRequirementModel[]): let schemesLength = security.schemes.length; while (schemesLength--) { const scheme = security.schemes[schemesLength]; - if (scheme.id === id && Array.isArray(scheme.scopes)) { - allScopes.push(...scheme.scopes); + if (scheme.id === id && Array.isArray(scheme.scopes) && scheme.scopes.length) { + allScopes.unshift(scheme.scopes); } } } diff --git a/src/components/__tests__/__snapshots__/SecurityRequirement.test.tsx.snap b/src/components/__tests__/__snapshots__/SecurityRequirement.test.tsx.snap index cfea66c7fe..1f47ea9527 100644 --- a/src/components/__tests__/__snapshots__/SecurityRequirement.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/SecurityRequirement.test.tsx.snap @@ -5,18 +5,20 @@ exports[`SecurityRequirement should render SecurityDefs 1`] = ` OAuth2 is also a safer and more secure way to give you access.

Security Scheme Type: OAuth2
Flow type: implicit
Scopes:
  • write:pets -

    modify pets in your account

  • read:pets -

    read your pets

    +
  • update:pets -

    update your pets

GitLab_PersonalAccessToken

GitLab Personal Access Token description

Security Scheme Type: API Key
Header parameter name: PRIVATE-TOKEN

GitLab_OpenIdConnect

GitLab OpenIdConnect description

Security Scheme Type: OpenID Connect

basicAuth

Security Scheme Type: HTTP
HTTP Authorization Scheme: basic
" `; -exports[`SecurityRequirement should render authDefinition 1`] = `"
Authorizations:
(API Key: GitLab_PersonalAccessTokenOpenID Connect: GitLab_OpenIdConnectHTTP: basicAuth) OAuth2: petstore_auth
,"`; +exports[`SecurityRequirement should render authDefinition 1`] = `"
Authorizations:
(API Key: GitLab_PersonalAccessTokenOpenID Connect: GitLab_OpenIdConnectHTTP: basicAuth) OAuth2: petstore_authOAuth2: petstore_auth
,"`; exports[`SecurityRequirement should render authDefinition 2`] = ` -"
Authorizations:
(API Key: GitLab_PersonalAccessTokenOpenID Connect: GitLab_OpenIdConnectHTTP: basicAuth) OAuth2: petstore_auth (write:petsread:pets)
OAuth2: petstore_auth

Get access to data while protecting your account credentials. +"

Authorizations:
(API Key: GitLab_PersonalAccessTokenOpenID Connect: GitLab_OpenIdConnectHTTP: basicAuth) OAuth2: petstore_auth (write:petsread:pets) OAuth2: petstore_auth (update:pets)
OAuth2: petstore_auth

Get access to data while protecting your account credentials. OAuth2 is also a safer and more secure way to give you access.

-
Flow type: implicit
Required scopes: write:pets read:pets
Scopes:
  • write:pets -

    modify pets in your account

    +
    Flow type: implicit
    Required scopes: write:pets read:pets or update:pets
    Scopes:
    • write:pets -

      modify pets in your account

    • read:pets -

      read your pets

      +
    • update:pets -

      update your pets

API Key: GitLab_PersonalAccessToken

GitLab Personal Access Token description

Header parameter name: PRIVATE-TOKEN
OpenID Connect: GitLab_OpenIdConnect

GitLab OpenIdConnect description

HTTP: basicAuth
HTTP Authorization Scheme: basic
," diff --git a/src/components/__tests__/fixtures/simple-security-fixture.json b/src/components/__tests__/fixtures/simple-security-fixture.json index 084ef84ac0..536525d9ee 100644 --- a/src/components/__tests__/fixtures/simple-security-fixture.json +++ b/src/components/__tests__/fixtures/simple-security-fixture.json @@ -23,6 +23,9 @@ }, { "petstore_auth": ["write:pets", "read:pets"] + }, + { + "petstore_auth": ["update:pets"] } ] } @@ -39,7 +42,8 @@ "authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog", "scopes": { "write:pets": "modify pets in your account", - "read:pets": "read your pets" + "read:pets": "read your pets", + "update:pets": "update your pets" } } }