mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-06 21:30:21 +03:00
Merge d5a5615b3a
into d083c1631d
This commit is contained in:
commit
9925f5a130
13
lib/components/AuthScopes/auth-scopes.html
Normal file
13
lib/components/AuthScopes/auth-scopes.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<ng-template [ngIf]="scopes">
|
||||
<div class="oauth-scopes hint__content">
|
||||
<span class="oauth-scopes-header">OAuth2 Scopes</span>
|
||||
<div class="oauth-scope">
|
||||
<span *ngFor="let scope of scopes.scopes" [attr.data-hint]="scope.name" class="hint--rounded hint--bounce hint--bottom">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="20px" height="20px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<path d="M384,224v-96C384,57.438,326.594,0,256,0c-70.578,0-128,57.438-128,128v96c-35.344,0-64,28.656-64,64v160c0,35.344,28.656,64,64,64h256c35.344,0,64-28.656,64-64V288C448,252.656,419.344,224,384,224z M272,379.094V432c0,8.844-7.156,16-16,16s-16-7.156-16-16v-52.906c-9.391-5.563-16-15.375-16-27.094c0-17.688,14.328-32,32-32s32,14.313,32,32C288,363.719,281.391,373.531,272,379.094z M320,224H192v-96c0-35.313,28.703-64,64-64c35.281,0,64,28.688,64,64V224z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
31
lib/components/AuthScopes/auth-scopes.ts
Normal file
31
lib/components/AuthScopes/auth-scopes.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
import { Component, Input, ChangeDetectionStrategy, OnInit } from '@angular/core';
|
||||
import { BaseComponent, SpecManager } from '../base';
|
||||
import { SchemaHelper } from '../../services/schema-helper.service';
|
||||
import { ComponentParser } from '../../services/component-parser.service';
|
||||
|
||||
@Component({
|
||||
selector: 'auth-scopes',
|
||||
templateUrl: './auth-scopes.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AuthScopes extends BaseComponent implements OnInit {
|
||||
@Input() pointer:string;
|
||||
|
||||
public scopes: any;
|
||||
|
||||
constructor(specMgr:SpecManager) {
|
||||
super(specMgr);
|
||||
}
|
||||
|
||||
init() {
|
||||
let theScopes = this.specMgr.getOperationScopes(this.pointer);
|
||||
if (theScopes.length) {
|
||||
this.scopes = {scopes: theScopes}
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.preinit();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
<div class="operation-content">
|
||||
<h2 class="operation-header sharable-header" [class.deprecated]="operation.deprecated">
|
||||
<a class="share-link" href="#{{operation.anchor}}"></a>{{operation.summary}}
|
||||
<auth-scopes pointer="{{pointer}}/security"> </auth-scopes>
|
||||
</h2>
|
||||
<endpoint-link *ngIf="pathInMiddlePanel"
|
||||
[verb]="operation.verb" [path]="operation.path"> </endpoint-link>
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ParamsList } from './ParamsList/params-list';
|
|||
import { RequestSamples } from './RequestSamples/request-samples';
|
||||
import { ResponsesList } from './ResponsesList/responses-list';
|
||||
import { ResponsesSamples } from './ResponsesSamples/responses-samples';
|
||||
import { AuthScopes} from './AuthScopes/auth-scopes';
|
||||
import { SchemaSample } from './SchemaSample/schema-sample';
|
||||
import { SideMenu, SideMenuItems } from './SideMenu/side-menu';
|
||||
import { OperationsList } from './OperationsList/operations-list';
|
||||
|
@ -23,10 +24,10 @@ import { Redoc } from './Redoc/redoc';
|
|||
|
||||
export const REDOC_DIRECTIVES = [
|
||||
ApiInfo, ApiLogo, JsonSchema, JsonSchemaLazy, ParamsList, RequestSamples, ResponsesList,
|
||||
ResponsesSamples, SchemaSample, SideMenu, OperationsList, Operation, Warnings, Redoc, SecurityDefinitions,
|
||||
ResponsesSamples, AuthScopes, SchemaSample, SideMenu, OperationsList, Operation, Warnings, Redoc, SecurityDefinitions,
|
||||
LoadingBar, SideMenuItems, RedocSearch, ExternalDocs, EndpointLink
|
||||
];
|
||||
|
||||
export { ApiInfo, ApiLogo, JsonSchema, JsonSchemaLazy, ParamsList, RequestSamples, ResponsesList,
|
||||
ResponsesSamples, SchemaSample, SideMenu, OperationsList, Operation, Warnings, Redoc, SecurityDefinitions,
|
||||
ResponsesSamples, AuthScopes, SchemaSample, SideMenu, OperationsList, Operation, Warnings, Redoc, SecurityDefinitions,
|
||||
LoadingBar, SideMenuItems, ExternalDocs, EndpointLink };
|
||||
|
|
|
@ -140,6 +140,41 @@ export class SpecManager {
|
|||
return obj;
|
||||
}
|
||||
|
||||
getOperationScopes(operationPtr:string) {
|
||||
const getSecurityDefinition = (name: string, scope: string) => {
|
||||
let secDefs = this._schema.securityDefinitions;
|
||||
if (secDefs[name] && secDefs[name].type === 'oauth2') {
|
||||
let availScopes = secDefs[name].scopes;
|
||||
if (availScopes && availScopes[scope]) {
|
||||
return availScopes[scope];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
let securityParams = this.byPointer(operationPtr) || [];
|
||||
let scopes = [];
|
||||
|
||||
// only support one security item per operation for now
|
||||
let base = securityParams[0];
|
||||
|
||||
if (base && base[Object.keys(base)[0]]) {
|
||||
let scopeObj = base[Object.keys(base)[0]];
|
||||
let authName = Object.keys(base)[0];
|
||||
Object.keys(scopeObj).forEach(key => {
|
||||
let val = scopeObj[key];
|
||||
let desc = getSecurityDefinition(authName, val);
|
||||
|
||||
// don't add if the security obj doesn't exist in the security definitions
|
||||
if (desc) {
|
||||
scopes.push({name: val, description: desc});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return scopes;
|
||||
}
|
||||
|
||||
getOperationParams(operationPtr:string):SwaggerParameter[] {
|
||||
/* inject JsonPointer into array elements */
|
||||
function injectPointers(array:SwaggerParameter[], root) {
|
||||
|
|
108
tests/schemas/schema-mgr-operation-security.json
Normal file
108
tests/schemas/schema-mgr-operation-security.json
Normal file
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Test schema"
|
||||
},
|
||||
"host": "petstore.swagger.io",
|
||||
"basePath": "/v2/",
|
||||
"parameters": {
|
||||
"extparam": {
|
||||
"name": "extParam",
|
||||
"in": "query",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"petstore_auth": {
|
||||
"type": "oauth2",
|
||||
"authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog",
|
||||
"flow": "implicit",
|
||||
"scopes": {
|
||||
"write:pets": "modify pets in your account",
|
||||
"read:pets": "read your pets"
|
||||
}
|
||||
},
|
||||
"github_auth": {
|
||||
"type": "oauth2",
|
||||
"authorizationUrl": "https://api.github.com/authorize",
|
||||
"flow": "implicit",
|
||||
"scopes": {
|
||||
"write:account": "modify your account",
|
||||
"read:account": "read your account"
|
||||
}
|
||||
},
|
||||
"api_key": {
|
||||
"type": "apiKey",
|
||||
"name": "api_key",
|
||||
"in": "header"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"test1": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "pathParam",
|
||||
"in": "path",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"summary": "test get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "operationParam",
|
||||
"in": "path",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write:pets",
|
||||
"read:pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"test2": {
|
||||
"parameters": [
|
||||
{ "$ref": "#/parameters/extparam" }
|
||||
],
|
||||
"get": {
|
||||
"summary": "test get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "operationParam",
|
||||
"in": "path",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"test3": {
|
||||
"get": {
|
||||
"summary": "test get",
|
||||
"parameters": [
|
||||
{ "$ref": "#/parameters/extparam" }
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"github_auth": [
|
||||
"write:account"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"test4": {
|
||||
"parameters": {
|
||||
"$ref": "#/parameters/extparam"
|
||||
},
|
||||
"get": {
|
||||
"summary": "test get"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,6 +105,33 @@ describe('Utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getOperationScopes method', () => {
|
||||
beforeEach(function (done) {
|
||||
specMgr.load('/tests/schemas/schema-mgr-operation-security.json').then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should handle operation oauth2 scopes', () => {
|
||||
let scopes = specMgr.getOperationScopes('/paths/test1/get/security');
|
||||
scopes.length.should.be.equal(2);
|
||||
scopes[0].name.should.be.equal('write:pets');
|
||||
scopes[0].description.should.be.equal('modify pets in your account');
|
||||
scopes[1].name.should.be.equal('read:pets');
|
||||
scopes[1].description.should.be.equal('read your pets');
|
||||
});
|
||||
|
||||
it('should handle operation scopes when multiple definitions are used', () => {
|
||||
let scopes = specMgr.getOperationScopes('/paths/test3/get/security');
|
||||
scopes.length.should.be.equal(1);
|
||||
scopes[0].name.should.be.equal('write:account');
|
||||
scopes[0].description.should.be.equal('modify your account');\
|
||||
});
|
||||
|
||||
it('should handle the case when no security is present', () => {
|
||||
let scopes = specMgr.getOperationScopes('/paths/test2/get/security');
|
||||
scopes.length.should.be.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOperationParams method', () => {
|
||||
beforeEach((done:any) => {
|
||||
specMgr.load('/tests/schemas/schema-mgr-operationParams.json').then(done, done.fail);
|
||||
|
|
Loading…
Reference in New Issue
Block a user