This commit is contained in:
George Wilson 2018-01-09 18:06:26 +00:00 committed by GitHub
commit 9925f5a130
7 changed files with 218 additions and 2 deletions

View 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>

View 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();
}
}

View File

@ -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>

View File

@ -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 };

View File

@ -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) {

View 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"
}
}
}
}

View File

@ -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);