@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
200 lines • 25 kB
JavaScript
import { inject, Injectable } from '@angular/core';
import { FetchClient } from '@c8y/client';
import { ContextRouteService, Permissions, ServiceRegistry, ViewContext } from '@c8y/ngx-components';
import { gettext } from '@c8y/ngx-components/gettext';
import { defer, shareReplay } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "@c8y/ngx-components";
export const CREDENTIALS_TYPES = {
NONE: {
name: 'NONE',
value: 'NONE',
label: gettext('No password')
},
USER_PASS: {
name: 'USER_PASS',
value: 'USER_PASS',
label: gettext('Username and password')
},
PASS_ONLY: {
name: 'PASS_ONLY',
value: 'PASS_ONLY',
label: gettext('Password only')
},
KEY_PAIR: {
name: 'KEY_PAIR',
value: 'KEY_PAIR',
label: gettext('Public/private keys')
},
CERTIFICATE: {
name: 'CERTIFICATE',
value: 'CERTIFICATE',
label: gettext('Certificate')
}
};
export const canActivateRemoteAccess = (route) => {
const permissions = inject(Permissions);
const remoteAccessService = inject(RemoteAccessService);
const contextRouteService = inject(ContextRouteService);
if (!permissions.hasRole(Permissions.ROLE_REMOTE_ACCESS_ADMIN)) {
return false;
}
const contextDetails = contextRouteService.getContextData(route);
if (contextDetails.context !== ViewContext.Device) {
return false;
}
const device = contextDetails.contextData;
if (!device || !Array.isArray(device.c8y_SupportedOperations)) {
return false;
}
const supportedOperations = device.c8y_SupportedOperations;
if (!supportedOperations.includes('c8y_RemoteAccessConnect')) {
return false;
}
return remoteAccessService.isAvailable$();
};
export class RemoteAccessService {
constructor(fetchClient, serviceRegistry) {
this.fetchClient = fetchClient;
this.serviceRegistry = serviceRegistry;
this.baseUrl = '/service/remoteaccess';
}
/**
* Verifies if the remote access service is available by sending a HEAD request to is's health endpoint.
* @returns cached Observable that emits true if the service is available, false otherwise.
*/
isAvailable$() {
if (!this.cachedIsAvailable$) {
this.cachedIsAvailable$ = defer(() => this.healthEndpointAvailable()).pipe(shareReplay(1));
}
return this.cachedIsAvailable$;
}
/**
* misses the leading ? for the query params
*/
getAuthQueryParamsForWebsocketConnection() {
const { headers } = this.fetchClient.getFetchOptions();
const params = new URLSearchParams();
if (headers) {
const xsrfToken = headers['X-XSRF-TOKEN'];
const auth = headers['Authorization'];
if (xsrfToken) {
params.append('XSRF-TOKEN', xsrfToken);
}
if (auth) {
params.append('token', auth.replace('Bearer ', '').replace('Basic ', ''));
}
}
const paramsString = params.toString();
return paramsString;
}
/**
* Returns the URI for the websocket connection to the remote access service.
*/
getWebSocketUri(deviceId, configurationId) {
const authQueryParams = this.getAuthQueryParamsForWebsocketConnection();
const protocol = window.location.protocol === 'http:' ? 'ws' : 'wss';
const pathName = `${protocol}://${window.location.host}${this.baseUrl}/client/${deviceId}/configurations/${configurationId}`;
return authQueryParams ? `${pathName}?${authQueryParams}` : pathName;
}
/**
* Retrieves all configurations for a given device.
*/
async listConfigurations(deviceId) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations`);
if (response.ok) {
return response.json();
}
throw new Error(`Failed to fetch configurations for device ${deviceId}`);
}
/**
* Deletes a configuration for a given device.
*/
async deleteConfiguration(deviceId, configurationId) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations/${configurationId}`, { method: 'DELETE' });
if (response.ok) {
return;
}
throw new Error(`Failed to delete configuration for device ${deviceId}`);
}
/**
* Retrieves all available remote access protocol providers.
*/
getProtocolProviders() {
return this.serviceRegistry.get('remoteAccessProtocolHook');
}
/**
* Creates a new configuration for a given device.
*/
async addConfiguration(deviceId, configuration) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(configuration)
});
if (response.ok) {
return response.json();
}
throw new Error(`Failed to add configuration for device ${configuration.attrs.deviceId}`);
}
/**
* Updates a configuration for a given device.
*/
async updateConfiguration(deviceId, configuration) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations/${configuration.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(configuration)
});
if (response.ok) {
return response.json();
}
throw new Error(`Failed to update configuration for device ${configuration.attrs.deviceId}`);
}
/**
* Generates a SSH key pair for a given hostname.
*/
async generateKeyPair(hostname) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/keypair/generate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ hostname })
});
if (response.ok) {
return response.json();
}
throw new Error(`Failed to generate key pair for ${hostname}`);
}
async healthEndpointAvailable() {
try {
const response = await this.fetchClient.fetch(`${this.baseUrl}/health`, {
method: 'HEAD',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
return !!response.ok;
}
}
catch (e) {
return false;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessService, deps: [{ token: i1.FetchClient }, { token: i2.ServiceRegistry }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.FetchClient }, { type: i2.ServiceRegistry }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlLWFjY2Vzcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcmVtb3RlLWFjY2Vzcy9kYXRhL3JlbW90ZS1hY2Nlc3Muc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRCxPQUFPLEVBQUUsV0FBVyxFQUFrQixNQUFNLGFBQWEsQ0FBQztBQUMxRCxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxlQUFlLEVBQ2YsV0FBVyxFQUNaLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3RELE9BQU8sRUFBYyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7O0FBYXRELE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHO0lBQy9CLElBQUksRUFBRTtRQUNKLElBQUksRUFBRSxNQUFNO1FBQ1osS0FBSyxFQUFFLE1BQU07UUFDYixLQUFLLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQztLQUM5QjtJQUNELFNBQVMsRUFBRTtRQUNULElBQUksRUFBRSxXQUFXO1FBQ2pCLEtBQUssRUFBRSxXQUFXO1FBQ2xCLEtBQUssRUFBRSxPQUFPLENBQUMsdUJBQXVCLENBQUM7S0FDeEM7SUFDRCxTQUFTLEVBQUU7UUFDVCxJQUFJLEVBQUUsV0FBVztRQUNqQixLQUFLLEVBQUUsV0FBVztRQUNsQixLQUFLLEVBQUUsT0FBTyxDQUFDLGVBQWUsQ0FBQztLQUNoQztJQUNELFFBQVEsRUFBRTtRQUNSLElBQUksRUFBRSxVQUFVO1FBQ2hCLEtBQUssRUFBRSxVQUFVO1FBQ2pCLEtBQUssRUFBRSxPQUFPLENBQUMscUJBQXFCLENBQUM7S0FDdEM7SUFDRCxXQUFXLEVBQUU7UUFDWCxJQUFJLEVBQUUsYUFBYTtRQUNuQixLQUFLLEVBQUUs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LFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDdkIsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQzsrR0EvS1UsbUJBQW1CO21IQUFuQixtQkFBbUIsY0FGbEIsTUFBTTs7NEZBRVAsbUJBQW1CO2tCQUgvQixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgQ2FuQWN0aXZhdGVGbiB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBGZXRjaENsaWVudCwgSU1hbmFnZWRPYmplY3QgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQge1xuICBDb250ZXh0Um91dGVTZXJ2aWNlLFxuICBQZXJtaXNzaW9ucyxcbiAgU2VydmljZVJlZ2lzdHJ5LFxuICBWaWV3Q29udGV4dFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL2dldHRleHQnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZGVmZXIsIHNoYXJlUmVwbGF5IH0gZnJvbSAncnhqcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbiB7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgaG9zdG5hbWU6IHN0cmluZztcbiAgcG9ydDogbnVtYmVyO1xuICBwcm90b2NvbDogc3RyaW5nO1xuICBhdHRycz86IGFueTtcbiAgY3JlZGVudGlhbHM/OiBhbnk7XG4gIGNyZWRlbnRpYWxzVHlwZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IENSRURFTlRJQUxTX1RZUEVTID0ge1xuICBOT05FOiB7XG4gICAgbmFtZTogJ05PTkUnLFxuICAgIHZhbHVlOiAnTk9ORScsXG4gICAgbGFiZWw6IGdldHRleHQoJ05vIHBhc3N3b3JkJylcbiAgfSxcbiAgVVNFUl9QQVNTOiB7XG4gICAgbmFtZTogJ1VTRVJfUEFTUycsXG4gICAgdmFsdWU6ICdVU0VSX1BBU1MnLFxuICAgIGxhYmVsOiBnZXR0ZXh0KCdVc2VybmFtZSBhbmQgcGFzc3dvcmQnKVxuICB9LFxuICBQQVNTX09OTFk6IHtcbiAgICBuYW1lOiAnUEFTU19PTkxZJyxcbiAgICB2YWx1ZTogJ1BBU1NfT05MWScsXG4gICAgbGFiZWw6IGdldHRleHQoJ1Bhc3N3b3JkIG9ubHknKVxuICB9LFxuICBLRVlfUEFJUjoge1xuICAgIG5hbWU6ICdLRVlfUEFJUicsXG4gICAgdmFsdWU6ICdLRVlfUEFJUicsXG4gICAgbGFiZWw6IGdldHRleHQoJ1B1YmxpYy9wcml2YXRlIGtleXMnKVxuICB9LFxuICBDRVJUSUZJQ0FURToge1xuICAgIG5hbWU6ICdDRVJUSUZJQ0FURScsXG4gICAgdmFsdWU6ICdDRVJUSUZJQ0FURScsXG4gICAgbGFiZWw6IGdldHRleHQoJ0NlcnRpZmljYXRlJylcbiAgfVxufSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IGNhbkFjdGl2YXRlUmVtb3RlQWNjZXNzOiBDYW5BY3RpdmF0ZUZuID0gKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gIGNvbnN0IHBlcm1pc3Npb25zID0gaW5qZWN0KFBlcm1pc3Npb25zKTtcbiAgY29uc3QgcmVtb3RlQWNjZXNzU2VydmljZSA9IGluamVjdChSZW1vdGVBY2Nlc3NTZXJ2aWNlKTtcbiAgY29uc3QgY29udGV4dFJvdXRlU2VydmljZSA9IGluamVjdChDb250ZXh0Um91dGVTZXJ2aWNlKTtcbiAgaWYgKCFwZXJtaXNzaW9ucy5oYXNSb2xlKFBlcm1pc3Npb25zLlJPTEVfUkVNT1RFX0FDQ0VTU19BRE1JTikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBjb250ZXh0RGV0YWlscyA9IGNvbnRleHRSb3V0ZVNlcnZpY2UuZ2V0Q29udGV4dERhdGEocm91dGUpO1xuICBpZiAoY29udGV4dERldGFpbHMuY29udGV4dCAhPT0gVmlld0NvbnRleHQuRGV2aWNlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgZGV2aWNlID0gY29udGV4dERldGFpbHMuY29udGV4dERhdGEgYXMgSU1hbmFnZWRPYmplY3Q7XG4gIGlmICghZGV2aWNlIHx8ICFBcnJheS5pc0FycmF5KGRldmljZS5jOHlfU3VwcG9ydGVkT3BlcmF0aW9ucykpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3Qgc3VwcG9ydGVkT3BlcmF0aW9uczogc3RyaW5nW10gPSBkZXZpY2UuYzh5X1N1cHBvcnRlZE9wZXJhdGlvbnM7XG4gIGlmICghc3VwcG9ydGVkT3BlcmF0aW9ucy5pbmNsdWRlcygnYzh5X1JlbW90ZUFjY2Vzc0Nvbm5lY3QnKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gcmVtb3RlQWNjZXNzU2VydmljZS5pc0F2YWlsYWJsZSQoKTtcbn07XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIFJlbW90ZUFjY2Vzc1NlcnZpY2Uge1xuICBwcml2YXRlIGNhY2hlZElzQXZhaWxhYmxlJDogT2JzZXJ2YWJsZTxib29sZWFuPjtcbiAgcmVhZG9ubHkgYmFzZVVybCA9ICcvc2VydmljZS9yZW1vdGVhY2Nlc3MnO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGZldGNoQ2xpZW50OiBGZXRjaENsaWVudCxcbiAgICBwcml2YXRlIHNlcnZpY2VSZWdpc3RyeTogU2VydmljZVJlZ2lzdHJ5XG4gICkge31cblxuICAvKipcbiAgICogVmVyaWZpZXMgaWYgdGhlIHJlbW90ZSBhY2Nlc3Mgc2VydmljZSBpcyBhdmFpbGFibGUgYnkgc2VuZGluZyBhIEhFQUQgcmVxdWVzdCB0byBpcydzIGhlYWx0aCBlbmRwb2ludC5cbiAgICogQHJldHVybnMgY2FjaGVkIE9ic2VydmFibGUgdGhhdCBlbWl0cyB0cnVlIGlmIHRoZSBzZXJ2aWNlIGlzIGF2YWlsYWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgKi9cbiAgaXNBdmFpbGFibGUkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIGlmICghdGhpcy5jYWNoZWRJc0F2YWlsYWJsZSQpIHtcbiAgICAgIHRoaXMuY2FjaGVkSXNBdmFpbGFibGUkID0gZGVmZXIoKCkgPT4gdGhpcy5oZWFsdGhFbmRwb2ludEF2YWlsYWJsZSgpKS5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jYWNoZWRJc0F2YWlsYWJsZSQ7XG4gIH1cblxuICAvKipcbiAgICogbWlzc2VzIHRoZSBsZWFkaW5nID8gZm9yIHRoZSBxdWVyeSBwYXJhbXNcbiAgICovXG4gIGdldEF1dGhRdWVyeVBhcmFtc0ZvcldlYnNvY2tldENvbm5lY3Rpb24oKSB7XG4gICAgY29uc3QgeyBoZWFkZXJzIH0gPSB0aGlzLmZldGNoQ2xpZW50LmdldEZldGNoT3B0aW9ucygpO1xuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcblxuICAgIGlmIChoZWFkZXJzKSB7XG4gICAgICBjb25zdCB4c3JmVG9rZW4gPSBoZWFkZXJzWydYLVhTUkYtVE9LRU4nXTtcbiAgICAgIGNvbnN0IGF1dGggPSBoZWFkZXJzWydBdXRob3JpemF0aW9uJ107XG5cbiAgICAgIGlmICh4c3JmVG9rZW4pIHtcbiAgICAgICAgcGFyYW1zLmFwcGVuZCgnWFNSRi1UT0tFTicsIHhzcmZUb2tlbik7XG4gICAgICB9XG4gICAgICBpZiAoYXV0aCkge1xuICAgICAgICBwYXJhbXMuYXBwZW5kKCd0b2tlbicsIGF1dGgucmVwbGFjZSgnQmVhcmVyICcsICcnKS5yZXBsYWNlKCdCYXNpYyAnLCAnJykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHBhcmFtc1N0cmluZyA9IHBhcmFtcy50b1N0cmluZygpO1xuICAgIHJldHVybiBwYXJhbXNTdHJpbmc7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgVVJJIGZvciB0aGUgd2Vic29ja2V0IGNvbm5lY3Rpb24gdG8gdGhlIHJlbW90ZSBhY2Nlc3Mgc2VydmljZS5cbiAgICovXG4gIGdldFdlYlNvY2tldFVyaTxLIGV4dGVuZHMgc3RyaW5nLCBJIGV4dGVuZHMgc3RyaW5nPihkZXZpY2VJZDogSywgY29uZmlndXJhdGlvbklkOiBJKSB7XG4gICAgY29uc3QgYXV0aFF1ZXJ5UGFyYW1zID0gdGhpcy5nZXRBdXRoUXVlcnlQYXJhbXNGb3JXZWJzb2NrZXRDb25uZWN0aW9uKCk7XG4gICAgY29uc3QgcHJvdG9jb2wgPSB3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwOicgPyAnd3MnIDogJ3dzcyc7XG4gICAgY29uc3QgcGF0aE5hbWUgPVxuICAgICAgYCR7cHJvdG9jb2x9Oi8vJHt3aW5kb3cubG9jYXRpb24uaG9zdH0ke3RoaXMuYmFzZVVybH0vY2xpZW50LyR7ZGV2aWNlSWR9L2NvbmZpZ3VyYXRpb25zLyR7Y29uZmlndXJhdGlvbklkfWAgYXMgY29uc3Q7XG4gICAgcmV0dXJuIGF1dGhRdWVyeVBhcmFtcyA/IChgJHtwYXRoTmFtZX0/JHthdXRoUXVlcnlQYXJhbXN9YCBhcyBjb25zdCkgOiBwYXRoTmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYWxsIGNvbmZpZ3VyYXRpb25zIGZvciBhIGdpdmVuIGRldmljZS5cbiAgICovXG4gIGFzeW5jIGxpc3RDb25maWd1cmF0aW9ucyhkZXZpY2VJZDogc3RyaW5nKTogUHJvbWlzZTxSZW1vdGVBY2Nlc3NDb25maWd1cmF0aW9uW10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZmV0Y2hDbGllbnQuZmV0Y2goXG4gICAgICBgJHt0aGlzLmJhc2VVcmx9L2RldmljZXMvJHtkZXZpY2VJZH0vY29uZmlndXJhdGlvbnNgXG4gICAgKTtcbiAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggY29uZmlndXJhdGlvbnMgZm9yIGRldmljZSAke2RldmljZUlkfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgYSBjb25maWd1cmF0aW9uIGZvciBhIGdpdmVuIGRldmljZS5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUNvbmZpZ3VyYXRpb24oZGV2aWNlSWQ6IHN0cmluZywgY29uZmlndXJhdGlvbklkOiBzdHJpbmcpIHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZmV0Y2hDbGllbnQuZmV0Y2goXG4gICAgICBgJHt0aGlzLmJhc2VVcmx9L2RldmljZXMvJHtkZXZpY2VJZH0vY29uZmlndXJhdGlvbnMvJHtjb25maWd1cmF0aW9uSWR9YCxcbiAgICAgIHsgbWV0aG9kOiAnREVMRVRFJyB9XG4gICAgKTtcblxuICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGRlbGV0ZSBjb25maWd1cmF0aW9uIGZvciBkZXZpY2UgJHtkZXZpY2VJZH1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYWxsIGF2YWlsYWJsZSByZW1vdGUgYWNjZXNzIHByb3RvY29sIHByb3ZpZGVycy5cbiAgICovXG4gIGdldFByb3RvY29sUHJvdmlkZXJzKCkge1xuICAgIHJldHVybiB0aGlzLnNlcnZpY2VSZWdpc3RyeS5nZXQoJ3JlbW90ZUFjY2Vzc1Byb3RvY29sSG9vaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY29uZmlndXJhdGlvbiBmb3IgYSBnaXZlbiBkZXZpY2UuXG4gICAqL1xuICBhc3luYyBhZGRDb25maWd1cmF0aW9uKFxuICAgIGRldmljZUlkOiBzdHJpbmcsXG4gICAgY29uZmlndXJhdGlvbjogT21pdDxSZW1vdGVBY2Nlc3NDb25maWd1cmF0aW9uLCAnaWQnPlxuICApOiBQcm9taXNlPFJlbW90ZUFjY2Vzc0NvbmZpZ3VyYXRpb24+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZmV0Y2hDbGllbnQuZmV0Y2goXG4gICAgICBgJHt0aGlzLmJhc2VVcmx9L2RldmljZXMvJHtkZXZpY2VJZH0vY29uZmlndXJhdGlvbnNgLFxuICAgICAge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoY29uZmlndXJhdGlvbilcbiAgICAgIH1cbiAgICApO1xuXG4gICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGFkZCBjb25maWd1cmF0aW9uIGZvciBkZXZpY2UgJHtjb25maWd1cmF0aW9uLmF0dHJzLmRldmljZUlkfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgYSBjb25maWd1cmF0aW9uIGZvciBhIGdpdmVuIGRldmljZS5cbiAgICovXG4gIGFzeW5jIHVwZGF0ZUNvbmZpZ3VyYXRpb24oXG4gICAgZGV2aWNlSWQ6IHN0cmluZyxcbiAgICBjb25maWd1cmF0aW9uOiBSZW1vdGVBY2Nlc3NDb25maWd1cmF0aW9uXG4gICk6IFByb21pc2U8UmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbj4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaENsaWVudC5mZXRjaChcbiAgICAgIGAke3RoaXMuYmFzZVVybH0vZGV2aWNlcy8ke2RldmljZUlkfS9jb25maWd1cmF0aW9ucy8ke2NvbmZpZ3VyYXRpb24uaWR9YCxcbiAgICAgIHtcbiAgICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoY29uZmlndXJhdGlvbilcbiAgICAgIH1cbiAgICApO1xuXG4gICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHVwZGF0ZSBjb25maWd1cmF0aW9uIGZvciBkZXZpY2UgJHtjb25maWd1cmF0aW9uLmF0dHJzLmRldmljZUlkfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhIFNTSCBrZXkgcGFpciBmb3IgYSBnaXZlbiBob3N0bmFtZS5cbiAgICovXG4gIGFzeW5jIGdlbmVyYXRlS2V5UGFpcihob3N0bmFtZTogc3RyaW5nKTogUHJvbWlzZTx7IHB1YmxpY0tleTogc3RyaW5nOyBwcml2YXRlS2V5OiBzdHJpbmcgfT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaENsaWVudC5mZXRjaChgJHt0aGlzLmJhc2VVcmx9L2tleXBhaXIvZ2VuZXJhdGVgLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJ1xuICAgICAgfSxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgaG9zdG5hbWUgfSlcbiAgICB9KTtcblxuICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBnZW5lcmF0ZSBrZXkgcGFpciBmb3IgJHtob3N0bmFtZX1gKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGVhbHRoRW5kcG9pbnRBdmFpbGFibGUoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaENsaWVudC5mZXRjaChgJHt0aGlzLmJhc2VVcmx9L2hlYWx0aGAsIHtcbiAgICAgICAgbWV0aG9kOiAnSEVBRCcsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgcmV0dXJuICEhcmVzcG9uc2Uub2s7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxufVxuIl19