UNPKG

@alfresco/adf-content-services

Version:
299 lines 43.7 kB
/*! * @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