Skip to content

Commit

Permalink
[typescript-angular2] Allow lazy oauth token refresh (#6486)
Browse files Browse the repository at this point in the history
- Startover with a new branch after pr #6493 was created on the wrong branch
- Handover authentication scheme name as well as the scopes to the accessToken function in the Configuration class
- accessToken returns an Observable to allow a lazy refresh of the accessToken
  • Loading branch information
alexrashed committed Sep 27, 2017
1 parent 28a3206 commit edb367a
Show file tree
Hide file tree
Showing 52 changed files with 2,217 additions and 2,959 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ export class {{classname}} {
}
if (configuration) {
this.configuration = configuration;
this.basePath = basePath || configuration.basePath || this.basePath;
this.basePath = basePath || configuration.basePath || this.basePath;
}
}

/**
*
*
* Extends object by coping non-existing properties.
* @param objA object to be extended
* @param objB source object
Expand Down Expand Up @@ -125,7 +125,7 @@ export class {{classname}} {
.replace('${' + '{{baseName}}' + '}', encodeURIComponent(String({{paramName}}))){{/pathParams}};

let queryParameters = new URLSearchParams('', new CustomQueryEncoderHelper());
let headers = new Headers(this.defaultHeaders.toJSON()); // https://github.com/angular/angular/issues/6845
let headersObservable = Observable.of(new Headers(this.defaultHeaders.toJSON())); // https://github.com/angular/angular/issues/6845

{{#allParams}}
{{#required}}
Expand Down Expand Up @@ -163,12 +163,12 @@ export class {{classname}} {
{{#headerParams}}
{{#isListContainer}}
if ({{paramName}}) {
headers.set('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']));
headersObservable = headersObservable.do((headers: Headers) => headers.set('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])));
}
{{/isListContainer}}
{{^isListContainer}}
if ({{paramName}} !== undefined && {{paramName}} !== null) {
headers.set('{{baseName}}', String({{paramName}}));
headersObservable = headersObservable.do((headers: Headers) => headers.set('{{baseName}}', String({{paramName}})));
}
{{/isListContainer}}

Expand All @@ -182,7 +182,8 @@ export class {{classname}} {
];

if (consumes != null && consumes.length > 0) {
headers.set('Content-Type', consumes.filter(item => this.isJsonMime(item)).join(";"));
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('Content-Type', consumes.filter(item => this.isJsonMime(item)).join(";")));
}

let canConsumeForm = this.canConsumeForm(consumes);
Expand All @@ -205,15 +206,17 @@ export class {{classname}} {
];

if (produces != null && produces.length > 0) {
headers.set('Accept', produces.filter(item => this.isJsonMime(item)).join(';'));
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('Accept', produces.filter(item => this.isJsonMime(item)).join(';')));
}

{{#authMethods}}
// authentication ({{name}}) required
{{#isApiKey}}
{{#isKeyInHeader}}
if (this.configuration.apiKeys["{{keyParamName}}"]) {
headers.set('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]);
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]));
}

{{/isKeyInHeader}}
Expand All @@ -227,24 +230,29 @@ export class {{classname}} {
{{#isBasic}}
// http basic authentication required
if (this.configuration.username || this.configuration.password) {
headers.set('Authorization', 'Basic ' + btoa(this.configuration.username + ':' + this.configuration.password));
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('Authorization', 'Basic ' + btoa(this.configuration.username + ':' + this.configuration.password)));
}

{{/isBasic}}
{{#isOAuth}}
// oauth required
if (this.configuration.accessToken) {
let accessToken = typeof this.configuration.accessToken === 'function'
? this.configuration.accessToken()
: this.configuration.accessToken;
headers.set('Authorization', 'Bearer ' + accessToken);
let accessTokenObservable = typeof this.configuration.accessToken === 'function'
? this.configuration.accessToken("{{name}}", [{{#scopes}}"{{{scope}}}"{{^-last}}, {{/-last}}{{/scopes}}])
: Observable.of(this.configuration.accessToken);
headersObservable = headersObservable.zip(accessTokenObservable, (headers: Headers, accessToken: string) => {
headers.set('Authorization', 'Bearer ' + accessToken);
return headers;
});
}

{{/isOAuth}}
{{/authMethods}}

{{#bodyParam}}
headers.set('Content-Type', 'application/json');
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('Content-Type', 'application/json'));

{{/bodyParam}}
{{#formParams}}
Expand All @@ -267,27 +275,31 @@ export class {{classname}} {
{{/isListContainer}}

{{/formParams}}
let requestOptions: RequestOptionsArgs = new RequestOptions({
method: {{httpMethod}},
headers: headers,
let requestOptionsObservable = headersObservable.map((headers: Headers) => {
let requestOptions: RequestOptionsArgs = new RequestOptions({
method: {{httpMethod}},
headers: headers,
{{#bodyParam}}
body: {{paramName}} == null ? '' : JSON.stringify({{paramName}}), // https://github.com/angular/angular/issues/10612
body: {{paramName}} == null ? '' : JSON.stringify({{paramName}}), // https://github.com/angular/angular/issues/10612
{{/bodyParam}}
{{#hasFormParams}}
body: formParams.toString(),
body: formParams.toString(),
{{/hasFormParams}}
{{#isResponseFile}}
responseType: ResponseContentType.Blob,
responseType: ResponseContentType.Blob,
{{/isResponseFile}}
search: queryParameters,
withCredentials:this.configuration.withCredentials
search: queryParameters,
withCredentials:this.configuration.withCredentials
});
// https://github.com/swagger-api/swagger-codegen/issues/4037
if (extraHttpRequestParams) {
requestOptions = (<any>Object).assign(requestOptions, extraHttpRequestParams);
}

return requestOptions;
});
// https://github.com/swagger-api/swagger-codegen/issues/4037
if (extraHttpRequestParams) {
requestOptions = (<any>Object).assign(requestOptions, extraHttpRequestParams);
}

return this.http.request(path, requestOptions);
return requestOptionsObservable.mergeMap((requestOptions: RequestOptionsArgs) => this.http.request(path, requestOptions));
}

{{/operation}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Observable } from 'rxjs/Observable';

export interface ConfigurationParameters {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | (() => string);
accessToken?: string | ((name: string, scopes?: string[]) => Observable<string>);
basePath?: string;
withCredentials?: boolean;
}
Expand All @@ -11,7 +13,7 @@ export class Configuration {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | (() => string);
accessToken?: string | ((name: string, scopes?: string[]) => Observable<string>);
basePath?: string;
withCredentials?: boolean;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

// Statics
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';

// Operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/zip';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/mergeMap';
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
wwwroot/*.js
node_modules
typings
dist
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.3
2.3.0-SNAPSHOT
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import * as api from './api/api';
import * as angular from 'angular';
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
import { Configuration } from './configuration';

const apiModule = angular.module('api', [])
.service('FakeApi', api.FakeApi)
import { FakeService } from './api/fake.service';

export default apiModule;
@NgModule({
imports: [ CommonModule, HttpModule ],
declarations: [],
exports: [],
providers: [ FakeService ]
})
export class ApiModule {
public static forConfig(configurationFactory: () => Configuration): ModuleWithProviders {
return {
ngModule: ApiModule,
providers: [ {provide: Configuration, useFactory: configurationFactory}]
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './FakeApi';
import { FakeApi } from './FakeApi';
export const APIS = [FakeApi];
export * from './fake.service';
import { FakeService } from './fake.service';
export const APIS = [FakeService];
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* Swagger Petstore *_/ ' \" =end -- \\r\\n \\n \\r
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end --
*
* OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r
* Contact: apiteam@swagger.io *_/ ' \" =end -- \\r\\n \\n \\r
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/

/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { Http, Headers, URLSearchParams } from '@angular/http';
import { RequestMethod, RequestOptions, RequestOptionsArgs } from '@angular/http';
import { Response, ResponseContentType } from '@angular/http';

import { Observable } from 'rxjs/Observable';
import '../rxjs-operators';


import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';
import { CustomQueryEncoderHelper } from '../encoder';


@Injectable()
export class FakeService {

protected basePath = 'https://petstore.swagger.io *_/ ' \" =end -- \\r\\n \\n \\r/v2 *_/ ' \" =end -- \\r\\n \\n \\r';
public defaultHeaders: Headers = new Headers();
public configuration: Configuration = new Configuration();
constructor(protected http: Http, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
if (basePath) {
this.basePath = basePath;
}
if (configuration) {
this.configuration = configuration;
this.basePath = basePath || configuration.basePath || this.basePath;
}
}
/**
*
* Extends object by coping non-existing properties.
* @param objA object to be extended
* @param objB source object
*/
private extendObj<T1,T2>(objA: T1, objB: T2) {
for(let key in objB){
if(objB.hasOwnProperty(key)){
(objA as any)[key] = (objB as any)[key];
}
}
return <T1&T2>objA;
}
/**
* @param consumes string[] mime-types
* @return true: consumes contains 'multipart/form-data', false: otherwise
*/
private canConsumeForm(consumes: string[]): boolean {
const form = 'multipart/form-data';
for (let consume of consumes) {
if (form === consume) {
return true;
}
}
return false;
}
public isJsonMime(mime: string): boolean {
const jsonMime: RegExp = new RegExp('(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$');
return mime != null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
}
/**
*
* @summary To test code injection *_/ ' \" =end -- \\r\\n \\n \\r
* @param test code inject * &#39; &quot; &#x3D;end rn n r To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
*/
public testCodeInjectEndRnNR(test code inject * &#39; &quot; &#x3D;end rn n r?: string, extraHttpRequestParams?: any): Observable<{}> {
return this.testCodeInjectEndRnNRWithHttpInfo(test code inject * &#39; &quot; &#x3D;end rn n r, extraHttpRequestParams)
.map((response: Response) => {
if (response.status === 204) {
return undefined;
} else {
return response.json() || {};
}
});
}
/**
* To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
*
* @param test code inject * &#39; &quot; &#x3D;end rn n r To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
*/
public testCodeInjectEndRnNRWithHttpInfo(test code inject * &#39; &quot; &#x3D;end rn n r?: string, extraHttpRequestParams?: any): Observable<Response> {
const path = this.basePath + '/fake';
let queryParameters = new URLSearchParams('', new CustomQueryEncoderHelper());
let headersObservable = Observable.of(new Headers(this.defaultHeaders.toJSON())); // https://github.com/angular/angular/issues/6845
// to determine the Content-Type header
let consumes: string[] = [
'application/json',
'*_/ =end -- '
];
if (consumes != null && consumes.length > 0) {
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('Content-Type', consumes.filter(item => this.isJsonMime(item)).join(";")));
}

let canConsumeForm = this.canConsumeForm(consumes);
let useForm = false;
let formParams = new (useForm ? FormData : URLSearchParams as any)() as {
set(param: string, value: any): void;
};

// to determine the Accept header
let produces: string[] = [
'application/json',
'*_/ =end -- '
];

if (produces != null && produces.length > 0) {
headersObservable = headersObservable.do((headers: Headers) =>
headers.set('Accept', produces.filter(item => this.isJsonMime(item)).join(';')));
}


if (test code inject * &#39; &quot; &#x3D;end rn n r !== undefined) {
formParams.set('test code inject */ &#39; &quot; &#x3D;end -- \r\n \n \r', <any>test code inject * &#39; &quot; &#x3D;end rn n r);
}

let requestOptionsObservable = headersObservable.map((headers: Headers) => {
let requestOptions: RequestOptionsArgs = new RequestOptions({
method: RequestMethod.Put,
headers: headers,
body: formParams.toString(),
search: queryParameters,
withCredentials:this.configuration.withCredentials
});
// https://github.com/swagger-api/swagger-codegen/issues/4037
if (extraHttpRequestParams) {
requestOptions = (<any>Object).assign(requestOptions, extraHttpRequestParams);
}

return requestOptions;
});

return requestOptionsObservable.mergeMap((requestOptions: RequestOptionsArgs) => this.http.request(path, requestOptions));
}

}
Loading

0 comments on commit edb367a

Please sign in to comment.