diff --git a/AzureFunctions.AngularClient/src/app/function/embedded/embedded-function-editor/embedded-function-editor.component.ts b/AzureFunctions.AngularClient/src/app/function/embedded/embedded-function-editor/embedded-function-editor.component.ts index fc2fa416aa..266f662e4e 100644 --- a/AzureFunctions.AngularClient/src/app/function/embedded/embedded-function-editor/embedded-function-editor.component.ts +++ b/AzureFunctions.AngularClient/src/app/function/embedded/embedded-function-editor/embedded-function-editor.component.ts @@ -1,3 +1,4 @@ +import { ArmService } from 'app/shared/services/arm.service'; import { CdsFunctionDescriptor } from 'app/shared/resourceDescriptors'; import { errorIds } from 'app/shared/models/error-ids'; import { ErrorEvent } from 'app/shared/models/error-event'; @@ -17,6 +18,7 @@ import { TreeViewInfo } from './../../../tree-view/models/tree-view-info'; import { BroadcastService } from 'app/shared/services/broadcast.service'; import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core'; import { AfterContentInit } from '@angular/core/src/metadata/lifecycle_hooks'; +import { UserService } from 'app/shared/services/user.service'; @Component({ selector: 'embedded-function-editor', @@ -42,7 +44,9 @@ export class EmbeddedFunctionEditorComponent implements OnInit, AfterContentInit constructor( private _broadcastService: BroadcastService, private _cacheService: CacheService, - private _translateService: TranslateService) { + private _translateService: TranslateService, + private _armService: ArmService, + private _userService: UserService) { this._busyManager = new BusyStateScopeManager(this._broadcastService, 'dashboard'); @@ -163,21 +167,31 @@ export class EmbeddedFunctionEditorComponent implements OnInit, AfterContentInit const result = confirm(this._translateService.instant(PortalResources.functionManage_areYouSure, { name: this._functionInfo.name })); if (result) { this._busyManager.setBusy(); - this._cacheService.deleteArm(this.resourceId) - .subscribe(r => { - this._busyManager.clearBusy(); - this._broadcastService.broadcastEvent(BroadcastEvent.TreeUpdate, { - resourceId: this.resourceId, - operation: 'remove' + const headers = this._armService.getHeaders(); + this._userService.getStartupInfo() + .first() + .switchMap(info => { + headers.append('x-cds-crm-user-token', info.crmInfo.crmTokenHeaderName); + headers.append('x-cds-crm-org', info.crmInfo.crmInstanceHeaderName); + headers.append('x-cds-crm-solutionid', info.crmInfo.crmSolutionIdHeaderName); + + const url = this._armService.getArmUrl(this.resourceId, this._armService.websiteApiVersion); + return this._cacheService.delete(url, headers); + }) + .subscribe(r => { + this._busyManager.clearBusy(); + this._broadcastService.broadcastEvent(BroadcastEvent.TreeUpdate, { + resourceId: this.resourceId, + operation: 'remove' + }); + }, err => { + this._busyManager.clearBusy(); + this._broadcastService.broadcast(BroadcastEvent.Error, { + message: this._translateService.instant(PortalResources.error_unableToDeleteFunction).format(this._functionInfo.name), + errorId: errorIds.embeddedEditorDeleteError, + resourceId: this.resourceId, + }); }); - }, err => { - this._busyManager.clearBusy(); - this._broadcastService.broadcast(BroadcastEvent.Error, { - message: this._translateService.instant(PortalResources.error_unableToDeleteFunction).format(this._functionInfo.name), - errorId: errorIds.embeddedEditorDeleteError, - resourceId: this.resourceId, - }); - }); } } } diff --git a/AzureFunctions.AngularClient/src/app/function/function-new-detail/function-new-detail.component.ts b/AzureFunctions.AngularClient/src/app/function/function-new-detail/function-new-detail.component.ts index 02af95b3cc..b11b0e06bc 100644 --- a/AzureFunctions.AngularClient/src/app/function/function-new-detail/function-new-detail.component.ts +++ b/AzureFunctions.AngularClient/src/app/function/function-new-detail/function-new-detail.component.ts @@ -1,3 +1,4 @@ +import { ArmService } from './../../shared/services/arm.service'; import { ArmEmbeddedService } from './../../shared/services/arm-embedded.service'; import { KeyCodes, LogCategories } from './../../shared/models/constants'; import { TreeViewInfo } from 'app/tree-view/models/tree-view-info'; @@ -24,6 +25,7 @@ import { UIFunctionBinding } from '../../shared/models/binding'; import { PortalService } from '../../shared/services/portal.service'; import { Observable } from 'rxjs/Observable'; import { CreateCard } from 'app/function/function-new/function-new.component'; +import { UserService } from 'app/shared/services/user.service'; @Component({ selector: 'function-new-detail', @@ -78,7 +80,9 @@ export class FunctionNewDetailComponent implements OnChanges { private _aiService: AiService, private _cacheService: CacheService, private _functionAppService: FunctionAppService, - private _logService: LogService) { + private _logService: LogService, + private _armService: ArmService, + private _userService: UserService) { this.isEmbedded = this._portalService.isEmbeddedFunctions; } @@ -89,7 +93,7 @@ export class FunctionNewDetailComponent implements OnChanges { this.updateLanguageOptions(); if (this._portalService.isEmbeddedFunctions) { - this.getEntityOptions(); + this._getEntities(); } } } @@ -121,21 +125,6 @@ export class FunctionNewDetailComponent implements OnChanges { } } - getEntityOptions() { - this._getEntities() - .subscribe(r => { - const entities = (r.value.map(e => e.name)).sort(); - this.entityOptions = []; - entities.forEach(entity => { - const dropDownElement: any = { - displayLabel: entity, - value: entity - }; - this.entityOptions.push(dropDownElement); - }); - }); - } - onEntityChanged(entity: string) { this.areInputsValid = false; this.functionEntity = entity.toLowerCase(); @@ -313,8 +302,27 @@ export class FunctionNewDetailComponent implements OnChanges { private _getEntities() { const url = this._cdsEntitiesUrl; - return this._cacheService.get(url) - .map(r => r.json()); + const headers = this._armService.getHeaders(); + this._userService.getStartupInfo() + .first() + .switchMap(info => { + headers.append('x-cds-crm-user-token', info.crmInfo.crmTokenHeaderName); + headers.append('x-cds-crm-org', info.crmInfo.crmInstanceHeaderName); + headers.append('x-cds-crm-solutionid', info.crmInfo.crmSolutionIdHeaderName); + + return this._cacheService.get(url, null, headers).map(r => r.json()); + }) + .subscribe(r => { + const entities = (r.value.map(e => e.name)).sort(); + this.entityOptions = []; + entities.forEach(entity => { + const dropDownElement: any = { + displayLabel: entity, + value: entity + }; + this.entityOptions.push(dropDownElement); + }); + }); } private _createFunction() { diff --git a/AzureFunctions.AngularClient/src/app/functions-list/functions-list.component.ts b/AzureFunctions.AngularClient/src/app/functions-list/functions-list.component.ts index feb6f7b3e8..3a8c173cf6 100644 --- a/AzureFunctions.AngularClient/src/app/functions-list/functions-list.component.ts +++ b/AzureFunctions.AngularClient/src/app/functions-list/functions-list.component.ts @@ -1,3 +1,4 @@ +import { ArmService } from './../shared/services/arm.service'; import { ArmSiteDescriptor } from './../shared/resourceDescriptors'; import { FunctionAppContext } from './../shared/function-app-context'; import { TreeUpdateEvent, BroadcastEvent } from './../shared/models/broadcast-event'; @@ -19,6 +20,7 @@ import { Observable } from 'rxjs/Observable'; import { FunctionAppService } from 'app/shared/services/function-app.service'; import { Subscription } from 'rxjs/Subscription'; import { NavigableComponent } from '../shared/components/navigable-component'; +import { UserService } from 'app/shared/services/user.service'; @Component({ selector: 'functions-list', @@ -47,10 +49,12 @@ export class FunctionsListComponent extends NavigableComponent implements OnDest private _translateService: TranslateService, broadcastService: BroadcastService, private _functionAppService: FunctionAppService, - private _cacheService: CacheService) { + private _cacheService: CacheService, + private _armService: ArmService, + private _userService: UserService) { super('functions-list', broadcastService, DashboardType.FunctionsDashboard); - this.isEmbedded = this._portalService.isEmbeddedFunctions; + this.isEmbedded = this._portalService.isEmbeddedFunctions; } setupNavigation(): Subscription { @@ -73,9 +77,9 @@ export class FunctionsListComponent extends NavigableComponent implements OnDest this.runtimeVersion = tuple[1]; this.isLoading = false; this.functions = (this._functionsNode.children); - this.functionsInfo = this._functionsNode.children.map((child: FunctionNode) =>{ + this.functionsInfo = this._functionsNode.children.map((child: FunctionNode) => { return child.functionInfo; - }) + }); }); } @@ -85,36 +89,36 @@ export class FunctionsListComponent extends NavigableComponent implements OnDest templates.result.forEach((template) => { - const templateIndex = this.createCards.findIndex(finalTemplate => { - return finalTemplate.name === template.metadata.name; - }); + const templateIndex = this.createCards.findIndex(finalTemplate => { + return finalTemplate.name === template.metadata.name; + }); - // if the card doesn't exist, create it based off the template, else add information to the preexisting card - if (templateIndex === -1) { - this.createCards.push({ - name: `${template.metadata.name}`, - value: template.id, - description: template.metadata.description, - enabledInTryMode: template.metadata.enabledInTryMode, - AADPermissions: template.metadata.AADPermissions, - languages: [`${template.metadata.language}`], - categories: template.metadata.category, - ids: [`${template.id}`], - icon: 'image/other.svg', - color: '#000000', - barcolor: '#D9D9D9', - focusable: false - }); - } else { - this.createCards[templateIndex].languages.push(`${template.metadata.language}`); - this.createCards[templateIndex].categories = this.createCards[templateIndex].categories.concat(template.metadata.category); - this.createCards[templateIndex].ids.push(`${template.id}`); - } + // if the card doesn't exist, create it based off the template, else add information to the preexisting card + if (templateIndex === -1) { + this.createCards.push({ + name: `${template.metadata.name}`, + value: template.id, + description: template.metadata.description, + enabledInTryMode: template.metadata.enabledInTryMode, + AADPermissions: template.metadata.AADPermissions, + languages: [`${template.metadata.language}`], + categories: template.metadata.category, + ids: [`${template.id}`], + icon: 'image/other.svg', + color: '#000000', + barcolor: '#D9D9D9', + focusable: false + }); + } else { + this.createCards[templateIndex].languages.push(`${template.metadata.language}`); + this.createCards[templateIndex].categories = this.createCards[templateIndex].categories.concat(template.metadata.category); + this.createCards[templateIndex].ids.push(`${template.id}`); + } }); // unique categories this.createCards.forEach((template, index) => { - const categoriesDict: {[key: string]: string; } = {}; + const categoriesDict: { [key: string]: string; } = {}; template.categories.forEach(category => { categoriesDict[category] = category; }); @@ -127,7 +131,7 @@ export class FunctionsListComponent extends NavigableComponent implements OnDest }); this.createFunctionCard = this.createCards[0]; - }); + }); } clickRow(item: FunctionNode) { @@ -201,18 +205,30 @@ export class FunctionsListComponent extends NavigableComponent implements OnDest embeddedDelete(item: FunctionNode) { const result = confirm(this._translateService.instant(PortalResources.functionManage_areYouSure, { name: item.functionInfo.name })); if (result) { - this._globalStateService.setBusyState(); - this._cacheService.deleteArm(item.resourceId) - .subscribe(r => { - this._globalStateService.clearBusyState(); - this._broadcastService.broadcastEvent(BroadcastEvent.TreeUpdate, { - resourceId: item.resourceId, - operation: 'remove' - }); - }, err => { - this._globalStateService.clearBusyState(); - // TODO: ellhamai - handle error - }); + this._globalStateService.setBusyState(); + + const headers = this._armService.getHeaders(); + this._userService.getStartupInfo() + .first() + .switchMap(info => { + headers.append('x-cds-crm-user-token', info.crmInfo.crmTokenHeaderName); + headers.append('x-cds-crm-org', info.crmInfo.crmInstanceHeaderName); + headers.append('x-cds-crm-solutionid', info.crmInfo.crmSolutionIdHeaderName); + + const url = this._armService.getArmUrl(item.resourceId, this._armService.websiteApiVersion); + return this._cacheService.delete(url, headers); + }) + .subscribe(r => { + this._globalStateService.clearBusyState(); + this._broadcastService.broadcastEvent(BroadcastEvent.TreeUpdate, { + resourceId: item.resourceId, + operation: 'remove' + }); + + }, err => { + this._globalStateService.clearBusyState(); + // TODO: ellhamai - handle error + }); } } diff --git a/AzureFunctions.AngularClient/src/app/shared/services/arm-embedded.service.ts b/AzureFunctions.AngularClient/src/app/shared/services/arm-embedded.service.ts index d304de7261..8b52f2bbf5 100644 --- a/AzureFunctions.AngularClient/src/app/shared/services/arm-embedded.service.ts +++ b/AzureFunctions.AngularClient/src/app/shared/services/arm-embedded.service.ts @@ -7,7 +7,6 @@ import { UserService } from './user.service'; import { Http, Headers, Response } from '@angular/http'; import { Injectable } from '@angular/core'; import { ArmService } from './arm.service'; -import { CrmInfo } from 'app/shared/models/portal'; @Injectable() export class ArmEmbeddedService extends ArmService { @@ -29,27 +28,12 @@ export class ArmEmbeddedService extends ArmService { '/api/' ]; - private _crmHeaders: CrmInfo; - constructor(http: Http, userService: UserService, aiService: AiService, portalService: PortalService) { super(http, userService, portalService, aiService); - - userService.getStartupInfo().subscribe(info => { - this._crmHeaders = info.crmInfo; - }); - - } - - getHeaders(etag?: string) { - const headers = super.getHeaders(); - headers.append('x-cds-crm-user-token', this._crmHeaders.crmTokenHeaderName); - headers.append('x-cds-crm-org', this._crmHeaders.crmInstanceHeaderName); - headers.append('x-cds-crm-solutionid', this._crmHeaders.crmSolutionIdHeaderName); - return headers; } send(method: string, url: string, body?: any, etag?: string, headers?: Headers): Observable { diff --git a/AzureFunctions.AngularClient/src/app/shared/services/arm.service.ts b/AzureFunctions.AngularClient/src/app/shared/services/arm.service.ts index 9cee480d4b..bf0aaceb24 100644 --- a/AzureFunctions.AngularClient/src/app/shared/services/arm.service.ts +++ b/AzureFunctions.AngularClient/src/app/shared/services/arm.service.ts @@ -30,7 +30,7 @@ export class ArmService { constructor(private _http: Http, _userService: UserService, - private _portalService: PortalService, + _portalService: PortalService, protected _aiService: AiService) { this.armUrl = _portalService.isEmbeddedFunctions ? ArmEmbeddedService.url : ArmServiceHelper.armEndpoint; @@ -48,7 +48,7 @@ export class ArmService { send(method: string, url: string, body?: any, etag?: string, headers?: Headers, invokeApi?: boolean) { - headers = (headers && !this._portalService.isEmbeddedFunctions) ? headers : this.getHeaders(etag); + headers = headers ? headers : this.getHeaders(etag); if (invokeApi) { let pathAndQuery = url.slice(this.armUrl.length); diff --git a/AzureFunctions.AngularClient/src/app/shared/services/function-app.service.ts b/AzureFunctions.AngularClient/src/app/shared/services/function-app.service.ts index aee90ba61a..262e24d80e 100644 --- a/AzureFunctions.AngularClient/src/app/shared/services/function-app.service.ts +++ b/AzureFunctions.AngularClient/src/app/shared/services/function-app.service.ts @@ -1,3 +1,4 @@ +import { StartupInfo } from './../models/portal'; import { Host } from './../models/host'; import { ArmSiteDescriptor } from './../resourceDescriptors'; import { HttpMethods, HttpConstants } from './../models/constants'; @@ -44,6 +45,8 @@ export class FunctionAppService { private readonly azure: ConditionalHttpClient; private readonly _embeddedTemplates: Templates; + private startupInfo: StartupInfo; + constructor(private _cacheService: CacheService, private _translateService: TranslateService, private _userService: UserService, @@ -51,6 +54,11 @@ export class FunctionAppService { private _portalService: PortalService, logService: LogService) { + this._userService.getStartupInfo() + .subscribe(info => { + this.startupInfo = info; + }); + this.runtime = new ConditionalHttpClient(_cacheService, logService, context => this.getRuntimeToken(context), 'NoClientCertificate', 'NotOverQuota', 'NotStopped', 'ReachableLoadballancer'); this.azure = new ConditionalHttpClient(_cacheService, logService, _ => _userService.getStartupInfo().map(i => i.token), 'NotOverQuota', 'ReachableLoadballancer'); this._embeddedTemplates = new Templates(); @@ -236,8 +244,15 @@ export class FunctionAppService { const content = JSON.stringify({ files: filesCopy, test_data: sampleData, config: config }); const url = context.urlTemplates.getFunctionUrl(functionName); - return this.getClient(context).executeWithConditions([], context, t => - this._cacheService.put(url, this.jsonHeaders(t), content).map(r => r.json() as FunctionInfo)); + return this.getClient(context).executeWithConditions([], context, t => { + const headers = this.jsonHeaders(t); + if (this._portalService.isEmbeddedFunctions) { + headers.append('x-cds-crm-user-token', this.startupInfo.crmInfo.crmTokenHeaderName); + headers.append('x-cds-crm-org', this.startupInfo.crmInfo.crmInstanceHeaderName); + headers.append('x-cds-crm-solutionid', this.startupInfo.crmInfo.crmSolutionIdHeaderName); + } + return this._cacheService.put(url, headers, content).map(r => r.json() as FunctionInfo); + }); } statusCodeToText(code: number) { @@ -260,7 +275,7 @@ export class FunctionAppService { if (matchesPathParams) { matchesPathParams.forEach((m) => { - const name = m.split(':') [0].replace('{', '').replace('}', ''); + const name = m.split(':')[0].replace('{', '').replace('}', ''); processedParams.push(name); const param = model.queryStringParams.find((p) => { return p.name === name;