@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
146 lines (144 loc) • 6.3 kB
JavaScript
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