diff --git a/api/swagger.yaml b/api/swagger.yaml index fda5fd3c0..d53124f67 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -13,10 +13,11 @@ produces: consumes: - application/json securityDefinitions: - basicAuth: + basic: type: basic security: - - basicAuth: [] + - basic: [] + - {} paths: /version: get: @@ -529,4 +530,4 @@ definitions: description: A flag to indicate if the chart is signed prov_file: type: string - description: The URL of the provance file \ No newline at end of file + description: The URL of the provance file diff --git a/api/v2.0/legacy_swagger.yaml b/api/v2.0/legacy_swagger.yaml index 753953f3f..e7c49248e 100644 --- a/api/v2.0/legacy_swagger.yaml +++ b/api/v2.0/legacy_swagger.yaml @@ -14,10 +14,11 @@ produces: consumes: - application/json securityDefinitions: - basicAuth: + basic: type: basic security: - - basicAuth: [] + - basic: [] + - {} paths: /email/ping: post: diff --git a/src/portal/src/app/dev-center/dev-center-base.ts b/src/portal/src/app/dev-center/dev-center-base.ts index 2dbfc2577..7cf3cd848 100644 --- a/src/portal/src/app/dev-center/dev-center-base.ts +++ b/src/portal/src/app/dev-center/dev-center-base.ts @@ -1,11 +1,11 @@ -import { AfterViewInit, OnInit, Directive } from '@angular/core'; +import { AfterViewInit, Component, Directive, OnInit } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { CookieService } from "ngx-cookie"; @Directive() -export abstract class DevCenterBase implements OnInit, AfterViewInit { - constructor( +export abstract class DevCenterBaseDirective implements OnInit, AfterViewInit { + protected constructor( public translate: TranslateService, public cookieService: CookieService, public titleService: Title) { @@ -20,20 +20,6 @@ export abstract class DevCenterBase implements OnInit, AfterViewInit { this.titleService.setTitle(res); }); } - public getCsrfInterceptor() { - return { - requestInterceptor: { - apply: (requestObj) => { - const csrfCookie = this.cookieService.get('__csrf'); - const headers = requestObj.headers || {}; - if (csrfCookie) { - headers["X-Harbor-CSRF-Token"] = csrfCookie; - } - return requestObj; - } - } - }; - } abstract getSwaggerUI(); abstract ngAfterViewInit(); } diff --git a/src/portal/src/app/dev-center/dev-center.component.ts b/src/portal/src/app/dev-center/dev-center.component.ts index 638aa8392..ad03c0783 100644 --- a/src/portal/src/app/dev-center/dev-center.component.ts +++ b/src/portal/src/app/dev-center/dev-center.component.ts @@ -7,7 +7,8 @@ import { TranslateService } from '@ngx-translate/core'; import { CookieService } from "ngx-cookie"; import * as SwaggerUI from 'swagger-ui'; import { mergeDeep } from "../shared/units/utils"; -import { DevCenterBase } from "./dev-center-base"; +import { DevCenterBaseDirective } from "./dev-center-base"; +import { SAFE_METHODS } from "../services/intercept-http.service"; // @ts-ignore window.Buffer = window.Buffer || require('buffer').Buffer; // this is for swagger UI @@ -16,13 +17,16 @@ enum SwaggerJsonUrls { SWAGGER2 = '/swagger2.json' } +const helpInfo: string = " If you want to enable basic authorization," + + " please logout Harbor first or manually delete the cookies under the current domain."; + @Component({ selector: 'dev-center', templateUrl: 'dev-center.component.html', viewProviders: [Title], styleUrls: ['dev-center.component.scss'] }) -export class DevCenterComponent extends DevCenterBase implements AfterViewInit, OnInit { +export class DevCenterComponent extends DevCenterBaseDirective implements AfterViewInit, OnInit { private ui: any; constructor( private el: ElementRef, @@ -37,15 +41,15 @@ export class DevCenterComponent extends DevCenterBase implements AfterViewInit, this.getSwaggerUI(); } getSwaggerUI() { - const _this = this; forkJoin([this.http.get(SwaggerJsonUrls.SWAGGER1), this.http.get(SwaggerJsonUrls.SWAGGER2)]) .pipe(catchError(error => observableThrowError(error))) .subscribe(jsonArr => { - const json: object = {}; + const json: any = {}; mergeDeep(json, jsonArr[0], jsonArr[1]); json['host'] = window.location.host; const protocal = window.location.protocol; json['schemes'] = [protocal.replace(":", "")]; + json.info.description = json.info.description + helpInfo; this.ui = SwaggerUI({ spec: json, domNode: this.el.nativeElement.querySelector('.swagger-container'), @@ -53,13 +57,26 @@ export class DevCenterComponent extends DevCenterBase implements AfterViewInit, presets: [ SwaggerUI.presets.apis ], - requestInterceptor: this.getCsrfInterceptor().requestInterceptor, - authorizations: { - csrf: function () { - this.headers['X-Harbor-CSRF-Token'] = _this.cookieService.get('__csrf'); - return true; + requestInterceptor: (request) => { + // Get the csrf token from localstorage + const token = localStorage.getItem("__csrf"); + const headers = request.headers || {}; + if (token ) { + if (request.method && SAFE_METHODS.indexOf(request.method.toUpperCase()) === -1) { + headers["X-Harbor-CSRF-Token"] = token; + } } - } + return request; + }, + responseInterceptor: (response) => { + const headers = response.headers || {}; + const responseToken: string = headers["X-Harbor-CSRF-Token"]; + if (responseToken) { + // Set the csrf token to localstorage + localStorage.setItem("__csrf", responseToken); + } + return response; + }, }); }); } diff --git a/src/portal/src/app/services/intercept-http.service.ts b/src/portal/src/app/services/intercept-http.service.ts index 9b73a48a3..b55f8890d 100644 --- a/src/portal/src/app/services/intercept-http.service.ts +++ b/src/portal/src/app/services/intercept-http.service.ts @@ -3,7 +3,7 @@ import { HttpInterceptor, HttpRequest, HttpHandler, HttpResponse, HttpErrorRespo import { Observable, throwError } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; -const SAFE_METHODS: string[] = ["GET", "HEAD", "OPTIONS", "TRACE"]; +export const SAFE_METHODS: string[] = ["GET", "HEAD", "OPTIONS", "TRACE"]; @Injectable({ providedIn: 'root'