@alfresco/adf-content-services
Version:
Alfresco ADF content services
299 lines • 43.7 kB
JavaScript
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { TranslationService } from '@alfresco/adf-core';
import { NodesApiService } from '../../common/services/nodes-api.service';
import { EcmUserModel } from '../../common/models/ecm-user.model';
import { GroupsApi } from '@alfresco/js-api';
import { SearchService } from '../../search/services/search.service';
import { Injectable } from '@angular/core';
import { forkJoin, from, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { PermissionDisplayModel } from '../models/permission.model';
import * as i0 from "@angular/core";
import * as i1 from "../../services/alfresco-api.service";
import * as i2 from "../../search/services/search.service";
import * as i3 from "../../common/services/nodes-api.service";
import * as i4 from "@alfresco/adf-core";
export class NodePermissionService {
get groupsApi() {
this._groupsApi = this._groupsApi ?? new GroupsApi(this.apiService.getInstance());
return this._groupsApi;
}
constructor(apiService, searchApiService, nodeService, translation) {
this.apiService = apiService;
this.searchApiService = searchApiService;
this.nodeService = nodeService;
this.translation = translation;
}
/**
* Gets a list of roles for the current node.
*
* @param node The target node
* @returns Array of strings representing the roles
*/
getNodeRoles(node) {
if (node.path.elements.some((el) => el.nodeType === 'st:site' || el.nodeType === 'st:sites')) {
const searchRequest = this.buildRetrieveSiteQueryBody(node.path.elements);
return this.searchApiService.searchByQueryBody(searchRequest).pipe(switchMap((siteNodeList) => {
const siteName = siteNodeList.list.entries[0].entry.name;
return this.getGroupMembersBySiteName(siteName);
}));
}
else {
return of(node.permissions?.settable);
}
}
/**
* Get permissions for a given node
*
* @param node Node to check permissions for
* @returns list of permission models
*/
getNodePermissions(node) {
const result = [];
if (node?.permissions?.locallySet) {
node.permissions.locallySet.map((permissionElement) => {
result.push(new PermissionDisplayModel(permissionElement));
});
}
if (node?.permissions?.inherited) {
node.permissions.inherited.map((permissionElement) => {
const permissionInherited = new PermissionDisplayModel(permissionElement);
permissionInherited.isInherited = true;
result.push(permissionInherited);
});
}
return result;
}
/**
* Updates the permission role for a node.
*
* @param node Target node
* @param updatedPermissionRole Permission role to update or add
* @returns Node with updated permission
*/
updatePermissionRole(node, updatedPermissionRole) {
const permissionBody = { permissions: { locallySet: [] } };
const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(updatedPermissionRole.authorityId);
permissionBody.permissions.locallySet = permissionBody.permissions.locallySet.concat(node.permissions.locallySet);
if (index !== -1) {
permissionBody.permissions.locallySet[index] = updatedPermissionRole;
}
else {
permissionBody.permissions.locallySet.push(updatedPermissionRole);
}
return this.nodeService.updateNode(node.id, permissionBody);
}
/**
* Update permissions for a node.
*
* @param nodeId ID of the target node
* @param permissionList New permission settings
* @returns Node with updated permissions
*/
updateNodePermissions(nodeId, permissionList) {
return this.nodeService.getNode(nodeId).pipe(switchMap((node) => this.updateLocallySetPermissions(node, permissionList)));
}
/**
* Updates the locally set permissions for a node.
*
* @param node ID of the target node
* @param permissions Permission settings
* @returns Node with updated permissions
*/
updateLocallySetPermissions(node, permissions) {
const permissionBody = { permissions: { locallySet: [] } };
const permissionList = permissions;
const duplicatedPermissions = this.getDuplicatedPermissions(node.permissions.locallySet, permissionList);
if (duplicatedPermissions.length > 0) {
const list = duplicatedPermissions
.map((permission) => 'authority -> ' + permission.authorityId + ' / role -> ' + permission.name)
.join(', ');
const duplicatePermissionMessage = this.translation.instant('PERMISSION_MANAGER.ERROR.DUPLICATE-PERMISSION', { list });
return throwError(duplicatePermissionMessage);
}
permissionBody.permissions.locallySet = node.permissions.locallySet ? node.permissions.locallySet.concat(permissionList) : permissionList;
return this.nodeService.updateNode(node.id, permissionBody);
}
getDuplicatedPermissions(nodeLocallySet, permissionListAdded) {
const duplicatePermissions = [];
if (nodeLocallySet) {
permissionListAdded.forEach((permission) => {
const duplicate = nodeLocallySet.find((localPermission) => this.isEqualPermission(localPermission, permission));
if (duplicate) {
duplicatePermissions.push(duplicate);
}
});
}
return duplicatePermissions;
}
isEqualPermission(oldPermission, newPermission) {
return (oldPermission.accessStatus === newPermission.accessStatus &&
oldPermission.authorityId === newPermission.authorityId &&
oldPermission.name === newPermission.name);
}
/**
* Removes a permission setting from a node.
*
* @param node ID of the target node
* @param permissionToRemove Permission setting to remove
* @returns Node with modified permissions
*/
removePermission(node, permissionToRemove) {
const permissionBody = { permissions: { locallySet: [] } };
const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(permissionToRemove.authorityId);
if (index !== -1) {
node.permissions.locallySet.splice(index, 1);
permissionBody.permissions.locallySet = node.permissions.locallySet;
return this.nodeService.updateNode(node.id, permissionBody);
}
else {
return of(node);
}
}
getGroupMembersBySiteName(siteName) {
const groupName = 'GROUP_site_' + siteName;
return this.getGroupMemberByGroupName(groupName).pipe(map((groupMemberPaging) => {
const displayResult = [];
groupMemberPaging.list.entries.forEach((member) => {
displayResult.push(this.formattedRoleName(member.entry.displayName, 'site_' + siteName));
});
return displayResult;
}));
}
/**
* Gets all members related to a group name.
*
* @param groupName Name of group to look for members
* @param opts Extra options supported by JS-API
* @returns List of members
*/
getGroupMemberByGroupName(groupName, opts) {
return from(this.groupsApi.listGroupMemberships(groupName, opts));
}
formattedRoleName(displayName, siteName) {
return displayName.replace(siteName + '_', '');
}
buildRetrieveSiteQueryBody(nodePath) {
const pathNames = nodePath.map((node) => 'name: "' + node.name + '"');
const builtPathNames = pathNames.join(' OR ');
return {
query: {
query: builtPathNames
},
paging: {
maxItems: 100,
skipCount: 0
},
include: ['aspectNames', 'properties'],
filterQueries: [
{
query: `TYPE:'st:site'`
}
]
};
}
getLocalPermissions(node) {
const result = [];
if (node?.permissions?.locallySet) {
node.permissions.locallySet.forEach((permissionElement) => {
result.push(new PermissionDisplayModel(permissionElement));
});
}
return result;
}
getInheritedPermission(node) {
const result = [];
if (node?.permissions?.inherited) {
node.permissions.inherited.forEach((permissionElement) => {
const permissionInherited = new PermissionDisplayModel(permissionElement);
permissionInherited.isInherited = true;
result.push(permissionInherited);
});
}
return result;
}
/**
* Removes permissions setting from a node.
*
* @param node target node with permission
* @param permissions Permissions to remove
* @returns Node with modified permissions
*/
removePermissions(node, permissions) {
const permissionBody = { permissions: { locallySet: [] } };
permissions.forEach((permission) => {
const index = node.permissions.locallySet.findIndex((locallySet) => locallySet.authorityId === permission.authorityId);
if (index !== -1) {
node.permissions.locallySet.splice(index, 1);
}
});
permissionBody.permissions.locallySet = node.permissions.locallySet;
return this.nodeService.updateNode(node.id, permissionBody);
}
/**
* updates permissions setting from a node.
*
* @param node target node with permission
* @param permissions Permissions to update
* @returns Node with modified permissions
*/
updatePermissions(node, permissions) {
const permissionBody = { permissions: { locallySet: [] } };
permissionBody.permissions.locallySet = permissions;
return this.nodeService.updateNode(node.id, permissionBody);
}
/**
* Gets all node detail for nodeId along with settable permissions.
*
* @param nodeId Id of the node
* @returns node and it's associated roles { node: Node; roles: RoleModel[] }
*/
getNodeWithRoles(nodeId) {
return this.nodeService.getNode(nodeId).pipe(switchMap((node) => forkJoin({
node: of(node),
roles: this.getNodeRoles(node).pipe(catchError(() => of(node.permissions?.settable)), map((_roles) => _roles.map((role) => ({ role, label: role }))))
})));
}
transformNodeToUserPerson(node) {
let person = null;
let group = null;
if (node.nodeType === 'cm:person') {
const firstName = node.properties['cm:firstName'];
const lastName = node.properties['cm:lastName'];
const email = node.properties['cm:email'];
const id = node.properties['cm:userName'];
person = new EcmUserModel({ id, firstName, lastName, email });
}
if (node.nodeType === 'cm:authorityContainer') {
const displayName = node.properties['cm:authorityDisplayName'] || node.properties['cm:authorityName'];
const id = node.properties['cm:authorityName'];
group = { displayName, id };
}
return { person, group };
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NodePermissionService, deps: [{ token: i1.AlfrescoApiService }, { token: i2.SearchService }, { token: i3.NodesApiService }, { token: i4.TranslationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NodePermissionService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: NodePermissionService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.AlfrescoApiService }, { type: i2.SearchService }, { type: i3.NodesApiService }, { type: i4.TranslationService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1wZXJtaXNzaW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL3Blcm1pc3Npb24tbWFuYWdlci9zZXJ2aWNlcy9ub2RlLXBlcm1pc3Npb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUN6RSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ2xFLE9BQU8sRUFBNEIsU0FBUyxFQUF1RCxNQUFNLGtCQUFrQixDQUFDO0FBQzVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFjLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7OztBQU1wRSxNQUFNLE9BQU8scUJBQXFCO0lBRTlCLElBQUksU0FBUztRQUNULElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDbEYsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQzNCLENBQUM7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QUFDO1FBQ2hDLENBQUM7UUFDRCxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQzdCLENBQUM7OEdBeFNRLHFCQUFxQjtrSEFBckIscUJBQXFCLGNBRmxCLE1BQU07OzJGQUVULHFCQUFxQjtrQkFIakMsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgwqkgMjAwNS0yMDI1IEh5bGFuZCBTb2Z0d2FyZSwgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEFsZnJlc2NvQXBpU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FsZnJlc2NvLWFwaS5zZXJ2aWNlJztcbmltcG9ydCB7IFRyYW5zbGF0aW9uU2VydmljZSB9IGZyb20gJ0BhbGZyZXNjby9hZGYtY29yZSc7XG5pbXBvcnQgeyBOb2Rlc0FwaVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb21tb24vc2VydmljZXMvbm9kZXMtYXBpLnNlcnZpY2UnO1xuaW1wb3J0IHsgRWNtVXNlck1vZGVsIH0gZnJvbSAnLi4vLi4vY29tbW9uL21vZGVscy9lY20tdXNlci5tb2RlbCc7XG5pbXBvcnQgeyBHcm91cCwgR3JvdXBNZW1iZXJQYWdpbmcsIEdyb3Vwc0FwaSwgTm9kZSwgUGF0aEVsZW1lbnQsIFBlcm1pc3Npb25FbGVtZW50LCBTZWFyY2hSZXF1ZXN0IH0gZnJvbSAnQGFsZnJlc2NvL2pzLWFwaSc7XG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VhcmNoL3NlcnZpY2VzL3NlYXJjaC5zZXJ2aWNlJztcbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGZvcmtKb2luLCBmcm9tLCBPYnNlcnZhYmxlLCBvZiwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgbWFwLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBQZXJtaXNzaW9uRGlzcGxheU1vZGVsIH0gZnJvbSAnLi4vbW9kZWxzL3Blcm1pc3Npb24ubW9kZWwnO1xuaW1wb3J0IHsgUm9sZU1vZGVsIH0gZnJvbSAnLi4vbW9kZWxzL3JvbGUubW9kZWwnO1xuXG5ASW5qZWN0YWJsZSh7XG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIE5vZGVQZXJtaXNzaW9uU2VydmljZSB7XG4gICAgcHJpdmF0ZSBfZ3JvdXBzQXBpOiBHcm91cHNBcGk7XG4gICAgZ2V0IGdyb3Vwc0FwaSgpOiBHcm91cHNBcGkge1xuICAgICAgICB0aGlzLl9ncm91cHNBcGkgPSB0aGlzLl9ncm91cHNBcGkgPz8gbmV3IEdyb3Vwc0FwaSh0aGlzLmFwaVNlcnZpY2UuZ2V0SW5zdGFuY2UoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9ncm91cHNBcGk7XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgYXBpU2VydmljZTogQWxmcmVzY29BcGlTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHNlYXJjaEFwaVNlcnZpY2U6IFNlYXJjaFNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgbm9kZVNlcnZpY2U6IE5vZGVzQXBpU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGlvbjogVHJhbnNsYXRpb25TZXJ2aWNlXG4gICAgKSB7fVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGxpc3Qgb2Ygcm9sZXMgZm9yIHRoZSBjdXJyZW50IG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgdGFyZ2V0IG5vZGVcbiAgICAgKiBAcmV0dXJucyBBcnJheSBvZiBzdHJpbmdzIHJlcHJlc2VudGluZyB0aGUgcm9sZXNcbiAgICAgKi9cbiAgICBnZXROb2RlUm9sZXMobm9kZTogTm9kZSk6IE9ic2VydmFibGU8c3RyaW5nW10+IHtcbiAgICAgICAgaWYgKG5vZGUucGF0aC5lbGVtZW50cy5zb21lKChlbCkgPT4gZWwubm9kZVR5cGUgPT09ICdzdDpzaXRlJyB8fCBlbC5ub2RlVHlwZSA9PT0gJ3N0OnNpdGVzJykpIHtcbiAgICAgICAgICAgIGNvbnN0IHNlYXJjaFJlcXVlc3QgPSB0aGlzLmJ1aWxkUmV0cmlldmVTaXRlUXVlcnlCb2R5KG5vZGUucGF0aC5lbGVtZW50cyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZWFyY2hBcGlTZXJ2aWNlLnNlYXJjaEJ5UXVlcnlCb2R5KHNlYXJjaFJlcXVlc3QpLnBpcGUoXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKChzaXRlTm9kZUxpc3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2l0ZU5hbWUgPSBzaXRlTm9kZUxpc3QubGlzdC5lbnRyaWVzWzBdLmVudHJ5Lm5hbWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEdyb3VwTWVtYmVyc0J5U2l0ZU5hbWUoc2l0ZU5hbWUpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG9mKG5vZGUucGVybWlzc2lvbnM/LnNldHRhYmxlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBwZXJtaXNzaW9ucyBmb3IgYSBnaXZlbiBub2RlXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSBOb2RlIHRvIGNoZWNrIHBlcm1pc3Npb25zIGZvclxuICAgICAqIEByZXR1cm5zIGxpc3Qgb2YgcGVybWlzc2lvbiBtb2RlbHNcbiAgICAgKi9cbiAgICBnZXROb2RlUGVybWlzc2lvbnMobm9kZTogTm9kZSk6IFBlcm1pc3Npb25EaXNwbGF5TW9kZWxbXSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdDogUGVybWlzc2lvbkRpc3BsYXlNb2RlbFtdID0gW107XG5cbiAgICAgICAgaWYgKG5vZGU/LnBlcm1pc3Npb25zPy5sb2NhbGx5U2V0KSB7XG4gICAgICAgICAgICBub2RlLnBlcm1pc3Npb25zLmxvY2FsbHlTZXQubWFwKChwZXJtaXNzaW9uRWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBQZXJtaXNzaW9uRGlzcGxheU1vZGVsKHBlcm1pc3Npb25FbGVtZW50KSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChub2RlPy5wZXJtaXNzaW9ucz8uaW5oZXJpdGVkKSB7XG4gICAgICAgICAgICBub2RlLnBlcm1pc3Npb25zLmluaGVyaXRlZC5tYXAoKHBlcm1pc3Npb25FbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGVybWlzc2lvbkluaGVyaXRlZCA9IG5ldyBQZXJtaXNzaW9uRGlzcGxheU1vZGVsKHBlcm1pc3Npb25FbGVtZW50KTtcbiAgICAgICAgICAgICAgICBwZXJtaXNzaW9uSW5oZXJpdGVkLmlzSW5oZXJpdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChwZXJtaXNzaW9uSW5oZXJpdGVkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgcGVybWlzc2lvbiByb2xlIGZvciBhIG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSBUYXJnZXQgbm9kZVxuICAgICAqIEBwYXJhbSB1cGRhdGVkUGVybWlzc2lvblJvbGUgUGVybWlzc2lvbiByb2xlIHRvIHVwZGF0ZSBvciBhZGRcbiAgICAgKiBAcmV0dXJucyBOb2RlIHdpdGggdXBkYXRlZCBwZXJtaXNzaW9uXG4gICAgICovXG4gICAgdXBkYXRlUGVybWlzc2lvblJvbGUobm9kZTogTm9kZSwgdXBkYXRlZFBlcm1pc3Npb25Sb2xlOiBQZXJtaXNzaW9uRWxlbWVudCk6IE9ic2VydmFibGU8Tm9kZT4ge1xuICAgICAgICBjb25zdCBwZXJtaXNzaW9uQm9keSA9IHsgcGVybWlzc2lvbnM6IHsgbG9jYWxseVNldDogW10gfSB9O1xuICAgICAgICBjb25zdCBpbmRleCA9IG5vZGUucGVybWlzc2lvbnMubG9jYWxseVNldC5tYXAoKHBlcm1pc3Npb24pID0+IHBlcm1pc3Npb24uYXV0aG9yaXR5SWQpLmluZGV4T2YodXBkYXRlZFBlcm1pc3Npb25Sb2xlLmF1dGhvcml0eUlkKTtcbiAgICAgICAgcGVybWlzc2lvbkJvZHkucGVybWlzc2lvbnMubG9jYWxseVNldCA9IHBlcm1pc3Npb25Cb2R5LnBlcm1pc3Npb25zLmxvY2FsbHlTZXQuY29uY2F0KG5vZGUucGVybWlzc2lvbnMubG9jYWxseVNldCk7XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHBlcm1pc3Npb25Cb2R5LnBlcm1pc3Npb25zLmxvY2FsbHlTZXRbaW5kZXhdID0gdXBkYXRlZFBlcm1pc3Npb25Sb2xlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVybWlzc2lvbkJvZHkucGVybWlzc2lvbnMubG9jYWxseVNldC5wdXNoKHVwZGF0ZWRQZXJtaXNzaW9uUm9sZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZVNlcnZpY2UudXBkYXRlTm9kZShub2RlLmlkLCBwZXJtaXNzaW9uQm9keSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHBlcm1pc3Npb25zIGZvciBhIG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZUlkIElEIG9mIHRoZSB0YXJnZXQgbm9kZVxuICAgICAqIEBwYXJhbSBwZXJtaXNzaW9uTGlzdCBOZXcgcGVybWlzc2lvbiBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIE5vZGUgd2l0aCB1cGRhdGVkIHBlcm1pc3Npb25zXG4gICAgICovXG4gICAgdXBkYXRlTm9kZVBlcm1pc3Npb25zKG5vZGVJZDogc3RyaW5nLCBwZXJtaXNzaW9uTGlzdDogUGVybWlzc2lvbkVsZW1lbnRbXSk6IE9ic2VydmFibGU8Tm9kZT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5ub2RlU2VydmljZS5nZXROb2RlKG5vZGVJZCkucGlwZShzd2l0Y2hNYXAoKG5vZGUpID0+IHRoaXMudXBkYXRlTG9jYWxseVNldFBlcm1pc3Npb25zKG5vZGUsIHBlcm1pc3Npb25MaXN0KSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIGxvY2FsbHkgc2V0IHBlcm1pc3Npb25zIGZvciBhIG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSBJRCBvZiB0aGUgdGFyZ2V0IG5vZGVcbiAgICAgKiBAcGFyYW0gcGVybWlzc2lvbnMgUGVybWlzc2lvbiBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIE5vZGUgd2l0aCB1cGRhdGVkIHBlcm1pc3Npb25zXG4gICAgICovXG4gICAgdXBkYXRlTG9jYWxseVNldFBlcm1pc3Npb25zKG5vZGU6IE5vZGUsIHBlcm1pc3Npb25zOiBQZXJtaXNzaW9uRWxlbWVudFtdKTogT2JzZXJ2YWJsZTxOb2RlPiB7XG4gICAgICAgIGNvbnN0IHBlcm1pc3Npb25Cb2R5ID0geyBwZXJtaXNzaW9uczogeyBsb2NhbGx5U2V0OiBbXSB9IH07XG4gICAgICAgIGNvbnN0IHBlcm1pc3Npb25MaXN0ID0gcGVybWlzc2lvbnM7XG4gICAgICAgIGNvbnN0IGR1cGxpY2F0ZWRQZXJtaXNzaW9ucyA9IHRoaXMuZ2V0RHVwbGljYXRlZFBlcm1pc3Npb25zKG5vZGUucGVybWlzc2lvbnMubG9jYWxseVNldCwgcGVybWlzc2lvbkxpc3QpO1xuICAgICAgICBpZiAoZHVwbGljYXRlZFBlcm1pc3Npb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGxpc3QgPSBkdXBsaWNhdGVkUGVybWlzc2lvbnNcbiAgICAgICAgICAgICAgICAubWFwKChwZXJtaXNzaW9uKSA9PiAnYXV0aG9yaXR5IC0+ICcgKyBwZXJtaXNzaW9uLmF1dGhvcml0eUlkICsgJyAvIHJvbGUgLT4gJyArIHBlcm1pc3Npb24ubmFtZSlcbiAgICAgICAgICAgICAgICAuam9pbignLCAnKTtcbiAgICAgICAgICAgIGNvbnN0IGR1cGxpY2F0ZVBlcm1pc3Npb25NZXNzYWdlOiBzdHJpbmcgPSB0aGlzLnRyYW5zbGF0aW9uLmluc3RhbnQoJ1BFUk1JU1NJT05fTUFOQUdFUi5FUlJPUi5EVVBMSUNBVEUtUEVSTUlTU0lPTicsIHsgbGlzdCB9KTtcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKGR1cGxpY2F0ZVBlcm1pc3Npb25NZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgICBwZXJtaXNzaW9uQm9keS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0ID0gbm9kZS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0ID8gbm9kZS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0LmNvbmNhdChwZXJtaXNzaW9uTGlzdCkgOiBwZXJtaXNzaW9uTGlzdDtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZVNlcnZpY2UudXBkYXRlTm9kZShub2RlLmlkLCBwZXJtaXNzaW9uQm9keSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXREdXBsaWNhdGVkUGVybWlzc2lvbnMobm9kZUxvY2FsbHlTZXQ6IFBlcm1pc3Npb25FbGVtZW50W10sIHBlcm1pc3Npb25MaXN0QWRkZWQ6IFBlcm1pc3Npb25FbGVtZW50W10pOiBQZXJtaXNzaW9uRWxlbWVudFtdIHtcbiAgICAgICAgY29uc3QgZHVwbGljYXRlUGVybWlzc2lvbnM6IFBlcm1pc3Npb25FbGVtZW50W10gPSBbXTtcbiAgICAgICAgaWYgKG5vZGVMb2NhbGx5U2V0KSB7XG4gICAgICAgICAgICBwZXJtaXNzaW9uTGlzdEFkZGVkLmZvckVhY2goKHBlcm1pc3Npb24pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkdXBsaWNhdGUgPSBub2RlTG9jYWxseVNldC5maW5kKChsb2NhbFBlcm1pc3Npb24pID0+IHRoaXMuaXNFcXVhbFBlcm1pc3Npb24obG9jYWxQZXJtaXNzaW9uLCBwZXJtaXNzaW9uKSk7XG4gICAgICAgICAgICAgICAgaWYgKGR1cGxpY2F0ZSkge1xuICAgICAgICAgICAgICAgICAgICBkdXBsaWNhdGVQZXJtaXNzaW9ucy5wdXNoKGR1cGxpY2F0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZVBlcm1pc3Npb25zO1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNFcXVhbFBlcm1pc3Npb24ob2xkUGVybWlzc2lvbjogUGVybWlzc2lvbkVsZW1lbnQsIG5ld1Blcm1pc3Npb246IFBlcm1pc3Npb25FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBvbGRQZXJtaXNzaW9uLmFjY2Vzc1N0YXR1cyA9PT0gbmV3UGVybWlzc2lvbi5hY2Nlc3NTdGF0dXMgJiZcbiAgICAgICAgICAgIG9sZFBlcm1pc3Npb24uYXV0aG9yaXR5SWQgPT09IG5ld1Blcm1pc3Npb24uYXV0aG9yaXR5SWQgJiZcbiAgICAgICAgICAgIG9sZFBlcm1pc3Npb24ubmFtZSA9PT0gbmV3UGVybWlzc2lvbi5uYW1lXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIHBlcm1pc3Npb24gc2V0dGluZyBmcm9tIGEgbm9kZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBub2RlIElEIG9mIHRoZSB0YXJnZXQgbm9kZVxuICAgICAqIEBwYXJhbSBwZXJtaXNzaW9uVG9SZW1vdmUgUGVybWlzc2lvbiBzZXR0aW5nIHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIE5vZGUgd2l0aCBtb2RpZmllZCBwZXJtaXNzaW9uc1xuICAgICAqL1xuICAgIHJlbW92ZVBlcm1pc3Npb24obm9kZTogTm9kZSwgcGVybWlzc2lvblRvUmVtb3ZlOiBQZXJtaXNzaW9uRWxlbWVudCk6IE9ic2VydmFibGU8Tm9kZT4ge1xuICAgICAgICBjb25zdCBwZXJtaXNzaW9uQm9keSA9IHsgcGVybWlzc2lvbnM6IHsgbG9jYWxseVNldDogW10gfSB9O1xuICAgICAgICBjb25zdCBpbmRleCA9IG5vZGUucGVybWlzc2lvbnMubG9jYWxseVNldC5tYXAoKHBlcm1pc3Npb24pID0+IHBlcm1pc3Npb24uYXV0aG9yaXR5SWQpLmluZGV4T2YocGVybWlzc2lvblRvUmVtb3ZlLmF1dGhvcml0eUlkKTtcblxuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICBub2RlLnBlcm1pc3Npb25zLmxvY2FsbHlTZXQuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIHBlcm1pc3Npb25Cb2R5LnBlcm1pc3Npb25zLmxvY2FsbHlTZXQgPSBub2RlLnBlcm1pc3Npb25zLmxvY2FsbHlTZXQ7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ub2RlU2VydmljZS51cGRhdGVOb2RlKG5vZGUuaWQsIHBlcm1pc3Npb25Cb2R5KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBvZihub2RlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0R3JvdXBNZW1iZXJzQnlTaXRlTmFtZShzaXRlTmFtZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxzdHJpbmdbXT4ge1xuICAgICAgICBjb25zdCBncm91cE5hbWUgPSAnR1JPVVBfc2l0ZV8nICsgc2l0ZU5hbWU7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEdyb3VwTWVtYmVyQnlHcm91cE5hbWUoZ3JvdXBOYW1lKS5waXBlKFxuICAgICAgICAgICAgbWFwKChncm91cE1lbWJlclBhZ2luZykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRpc3BsYXlSZXN1bHQ6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgICAgICAgZ3JvdXBNZW1iZXJQYWdpbmcubGlzdC5lbnRyaWVzLmZvckVhY2goKG1lbWJlcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkaXNwbGF5UmVzdWx0LnB1c2godGhpcy5mb3JtYXR0ZWRSb2xlTmFtZShtZW1iZXIuZW50cnkuZGlzcGxheU5hbWUsICdzaXRlXycgKyBzaXRlTmFtZSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBkaXNwbGF5UmVzdWx0O1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBtZW1iZXJzIHJlbGF0ZWQgdG8gYSBncm91cCBuYW1lLlxuICAgICAqXG4gICAgICogQHBhcmFtIGdyb3VwTmFtZSBOYW1lIG9mIGdyb3VwIHRvIGxvb2sgZm9yIG1lbWJlcnNcbiAgICAgKiBAcGFyYW0gb3B0cyBFeHRyYSBvcHRpb25zIHN1cHBvcnRlZCBieSBKUy1BUElcbiAgICAgKiBAcmV0dXJucyBMaXN0IG9mIG1lbWJlcnNcbiAgICAgKi9cbiAgICBnZXRHcm91cE1lbWJlckJ5R3JvdXBOYW1lKGdyb3VwTmFtZTogc3RyaW5nLCBvcHRzPzogYW55KTogT2JzZXJ2YWJsZTxHcm91cE1lbWJlclBhZ2luZz4ge1xuICAgICAgICByZXR1cm4gZnJvbSh0aGlzLmdyb3Vwc0FwaS5saXN0R3JvdXBNZW1iZXJzaGlwcyhncm91cE5hbWUsIG9wdHMpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZvcm1hdHRlZFJvbGVOYW1lKGRpc3BsYXlOYW1lLCBzaXRlTmFtZSk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBkaXNwbGF5TmFtZS5yZXBsYWNlKHNpdGVOYW1lICsgJ18nLCAnJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBidWlsZFJldHJpZXZlU2l0ZVF1ZXJ5Qm9keShub2RlUGF0aDogUGF0aEVsZW1lbnRbXSk6IFNlYXJjaFJlcXVlc3Qge1xuICAgICAgICBjb25zdCBwYXRoTmFtZXMgPSBub2RlUGF0aC5tYXAoKG5vZGUpID0+ICduYW1lOiBcIicgKyBub2RlLm5hbWUgKyAnXCInKTtcbiAgICAgICAgY29uc3QgYnVpbHRQYXRoTmFtZXMgPSBwYXRoTmFtZXMuam9pbignIE9SICcpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBxdWVyeToge1xuICAgICAgICAgICAgICAgIHF1ZXJ5OiBidWlsdFBhdGhOYW1lc1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhZ2luZzoge1xuICAgICAgICAgICAgICAgIG1heEl0ZW1zOiAxMDAsXG4gICAgICAgICAgICAgICAgc2tpcENvdW50OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW5jbHVkZTogWydhc3BlY3ROYW1lcycsICdwcm9wZXJ0aWVzJ10sXG4gICAgICAgICAgICBmaWx0ZXJRdWVyaWVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeTogYFRZUEU6J3N0OnNpdGUnYFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBnZXRMb2NhbFBlcm1pc3Npb25zKG5vZGU6IE5vZGUpOiBQZXJtaXNzaW9uRGlzcGxheU1vZGVsW10ge1xuICAgICAgICBjb25zdCByZXN1bHQ6IFBlcm1pc3Npb25EaXNwbGF5TW9kZWxbXSA9IFtdO1xuXG4gICAgICAgIGlmIChub2RlPy5wZXJtaXNzaW9ucz8ubG9jYWxseVNldCkge1xuICAgICAgICAgICAgbm9kZS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0LmZvckVhY2goKHBlcm1pc3Npb25FbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gobmV3IFBlcm1pc3Npb25EaXNwbGF5TW9kZWwocGVybWlzc2lvbkVsZW1lbnQpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBnZXRJbmhlcml0ZWRQZXJtaXNzaW9uKG5vZGU6IE5vZGUpOiBQZXJtaXNzaW9uRGlzcGxheU1vZGVsW10ge1xuICAgICAgICBjb25zdCByZXN1bHQ6IFBlcm1pc3Npb25EaXNwbGF5TW9kZWxbXSA9IFtdO1xuXG4gICAgICAgIGlmIChub2RlPy5wZXJtaXNzaW9ucz8uaW5oZXJpdGVkKSB7XG4gICAgICAgICAgICBub2RlLnBlcm1pc3Npb25zLmluaGVyaXRlZC5mb3JFYWNoKChwZXJtaXNzaW9uRWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBlcm1pc3Npb25Jbmhlcml0ZWQgPSBuZXcgUGVybWlzc2lvbkRpc3BsYXlNb2RlbChwZXJtaXNzaW9uRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgcGVybWlzc2lvbkluaGVyaXRlZC5pc0luaGVyaXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gocGVybWlzc2lvbkluaGVyaXRlZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgcGVybWlzc2lvbnMgc2V0dGluZyBmcm9tIGEgbm9kZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBub2RlIHRhcmdldCBub2RlIHdpdGggcGVybWlzc2lvblxuICAgICAqIEBwYXJhbSBwZXJtaXNzaW9ucyBQZXJtaXNzaW9ucyB0byByZW1vdmVcbiAgICAgKiBAcmV0dXJucyBOb2RlIHdpdGggbW9kaWZpZWQgcGVybWlzc2lvbnNcbiAgICAgKi9cbiAgICByZW1vdmVQZXJtaXNzaW9ucyhub2RlOiBOb2RlLCBwZXJtaXNzaW9uczogUGVybWlzc2lvbkVsZW1lbnRbXSk6IE9ic2VydmFibGU8Tm9kZT4ge1xuICAgICAgICBjb25zdCBwZXJtaXNzaW9uQm9keSA9IHsgcGVybWlzc2lvbnM6IHsgbG9jYWxseVNldDogW10gfSB9O1xuXG4gICAgICAgIHBlcm1pc3Npb25zLmZvckVhY2goKHBlcm1pc3Npb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gbm9kZS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0LmZpbmRJbmRleCgobG9jYWxseVNldCkgPT4gbG9jYWxseVNldC5hdXRob3JpdHlJZCA9PT0gcGVybWlzc2lvbi5hdXRob3JpdHlJZCk7XG4gICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0LnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBwZXJtaXNzaW9uQm9keS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0ID0gbm9kZS5wZXJtaXNzaW9ucy5sb2NhbGx5U2V0O1xuICAgICAgICByZXR1cm4gdGhpcy5ub2RlU2VydmljZS51cGRhdGVOb2RlKG5vZGUuaWQsIHBlcm1pc3Npb25Cb2R5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiB1cGRhdGVzIHBlcm1pc3Npb25zIHNldHRpbmcgZnJvbSBhIG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSB0YXJnZXQgbm9kZSB3aXRoIHBlcm1pc3Npb25cbiAgICAgKiBAcGFyYW0gcGVybWlzc2lvbnMgUGVybWlzc2lvbnMgdG8gdXBkYXRlXG4gICAgICogQHJldHVybnMgTm9kZSB3aXRoIG1vZGlmaWVkIHBlcm1pc3Npb25zXG4gICAgICovXG4gICAgdXBkYXRlUGVybWlzc2lvbnMobm9kZTogTm9kZSwgcGVybWlzc2lvbnM6IFBlcm1pc3Npb25FbGVtZW50W10pOiBPYnNlcnZhYmxlPE5vZGU+IHtcbiAgICAgICAgY29uc3QgcGVybWlzc2lvbkJvZHkgPSB7IHBlcm1pc3Npb25zOiB7IGxvY2FsbHlTZXQ6IFtdIH0gfTtcbiAgICAgICAgcGVybWlzc2lvbkJvZHkucGVybWlzc2lvbnMubG9jYWxseVNldCA9IHBlcm1pc3Npb25zO1xuICAgICAgICByZXR1cm4gdGhpcy5ub2RlU2VydmljZS51cGRhdGVOb2RlKG5vZGUuaWQsIHBlcm1pc3Npb25Cb2R5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBub2RlIGRldGFpbCBmb3Igbm9kZUlkIGFsb25nIHdpdGggc2V0dGFibGUgcGVybWlzc2lvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZUlkIElkIG9mIHRoZSBub2RlXG4gICAgICogQHJldHVybnMgbm9kZSBhbmQgaXQncyBhc3NvY2lhdGVkIHJvbGVzIHsgbm9kZTogTm9kZTsgcm9sZXM6IFJvbGVNb2RlbFtdIH1cbiAgICAgKi9cbiAgICBnZXROb2RlV2l0aFJvbGVzKG5vZGVJZDogc3RyaW5nKTogT2JzZXJ2YWJsZTx7IG5vZGU6IE5vZGU7IHJvbGVzOiBSb2xlTW9kZWxbXSB9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLm5vZGVTZXJ2aWNlLmdldE5vZGUobm9kZUlkKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChub2RlKSA9PlxuICAgICAgICAgICAgICAgIGZvcmtKb2luKHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZTogb2Yobm9kZSksXG4gICAgICAgICAgICAgICAgICAgIHJvbGVzOiB0aGlzLmdldE5vZGVSb2xlcyhub2RlKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBvZihub2RlLnBlcm1pc3Npb25zPy5zZXR0YWJsZSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChfcm9sZXMpID0+IF9yb2xlcy5tYXAoKHJvbGUpID0+ICh7IHJvbGUsIGxhYmVsOiByb2xlIH0pKSlcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdHJhbnNmb3JtTm9kZVRvVXNlclBlcnNvbihub2RlOiBOb2RlKTogeyBwZXJzb246IEVjbVVzZXJNb2RlbDsgZ3JvdXA6IEdyb3VwIH0ge1xuICAgICAgICBsZXQgcGVyc29uID0gbnVsbDtcbiAgICAgICAgbGV0IGdyb3VwOiBHcm91cCA9IG51bGw7XG4gICAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAnY206cGVyc29uJykge1xuICAgICAgICAgICAgY29uc3QgZmlyc3ROYW1lID0gbm9kZS5wcm9wZXJ0aWVzWydjbTpmaXJzdE5hbWUnXTtcbiAgICAgICAgICAgIGNvbnN0IGxhc3ROYW1lID0gbm9kZS5wcm9wZXJ0aWVzWydjbTpsYXN0TmFtZSddO1xuICAgICAgICAgICAgY29uc3QgZW1haWwgPSBub2RlLnByb3BlcnRpZXNbJ2NtOmVtYWlsJ107XG4gICAgICAgICAgICBjb25zdCBpZCA9IG5vZGUucHJvcGVydGllc1snY206dXNlck5hbWUnXTtcbiAgICAgICAgICAgIHBlcnNvbiA9IG5ldyBFY21Vc2VyTW9kZWwoeyBpZCwgZmlyc3ROYW1lLCBsYXN0TmFtZSwgZW1haWwgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gJ2NtOmF1dGhvcml0eUNvbnRhaW5lcicpIHtcbiAgICAgICAgICAgIGNvbnN0IGRpc3BsYXlOYW1lID0gbm9kZS5wcm9wZXJ0aWVzWydjbTphdXRob3JpdHlEaXNwbGF5TmFtZSddIHx8IG5vZGUucHJvcGVydGllc1snY206YXV0aG9yaXR5TmFtZSddO1xuICAgICAgICAgICAgY29uc3QgaWQgPSBub2RlLnByb3BlcnRpZXNbJ2NtOmF1dGhvcml0eU5hbWUnXTtcbiAgICAgICAgICAgIGdyb3VwID0geyBkaXNwbGF5TmFtZSwgaWQgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBwZXJzb24sIGdyb3VwIH07XG4gICAgfVxufVxuIl19