UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

146 lines (144 loc) 6.3 kB
import { Observable, of } from 'rxjs'; import { mergeMap } from 'rxjs/operators'; import { ErrorExtended } from '../data/error-extended'; import { headerConstants } from '../data/http-constants'; import { HostCoreMessageType } from './host-core-message-type'; export var HostCoreTokenMode; (function (HostCoreTokenMode) { HostCoreTokenMode[HostCoreTokenMode["Unknown"] = 0] = "Unknown"; HostCoreTokenMode[HostCoreTokenMode["Aad"] = 1] = "Aad"; })(HostCoreTokenMode || (HostCoreTokenMode = {})); export class HostCoreManager { static tokenOption = 'token'; static aadMode = 'aad'; maxResponseTimeout = 2 * 1000; /** * The token mode. */ tokenMode; /** * Token will be collected when using HostCoreManager for manifest loading. */ token = null; /** * Initializes a new instance of new HostCoreManager class. */ constructor() { // Check if token mode was sepecified at URL parameter. const optionParam = MsftSme.getLocationSearchParameter(HostCoreManager.tokenOption); this.tokenMode = optionParam && MsftSme.localeCompareIgnoreCase(optionParam.value, HostCoreManager.aadMode) === 0 ? HostCoreTokenMode.Aad : HostCoreTokenMode.Unknown; } /** * Query JSON data with a token. * @param url Url to query data using current token. * @returns ajax response object. */ httpGet(url) { const tokenQuery = this.tokenMode === HostCoreTokenMode.Aad ? this.requestTokenToParentWindow(url) : of(null); return tokenQuery.pipe(mergeMap(() => this.getNoCache(url))); } /** * Performs a request with 'get' http method with cache control. * @param url the uri for GET call. * @return the observable for GET result data. */ getNoCache(url, noCache = true, responseType = '', withCredentials = true) { const publish = new Observable(observer => { const request = new XMLHttpRequest(); const handler = () => { if (request.readyState === XMLHttpRequest.DONE) { if (request.status === 200) { try { let response; if (responseType === '') { response = JSON.parse(request.response); } else { response = request.response; } observer.next({ status: request.status, response }); observer.complete(); } catch (e) { observer.error(e); } } else { // if response has a html content, redirects to the form login page which is "/". // if response has an error JSON payload, it displays the error at the splashscreen. (RBAC error) let errorMessage = request.statusText; if (request.response && request.response.indexOf('<!DOCTYPE html>') < 0) { const errorResponse = JSON.parse(request.response); errorMessage = errorResponse?.error.message || errorMessage; } const error = new ErrorExtended(errorMessage); error.extendedSource = ErrorExtended.sources.getNoCache; error.extended = { status: request.status, url }; observer.error(error); } } }; request.open('Get', url); request.withCredentials = withCredentials; request.responseType = responseType; request.setRequestHeader(headerConstants.ACCEPT, 'application/json, text/plain, */*'); if (this.token) { // sending a token, it creates an active cookie on the browser. request.setRequestHeader(headerConstants.SME_AAD_AUTHORIZATION, `WAC;PAS ${this.token.jwt}`); } if (noCache) { request.setRequestHeader('Cache-control', 'no-cache'); } request.onreadystatechange = handler; request.send(); }); return publish; } /** * Query the token to host window. * @param url the target url (manifest.json) * @param responseTimeout the response timeout. * @returns observeral of token query. */ requestTokenToParentWindow(url, responseTimeout = this.maxResponseTimeout) { const hostWindow = MsftSme.getHostWindow(); if (!hostWindow) { return of(null); } if (this.token) { return of(this.token); } return new Observable(subscriber => { const request = { requestId: MsftSme.newGuid(), type: HostCoreMessageType.HostCoreToken }; const listener = (event) => { if (event.data && event.data.requestId === request.requestId && event.data.data) { this.token = event.data.data; subscriber.next(this.token); subscriber.complete(); } }; const channel = new MessageChannel(); channel.port1.addEventListener('message', listener); channel.port1.start(); channel.port2.start(); setTimeout(() => { hostWindow.postMessage(request, '*', [channel.port2]); setTimeout(() => { const error = new ErrorExtended('timed out for token query'); error.extendedSource = ErrorExtended.sources.getNoCache; error.extended = { status: 403, url }; subscriber.error(error); }, responseTimeout); }); return () => { channel.port1.removeEventListener('message', listener); channel.port1.close(); }; }); } } //# sourceMappingURL=host-core-manager.js.map