UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

1 lines 37.2 kB
{"version":3,"sources":["../../../packages/core/data/gateway-connection.ts"],"names":[],"mappings":"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","file":"gateway-connection.d.ts","sourcesContent":["import { Observable, of, ReplaySubject, Subscription, throwError } from 'rxjs';\r\nimport { AjaxError, AjaxRequest, AjaxResponse } from 'rxjs/ajax';\r\nimport { catchError, expand, filter, map, mergeMap, switchMap, take, tap } from 'rxjs/operators';\r\nimport { Strings } from '../generated/strings';\r\nimport { EnvironmentModule } from '../manifest/environment-modules';\r\nimport { RpcObservableElevateClient } from '../rpc/elevate/rpc-observable-elevate-client';\r\nimport {\r\n RpcObservableElevateError, RpcObservableElevateRequest, RpcObservableElevateResult\r\n} from '../rpc/elevate/rpc-observable-elevate-model';\r\nimport { RpcObservableElevateServer } from '../rpc/elevate/rpc-observable-elevate-server';\r\nimport { RpcForwardResponse } from '../rpc/forward/rpc-forward-model';\r\nimport { Rpc } from '../rpc/rpc';\r\nimport { RpcRelationshipType } from '../rpc/rpc-base';\r\nimport { RpcServiceForwarder } from '../rpc/rpc-forwarder';\r\nimport { AuthorizationManager } from '../security/authorization-manager';\r\nimport { SignedHttpRequestToken } from '../security/sign-on-manager';\r\nimport { CoreEnvironment } from './core-environment';\r\nimport { GatewayStatus } from './gateway-status';\r\nimport { GatewayUrlBuilder } from './gateway-url-builder';\r\nimport { GatewayUrls } from './gateway-urls';\r\nimport { Http, HttpMethod, HttpResponseRetryHandler, HttpRetryOptions } from './http';\r\nimport { headerConstants } from './http-constants';\r\nimport { Net } from './net';\r\n\r\n/**\r\n * Gateway Request options that we use to extend the AjaxRequest interface\r\n */\r\nexport interface GatewayRequestOptions {\r\n /**\r\n * Retry handler implementation for a request.\r\n * These handlers are used to invoke specific functionality for non-200 status codes in the http response.\r\n */\r\n retryHandlers?: HttpResponseRetryHandler[];\r\n\r\n /**\r\n * Determines the maximum number of times that any of the retry handlers will be tried.\r\n * before giving up and surfacing the error to the original caller\r\n */\r\n maxRetryCount?: number;\r\n\r\n /**\r\n * Observable handler to insert asynchronous logic before the actual http response is sent.\r\n * For Example: Waiting for pending authentication to complete before adding an authentication header\r\n */\r\n beforeCall?: (request: GatewayRequest) => Observable<void>;\r\n}\r\n\r\n/**\r\n * Extension of AjaxRequest interface for calling the Gateway API\r\n */\r\nexport interface GatewayRequest extends AjaxRequest, GatewayRequestOptions {\r\n}\r\n\r\n/**\r\n * Initialization object data for the Gateway's base class.\r\n */\r\nexport interface GatewayRPCForwardedProperties {\r\n /**\r\n * The gateway URL.\r\n */\r\n gatewayName: string;\r\n\r\n /**\r\n * Indicate whether gatewayUrl option was specified. (default to be false)\r\n */\r\n gatewayUrlSpecified: boolean;\r\n\r\n /**\r\n * The stative version. (default to be null)\r\n */\r\n staticVersion: string;\r\n}\r\n\r\n/**\r\n * The gateway information on current gateway URL.\r\n */\r\nexport interface GatewayInformation {\r\n /**\r\n * The name of gateway node.\r\n */\r\n name: string;\r\n\r\n /**\r\n * Indicating if https is used.\r\n */\r\n secure: boolean;\r\n\r\n /**\r\n * The port number of gateway.\r\n */\r\n port: number;\r\n}\r\n\r\n/**\r\n * Condition of gateway.\r\n */\r\nexport interface GatewayCondition {\r\n /**\r\n * the gateway is running as service mode (installed on server operating system).\r\n */\r\n isServiceMode: boolean;\r\n\r\n /**\r\n * the gateway is elevated on the desktop mode.\r\n */\r\n isGatewayProcessElevated: boolean;\r\n\r\n /**\r\n * the user account is a member of the gateway administrators.\r\n */\r\n isGatewayAdmin: boolean;\r\n}\r\n\r\n/**\r\n * The Gateway Connection class for creating requests and calling the Gateway's REST API\r\n */\r\nexport class GatewayConnection extends RpcServiceForwarder {\r\n private static rpcCommands = {\r\n forbiddenReceived: 'forbiddenRecieved'\r\n };\r\n\r\n /**\r\n * The IPv4 address for localhost\r\n */\r\n private readonly localhostIpV4 = '127.0.0.1';\r\n\r\n /**\r\n * The IPv6 address for localhost\r\n */\r\n private readonly localhostIpV6 = '::1';\r\n\r\n /**\r\n * The localhost name\r\n */\r\n private readonly localhost = 'localhost';\r\n\r\n /**\r\n * Time interval to check for internalGatewayStatus refresh.\r\n */\r\n private readonly lastUpdatedInternalGatewayStatusInterval = 1000 * 60 * 10; // 10 minutes\r\n\r\n /**\r\n * internally maintained gateway URL.\r\n */\r\n private internalGatewayUrl: string;\r\n\r\n /**\r\n * internally maintained static version.\r\n */\r\n private internalStaticVersion: string;\r\n\r\n /**\r\n * gatewayUrl param is specified.\r\n */\r\n private internalGatewayUrlSpecified: boolean;\r\n\r\n /**\r\n * Last time internal gateway status was updated in milliseconds\r\n */\r\n private lastUpdatedInternalGatewayStatus: number;\r\n\r\n /**\r\n * Internally maintained gateway status.\r\n */\r\n private internalGatewayStatus: Observable<GatewayStatus>;\r\n\r\n /**\r\n * The replay subject for gateway url to settle.\r\n */\r\n private gatewayUrlAwaiter = new ReplaySubject<string>(1);\r\n\r\n /**\r\n * The RPC observable elevate client.\r\n */\r\n private elevateClient: RpcObservableElevateClient = null;\r\n\r\n /**\r\n * The RPC observable elevate server.\r\n */\r\n private elevateServer: RpcObservableElevateServer = null;\r\n\r\n /**\r\n * The elevate callback observable.\r\n */\r\n private elevateCallbackInternal: () => Observable<boolean> = () => of(false);\r\n\r\n /**\r\n * The replay subject for navigation ready state.\r\n */\r\n private navigationReady = new ReplaySubject<boolean>(1);\r\n\r\n /**\r\n * Sets the elevate callback observable.\r\n */\r\n public set elevateCallback(value: () => Observable<boolean>) {\r\n this.elevateCallbackInternal = value;\r\n if (!this.elevateServer) {\r\n this.elevateServer = new RpcObservableElevateServer(this.rpc);\r\n this.elevateServer.register((_context: RpcObservableElevateRequest) => {\r\n return this.elevateCallbackInternal()\r\n .pipe(\r\n catchError((error, _caught) =>\r\n throwError(() => <RpcObservableElevateError>{error: Net.getErrorMessage(error) })),\r\n map(result =>\r\n <RpcObservableElevateResult>{ elevated: result })\r\n );\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Indicates that the gateway is disabled and therefore should not be called.\r\n */\r\n public get disabled(): boolean {\r\n const environment = MsftSme.self().Environment;\r\n return environment && environment.configuration.gateway.disabled;\r\n }\r\n\r\n /**\r\n * Gets the gateway URL to connect to.\r\n */\r\n public get gatewayUrl(): string {\r\n return this.internalGatewayUrl;\r\n }\r\n\r\n /**\r\n * Gets the gateway URL specified state.\r\n */\r\n public get staticVersion() {\r\n return this.internalStaticVersion;\r\n }\r\n\r\n /**\r\n * Gets the gateway URL specified state.\r\n */\r\n public get gatewayUrlSpecified(): boolean {\r\n return this.internalGatewayUrlSpecified;\r\n }\r\n\r\n /**\r\n * Gets the gateway URL observable while setting up.\r\n */\r\n public get gatewayUrlObservable(): Observable<string> {\r\n return this.gatewayUrlAwaiter.asObservable();\r\n }\r\n\r\n /**\r\n * Gets the navigation ready observable.\r\n */\r\n public get navigationReadyObservable(): Observable<boolean> {\r\n return this.navigationReady.asObservable();\r\n }\r\n\r\n /**\r\n * Sets the navigation ready status.\r\n */\r\n public set navigationReadyStatus(ready: boolean) {\r\n this.navigationReady.next(ready);\r\n }\r\n\r\n /**\r\n * Gets the gateway information.\r\n */\r\n public get gatewayInfo(): GatewayInformation {\r\n if (!this.internalGatewayUrl) {\r\n throw new Error(MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.GatewayUrlNotConfigured.message);\r\n }\r\n\r\n // RegEx: ('http' or 'https') '://' (('<gatewayName1>'):('<port>') or ('<gatewayName2>'))\r\n // 0: url\r\n // 1: https or http\r\n // 2: <gatewayName1>:<port> or <gatewayName2>\r\n // 3: <gatewayName1> or undefined\r\n // 4: <port> or undefined\r\n // 5: <gatewayName2>\r\n const url = MsftSme.trimEnd(this.internalGatewayUrl.toLowerCase(), '/');\r\n const match = url.match(/(http|https):\\/\\/((.+):(\\d+)|(.+))/);\r\n if (!match) {\r\n throw new Error(MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.GatewayUrlMalformed.message);\r\n }\r\n\r\n const secure = (match[1] === 'https');\r\n const name = match[3] || match[2];\r\n const port = parseInt(match[4], 10) || (secure ? 443 : 80);\r\n return { name, secure, port };\r\n }\r\n\r\n /**\r\n * Gets the gateway node name to make a CIM/PowerShell query to the gateway node.\r\n */\r\n public get gatewayName(): string {\r\n // localhost will be used to locally query gateway node. if this causes any access problem, need to be replaced.\r\n return 'localhost';\r\n }\r\n\r\n /**\r\n * Gets gateway status from cache or sets cache if it doesn't exist.\r\n */\r\n private get gatewayStatus(): Observable<any> {\r\n if (!this.internalGatewayStatus\r\n || Date.now() - this.lastUpdatedInternalGatewayStatus > this.lastUpdatedInternalGatewayStatusInterval) {\r\n return this.getStatus();\r\n }\r\n\r\n return of(this.internalGatewayStatus);\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the Gateway class.\r\n *\r\n * @param http the Http object.\r\n * @param rpc the Rpc class.\r\n * @patam authorizationManager the authorization manager class object.\r\n */\r\n constructor(public http: Http, rpc: Rpc, private authorizationManager: AuthorizationManager) {\r\n super('gateway-connection', rpc);\r\n\r\n // restore the AAD token if exist becase ealier access of token is required for gateway calls.\r\n authorizationManager.signOnManager.applySignedHttpRequestToken(\r\n <SignedHttpRequestToken>MsftSme.self().Environment.configuration?.signOn?.signedHttpRequestToken);\r\n }\r\n\r\n /**\r\n * Configure the gateway URL to connect to.\r\n */\r\n public configureGatewayEnvironment(url: string, urlSpecified: boolean, staticVersion: string): void {\r\n // trim last \"/\"\r\n if (url[url.length - 1] === '/') {\r\n url = url.substring(0, url.length - 1);\r\n }\r\n\r\n this.internalGatewayUrl = url;\r\n this.internalGatewayUrlSpecified = urlSpecified,\r\n this.internalStaticVersion = staticVersion;\r\n this.gatewayUrlAwaiter.next(url);\r\n }\r\n\r\n /**\r\n * Update the url with static version option.\r\n * @param url the original URL including options.\r\n * @returns updated url with \"version=\" option if staticVersion present.\r\n */\r\n public addStaticVersion(url: string): string {\r\n if (MsftSme.isNullOrWhiteSpace(this.staticVersion) || this.staticVersion.indexOf('staticVersion=') < 0) {\r\n return url;\r\n }\r\n\r\n const splitter = url.indexOf('?') > 0 ? '&' : '?';\r\n return `${url}${splitter}staticVersion=${this.staticVersion}`;\r\n }\r\n\r\n /**\r\n * Makes a POST call to the gateway\r\n *\r\n * @param relativeUrl the relative Url after \"/api\"\r\n * @param body the body string JSON.stringfy'ed\r\n * @param request the gateway request object.\r\n */\r\n public post(relativeUrl: string, body?: any, request?: GatewayRequest): Observable<any> {\r\n const postRequest = this.createRequest(HttpMethod.Post, relativeUrl, body, request);\r\n return this.call(postRequest);\r\n }\r\n\r\n /**\r\n * Makes a GET call to the gateway\r\n *\r\n * @param relativeUrl the relative Url after \"/api\"\r\n * @param request the gateway request object.\r\n */\r\n public get(relativeUrl: string, request?: GatewayRequest): Observable<any> {\r\n const getRequest = this.createRequest(HttpMethod.Get, relativeUrl, null, request);\r\n return this.call(getRequest);\r\n }\r\n\r\n /**\r\n * Makes a PUT call to the gateway\r\n *\r\n * @param relativeUrl the relative Url after \"/api\"\r\n * @param body the body string JSON.stringfy'ed\r\n * @param request the gateway request object.\r\n */\r\n public put(relativeUrl: string, body?: string, request?: GatewayRequest): Observable<any> {\r\n const putRequest = this.createRequest(HttpMethod.Put, relativeUrl, body, request);\r\n return this.call(putRequest);\r\n }\r\n\r\n /**\r\n * Makes a PATCH call to the gateway\r\n *\r\n * @param relativeUrl the relative Url after \"/api\"\r\n * @param body the body string JSON.stringfy'ed\r\n * @param request the gateway request object.\r\n */\r\n public patch(relativeUrl: string, body?: string, request?: GatewayRequest): Observable<any> {\r\n const patchRequest = this.createRequest(HttpMethod.Patch, relativeUrl, body, request);\r\n return this.call(patchRequest);\r\n }\r\n\r\n /**\r\n * Makes a DELETE call to the gateway\r\n *\r\n * @param relativeUrl the relative Url after \"/api\"\r\n * @param body the body string JSON.stringfy'ed\r\n * @param request the gateway request object.\r\n */\r\n public delete(relativeUrl: string, body?: string, request?: GatewayRequest): Observable<any> {\r\n const deleteRequest = this.createRequest(HttpMethod.Delete, relativeUrl, body, request);\r\n return this.call(deleteRequest);\r\n }\r\n\r\n /**\r\n * Makes a DELETE call to the gateway without waiting for the response.\r\n *\r\n * @param relativeUrl the relative Url after \"/api\"\r\n * @param request the gateway request object.\r\n */\r\n public deleteQuick(relativeUrl: string, headers?: any): void {\r\n headers[headerConstants.MODULE_NAME] = EnvironmentModule.getModuleName();\r\n headers[headerConstants.MODULE_VERSION] = EnvironmentModule.getModuleVersion();\r\n headers[headerConstants.ACCEPT_LANGUAGE] = CoreEnvironment.localizationManager.getLocaleId().neutral;\r\n if (this.staticVersion) {\r\n headers[headerConstants.STATIC_VERSION] = this.staticVersion;\r\n }\r\n\r\n if (this.authorizationManager.signOnManager.isSignOnTokenEnabled) {\r\n this.authorizationManager.signOnManager.SetAadAuthorizationHeader(headers);\r\n }\r\n\r\n const url = Net.gatewayApi(this.gatewayUrl, relativeUrl);\r\n this.http.deleteQuick(url, headers);\r\n }\r\n\r\n /**\r\n * Creates a GatewayRequest.\r\n *\r\n * @param method the http method to use\r\n * @param relativeUrl the relative Url after \"/api/\"\r\n * @param body the body string JSON.stringfy'ed\r\n * @param request the gateway request object to extend.\r\n */\r\n public createRequest(\r\n method: string,\r\n relativeUrl: string,\r\n body?: any,\r\n request?: GatewayRequest): GatewayRequest {\r\n\r\n const defaultMaxRetry = 3;\r\n request = MsftSme.deepAssign({}, request);\r\n\r\n // if request is undefined, default to empty object\r\n request = request || <GatewayRequest>{};\r\n request.headers = request.headers || {};\r\n (<any>request).headers[headerConstants.MODULE_NAME] = EnvironmentModule.getModuleName();\r\n (<any>request).headers[headerConstants.MODULE_VERSION] = EnvironmentModule.getModuleVersion();\r\n (<any>request).headers[headerConstants.ACCEPT_LANGUAGE] = CoreEnvironment.localizationManager.getLocaleId().neutral;\r\n if (this.staticVersion) {\r\n (<any>request).headers[headerConstants.STATIC_VERSION] = this.staticVersion;\r\n }\r\n\r\n // use default retry options if none are provided\r\n const retryHandlers: HttpResponseRetryHandler[] = [];\r\n if (this.authorizationManager.signOnManager.isSignOnTokenEnabled) {\r\n this.authorizationManager.signOnManager.SetAadAuthorizationHeader(request.headers);\r\n retryHandlers.push({\r\n canHandle: (code, error) => this.authorizationManager.signOnManager.canHandleUnauthorizedLogin(code, error),\r\n handle: (code, originalRequest, error) =>\r\n this.authorizationManager.signOnManager.handleUnauthorizedLogin(code, originalRequest, error)\r\n });\r\n }\r\n\r\n if (request.retryHandlers != null && request.retryHandlers.length > 0) {\r\n retryHandlers.push(...request.retryHandlers);\r\n }\r\n\r\n return Object.assign(request, <GatewayRequest><unknown>{\r\n method: method,\r\n url: relativeUrl,\r\n\r\n // default to the passed in body, the request body, or an empty string\r\n body: body || request.body || '',\r\n\r\n // default to the request headers, or an empty object\r\n headers: request.headers,\r\n\r\n // for the next 2 props, default to true unless explicitly set to false\r\n withCredentials: request.withCredentials === false ? false : true,\r\n crossDomain: request.crossDomain === false ? false : true,\r\n createXHR: () => new XMLHttpRequest(),\r\n\r\n retryHandlers,\r\n maxRetryCount: request.maxRetryCount === 0 ? 0 : request.maxRetryCount || defaultMaxRetry\r\n });\r\n }\r\n\r\n /**\r\n * Make a request.\r\n *\r\n * @param request the request to execute against the gateway.\r\n * @return Observable<any> the query result observable.\r\n */\r\n public call(request: GatewayRequest): Observable<any> {\r\n if (!this.gatewayUrl) {\r\n return this.gatewayUrlAwaiter.pipe(mergeMap(() => this.call(request)));\r\n }\r\n\r\n // create gateway url from current url if not set yet.\r\n if (!request.url || (!request.url.startsWith('http://') && !request.url.startsWith('https://'))) {\r\n request.url = Net.gatewayApi(this.gatewayUrl, request.url);\r\n }\r\n\r\n // create retry options from request\r\n const retryOptions: HttpRetryOptions = {\r\n handlers: (request.retryHandlers || []),\r\n maxRetry: request.maxRetryCount\r\n };\r\n // create observable for our request\r\n const requestObservable = this.http.request(request, retryOptions)\r\n .pipe(map((response: AjaxResponse<any>) => response ? response.response : {}));\r\n\r\n if (request.beforeCall) {\r\n return request.beforeCall(request).pipe(mergeMap(() => requestObservable));\r\n }\r\n\r\n return requestObservable;\r\n }\r\n\r\n /**\r\n * Gets default secure request options.\r\n *\r\n * @returns updated request object.\r\n */\r\n public get defaultHttpSecureOptions(): AjaxRequest {\r\n const request = { ...{ headers: {} }, ...Http.defaultHttpOptions };\r\n if (this.authorizationManager.signOnManager.isSignOnTokenEnabled) {\r\n this.authorizationManager.signOnManager.SetAadAuthorizationHeader(request.headers);\r\n }\r\n\r\n return request;\r\n }\r\n\r\n /**\r\n * Check if elevation is required from the error object.\r\n *\r\n * @param error the ajax error object.\r\n */\r\n public isElevationRequired(error: AjaxError): boolean {\r\n const code = error.xhr && error.xhr.response && error.xhr.response.error && error.xhr.response.error.code;\r\n return code === 'ElevationRequired';\r\n }\r\n\r\n /**\r\n * Elevate the gateway if it's desktop mode running.\r\n */\r\n public elevate(): Observable<boolean> {\r\n if (!this.elevateClient) {\r\n this.elevateClient = new RpcObservableElevateClient(this.rpc);\r\n }\r\n\r\n return this.elevateClient.elevate().pipe(map(result => result.elevated));\r\n }\r\n\r\n /**\r\n * Creates and returns a new URL builder for the current connection.\r\n */\r\n public url(): GatewayUrlBuilder {\r\n return new GatewayUrlBuilder(this.gatewayUrl);\r\n }\r\n\r\n /**\r\n * Clear the DNS cache.\r\n */\r\n public clearDnsCache(): Observable<void> {\r\n const dnsCacheClearUrl = 'gateway/dnsCacheClear';\r\n return this.delete(dnsCacheClearUrl)\r\n .pipe(map(_ => null));\r\n }\r\n\r\n /**\r\n * Polling to check if the gateway is elevated.\r\n */\r\n public pollingGatewayElevated(): Observable<boolean> {\r\n // user might not respond for elevation prompt, maximum waiting time is 2.5 min.\r\n // getElevatedStatus() takes 5000ms when the gateway is not responding.\r\n // 2.5 min = count [30] * 5000 msec.\r\n const uniQueId = MsftSme.getUniqueId();\r\n const maxWaitingCount = 30;\r\n let count = maxWaitingCount;\r\n return this.getElevatedStatus()\r\n .pipe(\r\n expand(status => {\r\n // user accepted.\r\n // adds 5 calls for the gateway dead period.\r\n // < Restart Requested from UI >\r\n // 1st query: it shows success on slow performed system, the gateway is even not shutdown yet.\r\n // 2nd query: It could success still.\r\n // 3rd query: Maybe timeout because the gateway is not started yet.\r\n // 4rd query: Maybe timeout because the gateway is not started yet.\r\n // 5rd query: Maybe timeout because the gateway is down.\r\n // 25 = 30 - 5\r\n const pollingStartCount = 25;\r\n if (\r\n (\r\n (count <= pollingStartCount\r\n && (!status.error || status.isGatewayProcessElevated))\r\n || status.completed\r\n )\r\n && (status.id === uniQueId)\r\n ) {\r\n return of({\r\n completed: true,\r\n id: uniQueId,\r\n isGatewayProcessElevated: status.isGatewayProcessElevated\r\n });\r\n }\r\n\r\n // no response for more than 2.5 minutes.\r\n // gateway was stopped for long or user never responded to UAC prompt.\r\n if (count-- <= 0 && status.id === uniQueId) {\r\n return of({\r\n completed: true,\r\n id: uniQueId,\r\n isGatewayProcessElevated: status.isGatewayProcessElevated\r\n });\r\n }\r\n\r\n return this.getElevatedStatus();\r\n }),\r\n filter(result => result.isGatewayProcessElevated || result.completed),\r\n take(1),\r\n map(result => result.isGatewayProcessElevated)\r\n );\r\n }\r\n\r\n /**\r\n * Perform gateway status query but cut off if it exceeds 2.5 seconds.\r\n */\r\n public getElevatedStatus(): Observable<{ error: boolean, isGatewayProcessElevated: boolean, completed: boolean, id: string }> {\r\n // if the gateway is not responding for 5000ms, cancel the call.\r\n const callCancelTime = 5000;\r\n return new Observable(observer => {\r\n let subscription: Subscription = null;\r\n let timer = setTimeout(\r\n () => {\r\n // handle pending timeout of the query when the gateway doesn't respond.\r\n if (subscription) {\r\n observer.next({ error: true, isGatewayProcessElevated: false, completed: undefined, id: undefined });\r\n observer.complete();\r\n subscription.unsubscribe();\r\n subscription = null;\r\n timer = null;\r\n }\r\n },\r\n callCancelTime);\r\n subscription = this.getStatus()\r\n .subscribe({\r\n next: data => {\r\n observer.next({\r\n error: false,\r\n isGatewayProcessElevated: data.isGatewayProcessElevated,\r\n completed: undefined,\r\n id: undefined\r\n });\r\n observer.complete();\r\n subscription.unsubscribe();\r\n subscription = null;\r\n if (timer) {\r\n clearTimeout(timer);\r\n }\r\n },\r\n error: () => {\r\n observer.next({ error: true, isGatewayProcessElevated: false, completed: undefined, id: undefined });\r\n observer.complete();\r\n subscription.unsubscribe();\r\n subscription = null;\r\n if (timer) {\r\n clearTimeout(timer);\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Gets gateway machine if found in list of given nodes\r\n * @param nodes Node names or IPs to check\r\n * @returns Node name of gateway if found, null otherwise\r\n */\r\n public getGateway(nodes: string[]): Observable<string> {\r\n return this.gatewayStatus.pipe(map(status => {\r\n for (const node of nodes) {\r\n if (MsftSme.isNullOrUndefined(node)) {\r\n continue;\r\n }\r\n\r\n switch (node.toLocaleLowerCase()) {\r\n case this.localhostIpV4:\r\n case this.localhostIpV6:\r\n case this.localhost:\r\n case status.fullyQualifiedDNSName?.toLocaleLowerCase():\r\n case status.name?.toLocaleLowerCase():\r\n case status.machineName?.toLocaleLowerCase():\r\n return node;\r\n }\r\n\r\n if (status.addressList?.find((address: string) => address === node)) {\r\n return node;\r\n }\r\n }\r\n\r\n return null;\r\n }));\r\n }\r\n\r\n /**\r\n * Check gateway condition.\r\n */\r\n public checkCondition(): Observable<GatewayCondition> {\r\n const result = <GatewayCondition>{};\r\n return this.getStatus()\r\n .pipe(\r\n switchMap(gateway => {\r\n if (gateway.gatewayMode === 'Service') {\r\n result.isServiceMode = true;\r\n result.isGatewayProcessElevated = false;\r\n return this.getAccessCheck();\r\n }\r\n\r\n result.isServiceMode = false;\r\n result.isGatewayProcessElevated = gateway.isGatewayProcessElevated;\r\n return of(true);\r\n }),\r\n map((isAdmin) => {\r\n result.isGatewayAdmin = !!isAdmin;\r\n return result;\r\n }),\r\n take(1)\r\n );\r\n }\r\n\r\n /**\r\n * Get gateway status.\r\n */\r\n public getStatus(): Observable<any> {\r\n return this.get('gateway/status').pipe(tap(status => {\r\n this.lastUpdatedInternalGatewayStatus = Date.now();\r\n this.internalGatewayStatus = status;\r\n }));\r\n }\r\n\r\n /**\r\n * Get user access check.\r\n */\r\n public getAccessCheck(): Observable<any> {\r\n return this.get(GatewayUrls.accessCheck);\r\n }\r\n\r\n /**\r\n * Called on a child service instance when onForwardInit returns from the parent\r\n * Initialize telemetry from within here so we can leverage gateway status for telemetry metadata.\r\n * @param data The response from the forwardInit call\r\n */\r\n protected onForwardInitResponse(data: RpcForwardResponse<GatewayRPCForwardedProperties>): void {\r\n if (data.error) {\r\n // if there is an error, we cannot continue, so throw its\r\n throw data.error;\r\n }\r\n\r\n if (!MsftSme.self().Environment.configuration.gateway.disabled) {\r\n this.internalGatewayUrl = data.result.gatewayName;\r\n this.internalGatewayUrlSpecified = data.result.gatewayUrlSpecified;\r\n this.internalStaticVersion = data.result.staticVersion;\r\n\r\n }\r\n }\r\n\r\n /**\r\n * Called when a new instance of the service in another window is initialized and needs to synchronize with its parent\r\n * @param from The RpcRelationshipType that this request is from\r\n * @returns an observable for the all the values needed to initialize the service\r\n */\r\n protected onForwardInit(): Observable<GatewayRPCForwardedProperties> {\r\n if (this.gatewayUrl) {\r\n return of({\r\n gatewayName: this.gatewayUrl,\r\n gatewayUrlSpecified: this.gatewayUrlSpecified,\r\n staticVersion: this.staticVersion\r\n });\r\n } else {\r\n // if gateway value hasn't been set yet, then wait for it.\r\n if (MsftSme.self().Environment.configuration.gateway.disabled) {\r\n return of(null);\r\n }\r\n\r\n return this.gatewayUrlAwaiter\r\n .pipe(map(url => ({\r\n gatewayName: url,\r\n gatewayUrlSpecified: this.gatewayUrlSpecified,\r\n staticVersion: this.staticVersion\r\n })));\r\n }\r\n }\r\n\r\n /**\r\n * Called when the forwarded services counterpart wants to get data from the parent\r\n * @param from The RpcRelationshipType that this request is from\r\n * @param name The name of the method to forward to\r\n * @param args The arguments of the method\r\n * @returns an observable for the result of the method call\r\n */\r\n protected onForwardExecute(from: RpcRelationshipType, name: string): Observable<any> {\r\n // gatewayConnection does not allow any method calls at this time\r\n return this.nameNotFound(name);\r\n }\r\n\r\n /**\r\n * Called when the forwarded services counterpart sends a notify message\r\n * @param from The RpcRelationshipType that this request is from\r\n * @param name The name of the property to change\r\n * @param value The new value of the property\r\n * @returns an observable that completes when the property has been changed.\r\n */\r\n protected onForwardNotify(from: RpcRelationshipType, name: string): Observable<void> {\r\n if (from === RpcRelationshipType.Child && name === GatewayConnection.rpcCommands.forbiddenReceived) {\r\n // Deprecated noop version 1.1100.0 at 10/1/2020. Using ErrorMonitor.\r\n return of(null);\r\n }\r\n // gatewayConnection does not allow any other notifications at this time\r\n return this.nameNotFound(name);\r\n }\r\n}\r\n"]}