mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-25 18:13:44 +03:00
feat: remove auth section (#2022)
This commit is contained in:
parent
b98c7a0d34
commit
a863302cc8
|
@ -232,7 +232,6 @@ You can use all of the following options with the standalone version of the <red
|
||||||
* `lazyRendering` - _Not implemented yet_ ~~if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\redocly.github.io/redoc) for the example.~~
|
* `lazyRendering` - _Not implemented yet_ ~~if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\redocly.github.io/redoc) for the example.~~
|
||||||
* `menuToggle` - if true clicking second time on expanded menu item will collapse it, default `true`.
|
* `menuToggle` - if true clicking second time on expanded menu item will collapse it, default `true`.
|
||||||
* `nativeScrollbars` - use native scrollbar for sidemenu instead of perfect-scroll (scrolling performance optimization for big specs).
|
* `nativeScrollbars` - use native scrollbar for sidemenu instead of perfect-scroll (scrolling performance optimization for big specs).
|
||||||
* `noAutoAuth` - do not inject Authentication section automatically.
|
|
||||||
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
||||||
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one.
|
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one.
|
||||||
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
||||||
|
|
71
src/components/SecurityRequirement/OAuthFlow.tsx
Normal file
71
src/components/SecurityRequirement/OAuthFlow.tsx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { OpenAPISecurityScheme } from '../../types';
|
||||||
|
import { SecurityRow } from './styled.elements';
|
||||||
|
import { SeeMore } from '../SeeMore/SeeMore';
|
||||||
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
|
||||||
|
export interface OAuthFlowProps {
|
||||||
|
type: string;
|
||||||
|
flow: OpenAPISecurityScheme['flows'][keyof OpenAPISecurityScheme['flows']];
|
||||||
|
RequiredScopes?: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OAuthFlowComponent(props: OAuthFlowProps) {
|
||||||
|
const { type, flow, RequiredScopes } = props;
|
||||||
|
const scopesNames = Object.keys(flow?.scopes || {});
|
||||||
|
console.log('rended');
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>Flow type: </b>
|
||||||
|
<code>{type} </code>
|
||||||
|
</SecurityRow>
|
||||||
|
{(type === 'implicit' || type === 'authorizationCode') && (
|
||||||
|
<SecurityRow>
|
||||||
|
<strong> Authorization URL: </strong>
|
||||||
|
<code>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={(flow as any).authorizationUrl}>
|
||||||
|
{(flow as any).authorizationUrl}
|
||||||
|
</a>
|
||||||
|
</code>
|
||||||
|
</SecurityRow>
|
||||||
|
)}
|
||||||
|
{(type === 'password' || type === 'clientCredentials' || type === 'authorizationCode') && (
|
||||||
|
<SecurityRow>
|
||||||
|
<b> Token URL: </b>
|
||||||
|
<code>{(flow as any).tokenUrl}</code>
|
||||||
|
</SecurityRow>
|
||||||
|
)}
|
||||||
|
{flow!.refreshUrl && (
|
||||||
|
<SecurityRow>
|
||||||
|
<strong> Refresh URL: </strong>
|
||||||
|
{flow!.refreshUrl}
|
||||||
|
</SecurityRow>
|
||||||
|
)}
|
||||||
|
{!!scopesNames.length && (
|
||||||
|
<>
|
||||||
|
{RequiredScopes || null}
|
||||||
|
<SecurityRow>
|
||||||
|
<b> Scopes: </b>
|
||||||
|
</SecurityRow>
|
||||||
|
<SeeMore height="4em">
|
||||||
|
<ul>
|
||||||
|
{scopesNames.map(scope => (
|
||||||
|
<li key={scope}>
|
||||||
|
<code>{scope}</code> -{' '}
|
||||||
|
<Markdown
|
||||||
|
className={'redoc-markdown'}
|
||||||
|
inline={true}
|
||||||
|
source={flow!.scopes[scope] || ''}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</SeeMore>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OAuthFlow = React.memo<OAuthFlowProps>(OAuthFlowComponent);
|
18
src/components/SecurityRequirement/RequiredScopesRow.tsx
Normal file
18
src/components/SecurityRequirement/RequiredScopesRow.tsx
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export const RequiredScopesRow = ({ scopes }: { scopes: string[] }): JSX.Element | null => {
|
||||||
|
if (!scopes.length) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<b>Required scopes: </b>
|
||||||
|
{scopes.map((scope, idx) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment key={idx}>
|
||||||
|
<code>{scope}</code>{' '}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
65
src/components/SecurityRequirement/SecurityDetails.tsx
Normal file
65
src/components/SecurityRequirement/SecurityDetails.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { SecuritySchemeModel } from '../../services';
|
||||||
|
import { titleize } from '../../utils';
|
||||||
|
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
||||||
|
import { SecurityRow } from './styled.elements';
|
||||||
|
import { OAuthFlow } from './OAuthFlow';
|
||||||
|
|
||||||
|
interface SecuritySchemaProps {
|
||||||
|
RequiredScopes?: JSX.Element;
|
||||||
|
scheme: SecuritySchemeModel;
|
||||||
|
}
|
||||||
|
export function SecurityDetails(props: SecuritySchemaProps) {
|
||||||
|
const { RequiredScopes, scheme } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledMarkdownBlock>
|
||||||
|
{scheme.apiKey ? (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>{titleize(scheme.apiKey.in || '')} parameter name: </b>
|
||||||
|
<code>{scheme.apiKey.name}</code>
|
||||||
|
</SecurityRow>
|
||||||
|
{RequiredScopes}
|
||||||
|
</>
|
||||||
|
) : scheme.http ? (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>HTTP Authorization Scheme: </b>
|
||||||
|
<code>{scheme.http.scheme}</code>
|
||||||
|
</SecurityRow>
|
||||||
|
<SecurityRow>
|
||||||
|
{scheme.http.scheme === 'bearer' && scheme.http.bearerFormat && (
|
||||||
|
<>
|
||||||
|
<b>Bearer format: </b>
|
||||||
|
<code>{scheme.http.bearerFormat}</code>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</SecurityRow>
|
||||||
|
{RequiredScopes}
|
||||||
|
</>
|
||||||
|
) : scheme.openId ? (
|
||||||
|
<>
|
||||||
|
<SecurityRow>
|
||||||
|
<b>Connect URL: </b>
|
||||||
|
<code>
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={scheme.openId.connectUrl}>
|
||||||
|
{scheme.openId.connectUrl}
|
||||||
|
</a>
|
||||||
|
</code>
|
||||||
|
</SecurityRow>
|
||||||
|
{RequiredScopes}
|
||||||
|
</>
|
||||||
|
) : scheme.flows ? (
|
||||||
|
Object.keys(scheme.flows).map(type => (
|
||||||
|
<OAuthFlow
|
||||||
|
key={type}
|
||||||
|
type={type}
|
||||||
|
RequiredScopes={RequiredScopes}
|
||||||
|
flow={scheme.flows[type]}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : null}
|
||||||
|
</StyledMarkdownBlock>
|
||||||
|
);
|
||||||
|
}
|
43
src/components/SecurityRequirement/SecurityHeader.tsx
Normal file
43
src/components/SecurityRequirement/SecurityHeader.tsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
||||||
|
import {
|
||||||
|
ScopeName,
|
||||||
|
SecurityRequirementAndWrap,
|
||||||
|
SecurityRequirementOrWrap,
|
||||||
|
} from './styled.elements';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { AUTH_TYPES } from '../SecuritySchemes/SecuritySchemes';
|
||||||
|
|
||||||
|
export interface SecurityRequirementProps {
|
||||||
|
security: SecurityRequirementModel;
|
||||||
|
showSecuritySchemeType?: boolean;
|
||||||
|
expanded: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SecurityHeader(props: SecurityRequirementProps) {
|
||||||
|
const { security, showSecuritySchemeType, expanded } = props;
|
||||||
|
|
||||||
|
const grouping = security.schemes.length > 1;
|
||||||
|
return (
|
||||||
|
<SecurityRequirementOrWrap expanded={expanded}>
|
||||||
|
{grouping && '('}
|
||||||
|
{security.schemes.map(scheme => {
|
||||||
|
return (
|
||||||
|
<SecurityRequirementAndWrap key={scheme.id}>
|
||||||
|
{showSecuritySchemeType && `${AUTH_TYPES[scheme.type] || scheme.type}: `}
|
||||||
|
<i>{scheme.displayName}</i>
|
||||||
|
{expanded && scheme.scopes.length
|
||||||
|
? [
|
||||||
|
' (',
|
||||||
|
scheme.scopes.map<React.ReactNode>(scope => (
|
||||||
|
<ScopeName key={scope}>{scope}</ScopeName>
|
||||||
|
)),
|
||||||
|
') ',
|
||||||
|
]
|
||||||
|
: null}
|
||||||
|
</SecurityRequirementAndWrap>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{grouping && ') '}
|
||||||
|
</SecurityRequirementOrWrap>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,153 +1,102 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
import styled, { media } from '../../styled-components';
|
|
||||||
|
|
||||||
import { Link, UnderlinedHeader } from '../../common-elements/';
|
|
||||||
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
||||||
import { linksCss } from '../Markdown/styled.elements';
|
import {
|
||||||
|
AuthHeader,
|
||||||
const ScopeNameList = styled.ul`
|
AuthHeaderColumn,
|
||||||
display: inline;
|
SecuritiesColumn,
|
||||||
list-style: none;
|
SecurityDetailsStyle,
|
||||||
padding: 0;
|
Wrap,
|
||||||
|
} from './styled.elements';
|
||||||
li {
|
import { useStore } from '../StoreBuilder';
|
||||||
display: inherit;
|
import { SecurityHeader } from './SecurityHeader';
|
||||||
|
import { RequiredScopesRow } from './RequiredScopesRow';
|
||||||
&:after {
|
import { AUTH_TYPES } from '../SecuritySchemes/SecuritySchemes';
|
||||||
content: ',';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
}
|
import { SecurityDetails } from './SecurityDetails';
|
||||||
&:last-child:after {
|
import { ShelfIcon } from '../../common-elements';
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ScopeName = styled.code`
|
|
||||||
font-size: ${props => props.theme.typography.code.fontSize};
|
|
||||||
font-family: ${props => props.theme.typography.code.fontFamily};
|
|
||||||
border: 1px solid ${({ theme }) => theme.colors.border.dark};
|
|
||||||
margin: 0 3px;
|
|
||||||
padding: 0.2em;
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SecurityRequirementAndWrap = styled.span`
|
|
||||||
&:after {
|
|
||||||
content: ' AND ';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child:after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
${linksCss};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SecurityRequirementOrWrap = styled.span`
|
|
||||||
&:before {
|
|
||||||
content: '( ';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
&:after {
|
|
||||||
content: ' ) OR ';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
&:last-child:after {
|
|
||||||
content: ' )';
|
|
||||||
}
|
|
||||||
|
|
||||||
&:only-child:before,
|
|
||||||
&:only-child:after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
${linksCss};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface SecurityRequirementProps {
|
|
||||||
security: SecurityRequirementModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SecurityRequirement extends React.PureComponent<SecurityRequirementProps> {
|
|
||||||
render() {
|
|
||||||
const security = this.props.security;
|
|
||||||
return (
|
|
||||||
<SecurityRequirementOrWrap>
|
|
||||||
{security.schemes.length ? (
|
|
||||||
security.schemes.map(scheme => {
|
|
||||||
return (
|
|
||||||
<SecurityRequirementAndWrap key={scheme.id}>
|
|
||||||
<Link to={scheme.sectionId}>{scheme.displayName}</Link>
|
|
||||||
{scheme.scopes.length > 0 && ' ('}
|
|
||||||
<ScopeNameList>
|
|
||||||
{scheme.scopes.map(scope => (
|
|
||||||
<li key={scope}>
|
|
||||||
<ScopeName>{scope}</ScopeName>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ScopeNameList>
|
|
||||||
{scheme.scopes.length > 0 && ') '}
|
|
||||||
</SecurityRequirementAndWrap>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<SecurityRequirementAndWrap>None</SecurityRequirementAndWrap>
|
|
||||||
)}
|
|
||||||
</SecurityRequirementOrWrap>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuthHeaderColumn = styled.div`
|
|
||||||
flex: 1 1 auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SecuritiesColumn = styled.div`
|
|
||||||
width: ${props => props.theme.schema.defaultDetailsWidth};
|
|
||||||
${media.lessThan('small')`
|
|
||||||
margin-top: 10px;
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const AuthHeader = styled(UnderlinedHeader)`
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Wrap = styled.div`
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
margin: 1em 0;
|
|
||||||
|
|
||||||
${media.lessThan('small')`
|
|
||||||
flex-direction: column;
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface SecurityRequirementsProps {
|
export interface SecurityRequirementsProps {
|
||||||
securities: SecurityRequirementModel[];
|
securities: SecurityRequirementModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SecurityRequirements extends React.PureComponent<SecurityRequirementsProps> {
|
export function SecurityRequirements(props: SecurityRequirementsProps) {
|
||||||
render() {
|
const store = useStore();
|
||||||
const securities = this.props.securities;
|
const showSecuritySchemeType = store?.options.showSecuritySchemeType;
|
||||||
if (!securities.length) {
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
|
||||||
|
const { securities } = props;
|
||||||
|
|
||||||
|
if (!securities?.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const operationSecuritySchemes = store?.spec.securitySchemes.schemes.filter(({ id }) => {
|
||||||
|
return securities.find(security => security.schemes.find(scheme => scheme.id === id));
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrap>
|
<>
|
||||||
<AuthHeaderColumn>
|
<Wrap expanded={expanded}>
|
||||||
|
<AuthHeaderColumn onClick={() => setExpanded(!expanded)}>
|
||||||
<AuthHeader>Authorizations:</AuthHeader>
|
<AuthHeader>Authorizations:</AuthHeader>
|
||||||
|
<ShelfIcon size={'1.3em'} direction={expanded ? 'down' : 'right'} />
|
||||||
</AuthHeaderColumn>
|
</AuthHeaderColumn>
|
||||||
<SecuritiesColumn>
|
<SecuritiesColumn expanded={expanded}>
|
||||||
{securities.map((security, idx) => (
|
{securities.map((security, idx) => (
|
||||||
<SecurityRequirement key={idx} security={security} />
|
<SecurityHeader
|
||||||
|
key={idx}
|
||||||
|
expanded={expanded}
|
||||||
|
showSecuritySchemeType={showSecuritySchemeType}
|
||||||
|
security={security}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</SecuritiesColumn>
|
</SecuritiesColumn>
|
||||||
</Wrap>
|
</Wrap>
|
||||||
|
{expanded &&
|
||||||
|
operationSecuritySchemes?.length &&
|
||||||
|
operationSecuritySchemes.map((scheme, idx) => (
|
||||||
|
<SecurityDetailsStyle key={idx}>
|
||||||
|
<h5>
|
||||||
|
<LockIcon /> {AUTH_TYPES[scheme.type] || scheme.type}: {scheme.id}
|
||||||
|
</h5>
|
||||||
|
<Markdown source={scheme.description || ''} />
|
||||||
|
<SecurityDetails
|
||||||
|
key={scheme.id}
|
||||||
|
scheme={scheme}
|
||||||
|
RequiredScopes={
|
||||||
|
<RequiredScopesRow scopes={getRequiredScopes(scheme.id, securities)} />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SecurityDetailsStyle>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LockIcon = () => (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="11" height="11">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
function getRequiredScopes(id: string, securities: SecurityRequirementModel[]): string[] {
|
||||||
|
const allScopes: string[] = [];
|
||||||
|
let securitiesLength = securities.length;
|
||||||
|
|
||||||
|
while (securitiesLength--) {
|
||||||
|
const security = securities[securitiesLength];
|
||||||
|
let schemesLength = security.schemes.length;
|
||||||
|
while (schemesLength--) {
|
||||||
|
const scheme = security.schemes[schemesLength];
|
||||||
|
if (scheme.id === id) {
|
||||||
|
allScopes.push(...scheme.scopes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(new Set(allScopes));
|
||||||
}
|
}
|
||||||
|
|
129
src/components/SecurityRequirement/styled.elements.ts
Normal file
129
src/components/SecurityRequirement/styled.elements.ts
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { linksCss } from '../Markdown/styled.elements';
|
||||||
|
import { media } from '../../styled-components';
|
||||||
|
import { UnderlinedHeader } from '../../common-elements';
|
||||||
|
|
||||||
|
export const Header = styled.div`
|
||||||
|
background-color: #e4e7eb;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ScopeNameList = styled.ul`
|
||||||
|
display: inline;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: inherit;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ',';
|
||||||
|
}
|
||||||
|
&:last-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ScopeName = styled.code`
|
||||||
|
font-size: ${props => props.theme.typography.code.fontSize};
|
||||||
|
font-family: ${props => props.theme.typography.code.fontFamily};
|
||||||
|
margin: 0 3px;
|
||||||
|
padding: 0.2em;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ',';
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityRequirementAndWrap = styled.span`
|
||||||
|
&:after {
|
||||||
|
content: ' and ';
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
${linksCss};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityRequirementOrWrap = styled.span<{ expanded?: boolean }>`
|
||||||
|
${p => !p.expanded && `white-space: nowrap;`}
|
||||||
|
&:after {
|
||||||
|
content: ' or ';
|
||||||
|
${p => p.expanded && `content: ' or \\a';`}
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child:after,
|
||||||
|
&:only-child:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
${linksCss};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthHeaderColumn = styled.div`
|
||||||
|
flex: 1 1 auto;
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecuritiesColumn = styled.div<{ expanded?: boolean }>`
|
||||||
|
width: ${props => props.theme.schema.defaultDetailsWidth};
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
${p =>
|
||||||
|
p.expanded &&
|
||||||
|
`background: ${p.theme.colors.gray['100']};
|
||||||
|
padding: 8px 9.6px;
|
||||||
|
margin: 20px 0;
|
||||||
|
width: 100%;
|
||||||
|
`};
|
||||||
|
${media.lessThan('small')`
|
||||||
|
margin-top: 10px;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const AuthHeader = styled(UnderlinedHeader)`
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Wrap = styled.div<{ expanded?: boolean }>`
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
margin: 1em 0;
|
||||||
|
flex-direction: ${p => (p.expanded ? 'column' : 'row')};
|
||||||
|
${media.lessThan('small')`
|
||||||
|
flex-direction: column;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityRow = styled.div`
|
||||||
|
margin: 0.5em 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SecurityDetailsStyle = styled.div`
|
||||||
|
border-bottom: 1px solid ${({ theme }) => theme.colors.border.dark};
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
padding-bottom: 0.7em;
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
line-height: 1em;
|
||||||
|
margin: 0 0 0.6em;
|
||||||
|
font-size: ${({ theme }) => theme.typography.fontSize};
|
||||||
|
}
|
||||||
|
|
||||||
|
.redoc-markdown p:first-child {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
`;
|
|
@ -1,72 +1,18 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { SecuritySchemesModel } from '../../services/models';
|
import { SecuritySchemesModel } from '../../services';
|
||||||
|
import { H2, Row, ShareLink, MiddlePanel, Section } from '../../common-elements';
|
||||||
import { H2, MiddlePanel, Row, Section, ShareLink } from '../../common-elements';
|
|
||||||
import { OpenAPISecurityScheme } from '../../types';
|
|
||||||
import { titleize } from '../../utils/helpers';
|
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
import { SecurityDetails } from '../SecurityRequirement/SecurityDetails';
|
||||||
|
import { SecurityDetailsStyle, SecurityRow } from '../SecurityRequirement/styled.elements';
|
||||||
|
|
||||||
const AUTH_TYPES = {
|
export const AUTH_TYPES = {
|
||||||
oauth2: 'OAuth2',
|
oauth2: 'OAuth2',
|
||||||
apiKey: 'API Key',
|
apiKey: 'API Key',
|
||||||
http: 'HTTP',
|
http: 'HTTP',
|
||||||
openIdConnect: 'OpenID Connect',
|
openIdConnect: 'OpenID Connect',
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface OAuthFlowProps {
|
|
||||||
type: string;
|
|
||||||
flow: OpenAPISecurityScheme['flows'][keyof OpenAPISecurityScheme['flows']];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OAuthFlow extends React.PureComponent<OAuthFlowProps> {
|
|
||||||
render() {
|
|
||||||
const { type, flow } = this.props;
|
|
||||||
const scopesNames = Object.keys(flow?.scopes || {});
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<th> {type} OAuth Flow </th>
|
|
||||||
<td>
|
|
||||||
{type === 'implicit' || type === 'authorizationCode' ? (
|
|
||||||
<div>
|
|
||||||
<strong> Authorization URL: </strong>
|
|
||||||
{(flow as any).authorizationUrl}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{type === 'password' || type === 'clientCredentials' || type === 'authorizationCode' ? (
|
|
||||||
<div>
|
|
||||||
<strong> Token URL: </strong>
|
|
||||||
{(flow as any).tokenUrl}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{flow!.refreshUrl && (
|
|
||||||
<div>
|
|
||||||
<strong> Refresh URL: </strong>
|
|
||||||
{flow!.refreshUrl}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!!scopesNames.length && (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<strong> Scopes: </strong>
|
|
||||||
</div>
|
|
||||||
<ul>
|
|
||||||
{scopesNames.map(scope => (
|
|
||||||
<li key={scope}>
|
|
||||||
<code>{scope}</code> -{' '}
|
|
||||||
<Markdown inline={true} source={flow!.scopes[scope] || ''} />
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SecurityDefsProps {
|
export interface SecurityDefsProps {
|
||||||
securitySchemes: SecuritySchemesModel;
|
securitySchemes: SecuritySchemesModel;
|
||||||
}
|
}
|
||||||
|
@ -82,52 +28,13 @@ export class SecurityDefs extends React.PureComponent<SecurityDefsProps> {
|
||||||
{scheme.displayName}
|
{scheme.displayName}
|
||||||
</H2>
|
</H2>
|
||||||
<Markdown source={scheme.description || ''} />
|
<Markdown source={scheme.description || ''} />
|
||||||
<StyledMarkdownBlock>
|
<SecurityDetailsStyle>
|
||||||
<table className="security-details">
|
<SecurityRow>
|
||||||
<tbody>
|
<b>Security Scheme Type: </b>
|
||||||
<tr>
|
<span>{AUTH_TYPES[scheme.type] || scheme.type}</span>
|
||||||
<th> Security Scheme Type </th>
|
</SecurityRow>
|
||||||
<td> {AUTH_TYPES[scheme.type] || scheme.type} </td>
|
<SecurityDetails scheme={scheme} />
|
||||||
</tr>
|
</SecurityDetailsStyle>
|
||||||
{scheme.apiKey ? (
|
|
||||||
<tr>
|
|
||||||
<th> {titleize(scheme.apiKey.in || '')} parameter name:</th>
|
|
||||||
<td> {scheme.apiKey.name} </td>
|
|
||||||
</tr>
|
|
||||||
) : scheme.http ? (
|
|
||||||
[
|
|
||||||
<tr key="scheme">
|
|
||||||
<th> HTTP Authorization Scheme </th>
|
|
||||||
<td> {scheme.http.scheme} </td>
|
|
||||||
</tr>,
|
|
||||||
scheme.http.scheme === 'bearer' && scheme.http.bearerFormat && (
|
|
||||||
<tr key="bearer">
|
|
||||||
<th> Bearer format </th>
|
|
||||||
<td> "{scheme.http.bearerFormat}" </td>
|
|
||||||
</tr>
|
|
||||||
),
|
|
||||||
]
|
|
||||||
) : scheme.openId ? (
|
|
||||||
<tr>
|
|
||||||
<th> Connect URL </th>
|
|
||||||
<td>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
href={scheme.openId.connectUrl}
|
|
||||||
>
|
|
||||||
{scheme.openId.connectUrl}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : scheme.flows ? (
|
|
||||||
Object.keys(scheme.flows).map(type => (
|
|
||||||
<OAuthFlow key={type} type={type} flow={scheme.flows[type]} />
|
|
||||||
))
|
|
||||||
) : null}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</StyledMarkdownBlock>
|
|
||||||
</MiddlePanel>
|
</MiddlePanel>
|
||||||
</Row>
|
</Row>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
65
src/components/SeeMore/SeeMore.tsx
Normal file
65
src/components/SeeMore/SeeMore.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const TOLERANCE_PX = 20;
|
||||||
|
|
||||||
|
interface SeeMoreProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
height: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SeeMore({ children, height }: SeeMoreProps): JSX.Element {
|
||||||
|
const ref = React.createRef() as React.RefObject<HTMLDivElement>;
|
||||||
|
const [showMore, setShowMore] = React.useState(false);
|
||||||
|
const [showLink, setShowLink] = React.useState(false);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (ref.current && ref.current.clientHeight + TOLERANCE_PX < ref.current.scrollHeight) {
|
||||||
|
setShowLink(true);
|
||||||
|
}
|
||||||
|
}, [ref]);
|
||||||
|
|
||||||
|
const onClickMore = () => {
|
||||||
|
setShowMore(!showMore);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Container
|
||||||
|
ref={ref}
|
||||||
|
className={showMore ? '' : 'container'}
|
||||||
|
style={{ height: showMore ? 'auto' : height }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Container>
|
||||||
|
<ButtonContainer dimmed={!showMore}>
|
||||||
|
{showLink && (
|
||||||
|
<ButtonLinkStyled onClick={onClickMore}>
|
||||||
|
{showMore ? 'See less' : 'See more'}
|
||||||
|
</ButtonLinkStyled>
|
||||||
|
)}
|
||||||
|
</ButtonContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
overflow-y: hidden;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonContainer = styled.div<{ dimmed?: boolean }>`
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5em;
|
||||||
|
${({ dimmed }) =>
|
||||||
|
dimmed &&
|
||||||
|
`background-image: linear-gradient(to bottom, transparent,rgb(255 255 255));
|
||||||
|
position: relative;
|
||||||
|
top: -0.5em;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
background-position-y: -1em;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonLinkStyled = styled.a`
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { createContext } from 'react';
|
import { createContext, useContext } from 'react';
|
||||||
|
|
||||||
import { AppStore } from '../services/';
|
import { AppStore } from '../services/';
|
||||||
import { RedocRawOptions } from '../services/RedocNormalizedOptions';
|
import { RedocRawOptions } from '../services/RedocNormalizedOptions';
|
||||||
|
@ -79,3 +79,7 @@ export function StoreBuilder(props: StoreBuilderProps) {
|
||||||
store,
|
store,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useStore(): AppStore | undefined {
|
||||||
|
return useContext(StoreContext);
|
||||||
|
}
|
||||||
|
|
|
@ -1,28 +1,52 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
|
|
||||||
import { OpenAPIParser } from '../../services';
|
import {
|
||||||
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
createStore,
|
||||||
import { SecurityRequirement } from '../SecurityRequirement/SecurityRequirement';
|
OpenAPIParser,
|
||||||
import { RedocNormalizedOptions } from '../../services/RedocNormalizedOptions';
|
OperationModel,
|
||||||
|
RedocNormalizedOptions,
|
||||||
|
SecuritySchemesModel,
|
||||||
|
} from '../../services';
|
||||||
|
import { StoreProvider } from '../StoreBuilder';
|
||||||
|
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
||||||
|
import { withTheme } from '../testProviders';
|
||||||
|
import { SecurityDefs } from '../SecuritySchemes/SecuritySchemes';
|
||||||
|
import * as simpleSecurityFixture from './fixtures/simple-security-fixture.json';
|
||||||
|
|
||||||
const options = new RedocNormalizedOptions({});
|
|
||||||
describe('Components', () => {
|
|
||||||
describe('SecurityRequirement', () => {
|
describe('SecurityRequirement', () => {
|
||||||
describe('SecurityRequirement', () => {
|
it('should render authDefinition', async () => {
|
||||||
it("should render 'None' when empty object in security open api", () => {
|
const store = await createStore(simpleSecurityFixture, undefined, {
|
||||||
const parser = new OpenAPIParser(
|
showSecuritySchemeType: true,
|
||||||
{ openapi: '3.0', info: { title: 'test', version: '0' }, paths: {} },
|
});
|
||||||
undefined,
|
|
||||||
options,
|
store.spec.contentItems.forEach((item: OperationModel) => {
|
||||||
|
if (item.security) {
|
||||||
|
const component = mount(
|
||||||
|
withTheme(
|
||||||
|
<StoreProvider value={store}>
|
||||||
|
<SecurityRequirements securities={item.security} />,
|
||||||
|
</StoreProvider>,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const securityRequirement = new SecurityRequirementModel({}, parser);
|
expect(component.html()).toMatchSnapshot();
|
||||||
const securityElement = shallow(
|
component.find('svg').simulate('click');
|
||||||
<SecurityRequirement key={1} security={securityRequirement} />,
|
//Security expanded
|
||||||
).getElement();
|
expect(component.html()).toMatchSnapshot();
|
||||||
expect(securityElement.props.children.type.target).toEqual('span');
|
}
|
||||||
expect(securityElement.props.children.props.children).toEqual('None');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render SecurityDefs', async () => {
|
||||||
|
const parser = new OpenAPIParser(
|
||||||
|
simpleSecurityFixture,
|
||||||
|
undefined,
|
||||||
|
new RedocNormalizedOptions({}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const component = mount(
|
||||||
|
withTheme(<SecurityDefs securitySchemes={new SecuritySchemesModel(parser)} />),
|
||||||
|
);
|
||||||
|
expect(component.html()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -96,7 +96,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -106,6 +105,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -353,7 +353,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -363,6 +362,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -585,7 +585,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -595,6 +594,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -884,7 +884,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -894,6 +893,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1141,7 +1141,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1151,6 +1150,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1373,7 +1373,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1383,6 +1382,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1628,7 +1628,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1638,6 +1637,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -1924,7 +1924,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -1934,6 +1933,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -2181,7 +2181,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -2191,6 +2190,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
@ -2413,7 +2413,6 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"menuToggle": true,
|
"menuToggle": true,
|
||||||
"minCharacterLengthToInitSearch": 3,
|
"minCharacterLengthToInitSearch": 3,
|
||||||
"nativeScrollbars": false,
|
"nativeScrollbars": false,
|
||||||
"noAutoAuth": false,
|
|
||||||
"nonce": undefined,
|
"nonce": undefined,
|
||||||
"onlyRequiredInSamples": false,
|
"onlyRequiredInSamples": false,
|
||||||
"pathInMiddlePanel": false,
|
"pathInMiddlePanel": false,
|
||||||
|
@ -2423,6 +2422,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"scrollYOffset": [Function],
|
"scrollYOffset": [Function],
|
||||||
"showExtensions": false,
|
"showExtensions": false,
|
||||||
"showObjectSchemaExamples": false,
|
"showObjectSchemaExamples": false,
|
||||||
|
"showSecuritySchemeType": false,
|
||||||
"showWebhookVerb": false,
|
"showWebhookVerb": false,
|
||||||
"sideNavStyle": "summary-only",
|
"sideNavStyle": "summary-only",
|
||||||
"simpleOneOfTypeLabel": false,
|
"simpleOneOfTypeLabel": false,
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`SecurityRequirement should render SecurityDefs 1`] = `
|
||||||
|
"<div id=\\"section/Authentication/petstore_auth\\" data-section-id=\\"section/Authentication/petstore_auth\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">petstore_auth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>Get access to data while protecting your account credentials.
|
||||||
|
OAuth2 is also a safer and more secure way to give you access.</p>
|
||||||
|
</div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>OAuth2</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-fXgAZx gZCyoW\\"><strong> Authorization URL: </strong><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"http://petstore.swagger.io/api/oauth/dialog\\">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div class=\\"sc-fXgAZx gZCyoW\\"><b> Scopes: </b></div><div class=\\"sc-jXcxbT blWOKY container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p>
|
||||||
|
</span></li><li><code>read:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>read your pets</p>
|
||||||
|
</span></li></ul></div><div class=\\"sc-eEVmNe gbLbHj\\"></div></div></div></div></div></div><div id=\\"section/Authentication/GitLab_PersonalAccessToken\\" data-section-id=\\"section/Authentication/GitLab_PersonalAccessToken\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_PersonalAccessToken</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p>
|
||||||
|
</div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>API Key</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div></div></div></div><div id=\\"section/Authentication/GitLab_OpenIdConnect\\" data-section-id=\\"section/Authentication/GitLab_OpenIdConnect\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">GitLab_OpenIdConnect</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p>
|
||||||
|
</div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>OpenID Connect</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Connect URL: </b><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://gitlab.com/.well-known/openid-configuration\\">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div></div></div></div><div id=\\"section/Authentication/basicAuth\\" data-section-id=\\"section/Authentication/basicAuth\\" class=\\"sc-eCApnc jlMQbh\\"><div class=\\"sc-iCoGMd gLxhOh\\"><div class=\\"sc-hKFxyN juinod\\"><h2 class=\\"sc-pNWdM eftmgB\\">basicAuth</h2><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-EZqKI aOkZE\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Security Scheme Type: </b><span>HTTP</span></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-fXgAZx gZCyoW\\"></div></div></div></div></div></div>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`SecurityRequirement should render authDefinition 1`] = `"<div class=\\"sc-bQCEYZ eDdCgW\\"><div class=\\"sc-xGAEC femyTb\\"><h5 class=\\"sc-iqAclL sc-jHcXXw eONCmm keQLTh\\">Authorizations:</h5><svg class=\\"sc-dIsUp iPqByX\\" version=\\"1.1\\" viewBox=\\"0 0 24 24\\" x=\\"0\\" xmlns=\\"http://www.w3.org/2000/svg\\" y=\\"0\\" aria-hidden=\\"true\\"><polygon points=\\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \\"></polygon></svg></div><div class=\\"sc-dWBRfb kJFNCL\\"><span class=\\"sc-kYPZxB irJeRy\\">(<span class=\\"sc-hzUIXc gcouO\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-hzUIXc gcouO\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-hzUIXc gcouO\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-kYPZxB irJeRy\\"><span class=\\"sc-hzUIXc gcouO\\">OAuth2: <i>petstore_auth</i></span></span></div></div>,"`;
|
||||||
|
|
||||||
|
exports[`SecurityRequirement should render authDefinition 2`] = `
|
||||||
|
"<div class=\\"sc-bQCEYZ dSwEDq\\"><div class=\\"sc-xGAEC femyTb\\"><h5 class=\\"sc-iqAclL sc-jHcXXw eONCmm keQLTh\\">Authorizations:</h5><svg class=\\"sc-dIsUp fVWtGJ\\" version=\\"1.1\\" viewBox=\\"0 0 24 24\\" x=\\"0\\" xmlns=\\"http://www.w3.org/2000/svg\\" y=\\"0\\" aria-hidden=\\"true\\"><polygon points=\\"17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 \\"></polygon></svg></div><div class=\\"sc-dWBRfb ekRdav\\"><span class=\\"sc-kYPZxB fhGdrc\\">(<span class=\\"sc-hzUIXc gcouO\\">API Key: <i>GitLab_PersonalAccessToken</i></span><span class=\\"sc-hzUIXc gcouO\\">OpenID Connect: <i>GitLab_OpenIdConnect</i></span><span class=\\"sc-hzUIXc gcouO\\">HTTP: <i>basicAuth</i></span>) </span><span class=\\"sc-kYPZxB fhGdrc\\"><span class=\\"sc-hzUIXc gcouO\\">OAuth2: <i>petstore_auth</i> (<code class=\\"sc-eHEENL fwFTyL\\">write:pets</code><code class=\\"sc-eHEENL fwFTyL\\">read:pets</code>) </span></span></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> OAuth2: petstore_auth</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>Get access to data while protecting your account credentials.
|
||||||
|
OAuth2 is also a safer and more secure way to give you access.</p>
|
||||||
|
</div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Flow type: </b><code>implicit </code></div><div class=\\"sc-fXgAZx gZCyoW\\"><strong> Authorization URL: </strong><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"http://petstore.swagger.io/api/oauth/dialog\\">http://petstore.swagger.io/api/oauth/dialog</a></code></div><div><b>Required scopes: </b><code>write:pets</code> <code>read:pets</code> </div><div class=\\"sc-fXgAZx gZCyoW\\"><b> Scopes: </b></div><div class=\\"sc-jXcxbT blWOKY container\\" style=\\"height: 4em;\\"><ul><li><code>write:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>modify pets in your account</p>
|
||||||
|
</span></li><li><code>read:pets</code> - <span class=\\"sc-carFqZ bmTzxo redoc-markdown\\"><p>read your pets</p>
|
||||||
|
</span></li></ul></div><div class=\\"sc-eEVmNe gbLbHj\\"></div></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> API Key: GitLab_PersonalAccessToken</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab Personal Access Token description</p>
|
||||||
|
</div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Header parameter name: </b><code>PRIVATE-TOKEN</code></div></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> OpenID Connect: GitLab_OpenIdConnect</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><p>GitLab OpenIdConnect description</p>
|
||||||
|
</div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>Connect URL: </b><code><a target=\\"_blank\\" rel=\\"noopener noreferrer\\" href=\\"https://gitlab.com/.well-known/openid-configuration\\">https://gitlab.com/.well-known/openid-configuration</a></code></div></div></div><div class=\\"sc-EZqKI aOkZE\\"><h5><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 24 24\\" width=\\"11\\" height=\\"11\\"><path fill=\\"currentColor\\" d=\\"M18 10V6A6 6 0 0 0 6 6v4H3v14h18V10h-3zM8 6c0-2.206 1.794-4 4-4s4 1.794 4 4v4H8V6zm11 16H5V12h14v10z\\"></path></svg> HTTP: basicAuth</h5><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"></div><div class=\\"sc-iJCRrE sc-ciSkZP jCdxGr QGruV\\"><div class=\\"sc-fXgAZx gZCyoW\\"><b>HTTP Authorization Scheme: </b><code>basic</code></div><div class=\\"sc-fXgAZx gZCyoW\\"></div></div></div>,"
|
||||||
|
`;
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0",
|
||||||
|
"info": {
|
||||||
|
"title": "test",
|
||||||
|
"version": "0"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/pet": {
|
||||||
|
"put": {
|
||||||
|
"summary": "Add a new pet to the store",
|
||||||
|
"description": "Add new pet to the store inventory.",
|
||||||
|
"operationId": "updatePet",
|
||||||
|
"responses": {
|
||||||
|
"405": {
|
||||||
|
"description": "Invalid input"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"GitLab_PersonalAccessToken": [],
|
||||||
|
"GitLab_OpenIdConnect": [],
|
||||||
|
"basicAuth": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"petstore_auth": ["write:pets", "read:pets"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"securitySchemes": {
|
||||||
|
"petstore_auth": {
|
||||||
|
"description": "Get access to data while protecting your account credentials.\nOAuth2 is also a safer and more secure way to give you access.\n",
|
||||||
|
"type": "oauth2",
|
||||||
|
"bearerFormat": "",
|
||||||
|
"flows": {
|
||||||
|
"implicit": {
|
||||||
|
"authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog",
|
||||||
|
"scopes": {
|
||||||
|
"write:pets": "modify pets in your account",
|
||||||
|
"read:pets": "read your pets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GitLab_PersonalAccessToken": {
|
||||||
|
"description": "GitLab Personal Access Token description",
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "PRIVATE-TOKEN",
|
||||||
|
"in": "header",
|
||||||
|
"bearerFormat": "",
|
||||||
|
"flows": {}
|
||||||
|
},
|
||||||
|
"GitLab_OpenIdConnect": {
|
||||||
|
"description": "GitLab OpenIdConnect description",
|
||||||
|
"bearerFormat": "",
|
||||||
|
"type": "openIdConnect",
|
||||||
|
"openIdConnectUrl": "https://gitlab.com/.well-known/openid-configuration"
|
||||||
|
},
|
||||||
|
"basicAuth": {
|
||||||
|
"type": "http",
|
||||||
|
"scheme": "basic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,11 +12,7 @@ import { SearchStore } from './SearchStore';
|
||||||
|
|
||||||
import { SchemaDefinition } from '../components/SchemaDefinition/SchemaDefinition';
|
import { SchemaDefinition } from '../components/SchemaDefinition/SchemaDefinition';
|
||||||
import { SecurityDefs } from '../components/SecuritySchemes/SecuritySchemes';
|
import { SecurityDefs } from '../components/SecuritySchemes/SecuritySchemes';
|
||||||
import {
|
import { SCHEMA_DEFINITION_JSX_NAME, SECURITY_DEFINITIONS_JSX_NAME } from '../utils/openapi';
|
||||||
SCHEMA_DEFINITION_JSX_NAME,
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
SECURITY_DEFINITIONS_JSX_NAME,
|
|
||||||
} from '../utils/openapi';
|
|
||||||
|
|
||||||
import { IS_BROWSER } from '../utils';
|
import { IS_BROWSER } from '../utils';
|
||||||
|
|
||||||
|
@ -158,12 +154,6 @@ export class AppStore {
|
||||||
|
|
||||||
const DEFAULT_OPTIONS: RedocRawOptions = {
|
const DEFAULT_OPTIONS: RedocRawOptions = {
|
||||||
allowedMdComponents: {
|
allowedMdComponents: {
|
||||||
[SECURITY_DEFINITIONS_COMPONENT_NAME]: {
|
|
||||||
component: SecurityDefs,
|
|
||||||
propsSelector: (store: AppStore) => ({
|
|
||||||
securitySchemes: store.spec.securitySchemes,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
[SECURITY_DEFINITIONS_JSX_NAME]: {
|
[SECURITY_DEFINITIONS_JSX_NAME]: {
|
||||||
component: SecurityDefs,
|
component: SecurityDefs,
|
||||||
propsSelector: (store: AppStore) => ({
|
propsSelector: (store: AppStore) => ({
|
||||||
|
|
|
@ -7,13 +7,7 @@ import {
|
||||||
OpenAPIServer,
|
OpenAPIServer,
|
||||||
OpenAPIPaths,
|
OpenAPIPaths,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import { isOperationName, JsonPointer, alphabeticallyByProp } from '../utils';
|
||||||
isOperationName,
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
setSecuritySchemePrefix,
|
|
||||||
JsonPointer,
|
|
||||||
alphabeticallyByProp,
|
|
||||||
} from '../utils';
|
|
||||||
import { MarkdownRenderer } from './MarkdownRenderer';
|
import { MarkdownRenderer } from './MarkdownRenderer';
|
||||||
import { GroupModel, OperationModel } from './models';
|
import { GroupModel, OperationModel } from './models';
|
||||||
import { OpenAPIParser } from './OpenAPIParser';
|
import { OpenAPIParser } from './OpenAPIParser';
|
||||||
|
@ -93,14 +87,7 @@ export class MenuBuilder {
|
||||||
if (heading.items) {
|
if (heading.items) {
|
||||||
group.items = mapHeadingsDeep(group, heading.items, depth + 1);
|
group.items = mapHeadingsDeep(group, heading.items, depth + 1);
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
MarkdownRenderer.containsComponent(
|
|
||||||
group.description || '',
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
setSecuritySchemePrefix(group.id + '/');
|
|
||||||
}
|
|
||||||
return group;
|
return group;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,7 @@ export class MenuStore {
|
||||||
let item: IMenuItem | undefined;
|
let item: IMenuItem | undefined;
|
||||||
|
|
||||||
item = this.flatItems.find(i => i.id === id);
|
item = this.flatItems.find(i => i.id === id);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
this.activateAndScroll(item, false);
|
this.activateAndScroll(item, false);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
|
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
|
||||||
|
|
||||||
import { appendToMdHeading, isArray, isBoolean, IS_BROWSER } from '../utils/';
|
import { isArray, isBoolean, IS_BROWSER } from '../utils/';
|
||||||
import { JsonPointer } from '../utils/JsonPointer';
|
import { JsonPointer } from '../utils/JsonPointer';
|
||||||
import {
|
import { getDefinitionName, isNamedDefinition } from '../utils/openapi';
|
||||||
getDefinitionName,
|
|
||||||
isNamedDefinition,
|
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
|
||||||
SECURITY_DEFINITIONS_JSX_NAME,
|
|
||||||
} from '../utils/openapi';
|
|
||||||
import { buildComponentComment, MarkdownRenderer } from './MarkdownRenderer';
|
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
|
|
||||||
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
||||||
|
@ -53,7 +47,6 @@ export class OpenAPIParser {
|
||||||
private options: RedocNormalizedOptions = new RedocNormalizedOptions({}),
|
private options: RedocNormalizedOptions = new RedocNormalizedOptions({}),
|
||||||
) {
|
) {
|
||||||
this.validate(spec);
|
this.validate(spec);
|
||||||
this.preprocess(spec);
|
|
||||||
|
|
||||||
this.spec = spec;
|
this.spec = spec;
|
||||||
this.allowMergeRefs = spec.openapi.startsWith('3.1');
|
this.allowMergeRefs = spec.openapi.startsWith('3.1');
|
||||||
|
@ -70,25 +63,6 @@ export class OpenAPIParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preprocess(spec: OpenAPISpec) {
|
|
||||||
if (
|
|
||||||
!this.options.noAutoAuth &&
|
|
||||||
spec.info &&
|
|
||||||
spec.components &&
|
|
||||||
spec.components.securitySchemes
|
|
||||||
) {
|
|
||||||
// Automatically inject Authentication section with SecurityDefinitions component
|
|
||||||
const description = spec.info.description || '';
|
|
||||||
if (
|
|
||||||
!MarkdownRenderer.containsComponent(description, SECURITY_DEFINITIONS_COMPONENT_NAME) &&
|
|
||||||
!MarkdownRenderer.containsComponent(description, SECURITY_DEFINITIONS_JSX_NAME)
|
|
||||||
) {
|
|
||||||
const comment = buildComponentComment(SECURITY_DEFINITIONS_COMPONENT_NAME);
|
|
||||||
spec.info.description = appendToMdHeading(description, 'Authentication', comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get spec part by JsonPointer ($ref)
|
* get spec part by JsonPointer ($ref)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -21,7 +21,6 @@ export interface RedocRawOptions {
|
||||||
sortEnumValuesAlphabetically?: boolean | string;
|
sortEnumValuesAlphabetically?: boolean | string;
|
||||||
sortOperationsAlphabetically?: boolean | string;
|
sortOperationsAlphabetically?: boolean | string;
|
||||||
sortTagsAlphabetically?: boolean | string;
|
sortTagsAlphabetically?: boolean | string;
|
||||||
noAutoAuth?: boolean | string;
|
|
||||||
nativeScrollbars?: boolean | string;
|
nativeScrollbars?: boolean | string;
|
||||||
pathInMiddlePanel?: boolean | string;
|
pathInMiddlePanel?: boolean | string;
|
||||||
untrustedSpec?: boolean | string;
|
untrustedSpec?: boolean | string;
|
||||||
|
@ -42,6 +41,7 @@ export interface RedocRawOptions {
|
||||||
expandSingleSchemaField?: boolean | string;
|
expandSingleSchemaField?: boolean | string;
|
||||||
schemaExpansionLevel?: number | string | 'all';
|
schemaExpansionLevel?: number | string | 'all';
|
||||||
showObjectSchemaExamples?: boolean | string;
|
showObjectSchemaExamples?: boolean | string;
|
||||||
|
showSecuritySchemeType?: boolean;
|
||||||
|
|
||||||
unstable_ignoreMimeParameters?: boolean;
|
unstable_ignoreMimeParameters?: boolean;
|
||||||
|
|
||||||
|
@ -224,7 +224,6 @@ export class RedocNormalizedOptions {
|
||||||
sortEnumValuesAlphabetically: boolean;
|
sortEnumValuesAlphabetically: boolean;
|
||||||
sortOperationsAlphabetically: boolean;
|
sortOperationsAlphabetically: boolean;
|
||||||
sortTagsAlphabetically: boolean;
|
sortTagsAlphabetically: boolean;
|
||||||
noAutoAuth: boolean;
|
|
||||||
nativeScrollbars: boolean;
|
nativeScrollbars: boolean;
|
||||||
pathInMiddlePanel: boolean;
|
pathInMiddlePanel: boolean;
|
||||||
untrustedSpec: boolean;
|
untrustedSpec: boolean;
|
||||||
|
@ -245,6 +244,7 @@ export class RedocNormalizedOptions {
|
||||||
expandSingleSchemaField: boolean;
|
expandSingleSchemaField: boolean;
|
||||||
schemaExpansionLevel: number;
|
schemaExpansionLevel: number;
|
||||||
showObjectSchemaExamples: boolean;
|
showObjectSchemaExamples: boolean;
|
||||||
|
showSecuritySchemeType?: boolean;
|
||||||
|
|
||||||
/* tslint:disable-next-line */
|
/* tslint:disable-next-line */
|
||||||
unstable_ignoreMimeParameters: boolean;
|
unstable_ignoreMimeParameters: boolean;
|
||||||
|
@ -294,7 +294,6 @@ export class RedocNormalizedOptions {
|
||||||
this.sortEnumValuesAlphabetically = argValueToBoolean(raw.sortEnumValuesAlphabetically);
|
this.sortEnumValuesAlphabetically = argValueToBoolean(raw.sortEnumValuesAlphabetically);
|
||||||
this.sortOperationsAlphabetically = argValueToBoolean(raw.sortOperationsAlphabetically);
|
this.sortOperationsAlphabetically = argValueToBoolean(raw.sortOperationsAlphabetically);
|
||||||
this.sortTagsAlphabetically = argValueToBoolean(raw.sortTagsAlphabetically);
|
this.sortTagsAlphabetically = argValueToBoolean(raw.sortTagsAlphabetically);
|
||||||
this.noAutoAuth = argValueToBoolean(raw.noAutoAuth);
|
|
||||||
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
|
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
|
||||||
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
|
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
|
||||||
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
|
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
|
||||||
|
@ -317,6 +316,7 @@ export class RedocNormalizedOptions {
|
||||||
this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField);
|
this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField);
|
||||||
this.schemaExpansionLevel = argValueToExpandLevel(raw.schemaExpansionLevel);
|
this.schemaExpansionLevel = argValueToExpandLevel(raw.schemaExpansionLevel);
|
||||||
this.showObjectSchemaExamples = argValueToBoolean(raw.showObjectSchemaExamples);
|
this.showObjectSchemaExamples = argValueToBoolean(raw.showObjectSchemaExamples);
|
||||||
|
this.showSecuritySchemeType = argValueToBoolean(raw.showSecuritySchemeType);
|
||||||
|
|
||||||
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
|
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { OpenAPISecurityRequirement, OpenAPISecurityScheme } from '../../types';
|
import { OpenAPISecurityRequirement, OpenAPISecurityScheme } from '../../types';
|
||||||
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export interface SecurityScheme extends OpenAPISecurityScheme {
|
export interface SecurityScheme extends OpenAPISecurityScheme {
|
||||||
|
@ -29,7 +28,7 @@ export class SecurityRequirementModel {
|
||||||
return {
|
return {
|
||||||
...scheme,
|
...scheme,
|
||||||
id,
|
id,
|
||||||
sectionId: SECURITY_SCHEMES_SECTION_PREFIX + id,
|
sectionId: id,
|
||||||
displayName,
|
displayName,
|
||||||
scopes,
|
scopes,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { OpenAPISecurityScheme, Referenced } from '../../types';
|
import { OpenAPISecurityScheme, Referenced } from '../../types';
|
||||||
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi';
|
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export class SecuritySchemeModel {
|
export class SecuritySchemeModel {
|
||||||
|
|
|
@ -615,7 +615,6 @@ export function normalizeServers(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SECURITY_DEFINITIONS_COMPONENT_NAME = 'security-definitions';
|
|
||||||
export const SECURITY_DEFINITIONS_JSX_NAME = 'SecurityDefinitions';
|
export const SECURITY_DEFINITIONS_JSX_NAME = 'SecurityDefinitions';
|
||||||
export const SCHEMA_DEFINITION_JSX_NAME = 'SchemaDefinition';
|
export const SCHEMA_DEFINITION_JSX_NAME = 'SchemaDefinition';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user