angular-firebase-authorizator
Version:
Beta version of authorizator for angular linked to firebase, it creates a model in firestore to assign permissions to users an roles, and creates a view to update this permissions
522 lines • 78.8 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, ActivatedRoute } from '@angular/router';
import { Observable, of } from 'rxjs';
import { Operation } from '../classes/permission-obj';
import { take, map, catchError } from 'rxjs/operators';
var AuthGuard = /** @class */ (function () {
function AuthGuard(router, authorizatorservice) {
this.router = router;
this.authorizatorservice = authorizatorservice;
}
AuthGuard.prototype.isAuthorized = function (rootFirebasePath, resource) {
var _this = this;
return new Observable(function (observer) {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
if (resource) {
Promise.all([
_this.authorizatorservice.getUser(rootFirebasePath, user.email),
_this.authorizatorservice.getRolesByUser(rootFirebasePath, user.email)
]).then(function (values) {
var userDB = values[0];
var rolesDB = values[1] || [];
var resourcePermissionsByUser = [];
var resourcePermissionsByRoles = [];
if (userDB && userDB.data.permissions) {
userDB.data.permissions.filter(function (permission) { return permission.resource === resource || permission.resource === 'owner'; }).forEach(function (permission) {
resourcePermissionsByUser.push(permission);
});
}
rolesDB.forEach(function (rolDB) {
if (rolDB.data.permissions) {
rolDB.data.permissions.filter(function (permission) { return permission.resource === resource; }).forEach(function (permission) {
resourcePermissionsByRoles.push(permission);
});
}
});
if (resourcePermissionsByUser && resourcePermissionsByUser.length > 0 &&
resourcePermissionsByUser.findIndex(function (permission) { return permission.operations && permission.operations.findIndex(function (operation) { return operation === Operation.Deny; }) > -1; }) === -1) {
observer.next('authorized');
}
else {
if (resourcePermissionsByRoles && resourcePermissionsByRoles.length > 0 &&
resourcePermissionsByRoles.findIndex(function (permission) { return permission.operations.findIndex(function (operation) { return operation === Operation.Deny; }) > -1; }) === -1) {
observer.next('authorized');
}
else {
console.error('Unauthorized resource');
observer.next('unauthorized');
}
}
}).catch(function (error) {
console.error('Error getting permissions from database');
console.error(error);
observer.next('unauthorized');
});
}
else {
console.error('Resource not received');
observer.next('unauthorized');
}
}
else {
console.error('Unauthenticated user');
observer.next('unauthenticated');
}
}, function (err) {
observer.error(err);
}, function () {
observer.complete();
});
});
};
AuthGuard.prototype.canActivate = function (route, state) {
var _this = this;
var rootFirebasePath = route.data.rootFirebasePath;
var resource = route.data.resource;
var anonymousRoute = route.data.anonymousRoute || '/';
var unauthorizedRoute = route.data.unauthorizedRoute || '/';
var findVariable = rootFirebasePath.indexOf(':');
if (findVariable > -1) {
var variableEnd = rootFirebasePath.indexOf('/', findVariable);
var variableFound_1;
if (variableEnd > -1) {
variableFound_1 = rootFirebasePath.substring(findVariable + 1, variableEnd);
}
else {
variableFound_1 = rootFirebasePath.substring(findVariable + 1);
}
var existsVariable = Object.keys(route.params).findIndex(function (key) { return key === variableFound_1; });
if (existsVariable > -1) {
rootFirebasePath = rootFirebasePath.replace(':' + variableFound_1, route.params[variableFound_1]);
}
}
return this.isAuthorized(rootFirebasePath, resource).pipe(take(1), map(function (isAuth) {
if (isAuth === 'unauthenticated') {
_this.router.navigate([anonymousRoute], { queryParams: { returnUrl: state.url } });
return false;
}
if (isAuth === 'unauthorized') {
_this.router.navigate([unauthorizedRoute], { queryParams: { returnUrl: state.url } });
return false;
}
if (isAuth === 'authorized') {
return true;
}
return false;
}), catchError(function (err) {
console.error('Error getting authenticated user');
console.error(err);
// not resource sended so redirect to unauthorized page with the return url
_this.router.navigate([anonymousRoute], { queryParams: { returnUrl: state.url } });
return of(false);
}));
};
AuthGuard.ctorParameters = function () { return [
{ type: Router },
{ type: AuthorizatorService }
]; };
AuthGuard = __decorate([
Injectable(),
__metadata("design:paramtypes", [Router, AuthorizatorService])
], AuthGuard);
return AuthGuard;
}());
export { AuthGuard };
var AuthorizatorService = /** @class */ (function () {
function AuthorizatorService() {
}
//#region Users
AuthorizatorService.prototype.addUser = function (rootFirebasePath, user) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/users').replace('//', '/');
firestore.collection(path).doc(user.id).get().then(function (userDB) {
if (userDB.exists) {
reject({ key: 'exists', message: 'User already exists' });
}
else {
firestore.collection(path).doc(user.id).set(user.data).then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error adding user' });
});
}
});
});
};
AuthorizatorService.prototype.removeUser = function (rootFirebasePath, userId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/users').replace('//', '/');
firestore.collection(path).doc(userId).delete().then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error removing user' });
});
});
};
AuthorizatorService.prototype.getUser = function (rootFirebasePath, userId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/users').replace('//', '/');
firestore.collection(path).doc(userId).get().then(function (userDB) {
resolve({
id: userDB.id,
data: userDB.data()
});
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getUsers = function (rootFirebasePath) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
if (!rootFirebasePath) {
rootFirebasePath = '';
}
var path = (rootFirebasePath + '/users').replace('//', '/');
firestore.collection(path).get().then(function (usersDB) {
if (usersDB.empty) {
resolve(null);
}
else {
resolve(usersDB.docs.map(function (userDB) {
return {
id: userDB.id,
data: userDB.data()
};
}));
}
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.updateUserPermissions = function (rootFirebasePath, user) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/users').replace('//', '/');
firestore.collection(path).doc(user.id).get().then(function (userDB) {
if (!userDB.exists) {
reject({ key: 'notexists', message: 'User not exists' });
}
else {
firestore.collection(path).doc(user.id).update({ permissions: user.data.permissions }).then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error updating permissions' });
});
}
});
});
};
//#endregion
//#region Resources
AuthorizatorService.prototype.addResource = function (rootFirebasePath, resource) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/resources').replace('//', '/');
firestore.collection(path).add(resource.data).then(function (resourceCreated) {
resolve(resourceCreated.id);
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.removeResource = function (rootFirebasePath, resourceId) {
var _this = this;
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var resourcePath = (rootFirebasePath + '/resources').replace('//', '/');
var usersPath = (rootFirebasePath + '/users').replace('//', '/');
var rolesPath = (rootFirebasePath + '/roles').replace('//', '/');
var resourceRef = firestore.collection(resourcePath).doc(resourceId);
Promise.all([
_this.getUsersByResource(rootFirebasePath, resourceId),
_this.getRolesByResource(rootFirebasePath, resourceId)
]).then(function (values) {
var batch = firestore.batch();
var usersToUpdate = values[0];
var rolesToUpdate = values[1];
usersToUpdate.forEach(function (userToUpdate) {
userToUpdate.data.permissions.splice(userToUpdate.data.permissions.findIndex(function (permission) { return permission.resource === resourceId; }), 1);
var userRef = firestore.collection(usersPath).doc(userToUpdate.id);
batch.update(userRef, { data: userToUpdate.data });
});
rolesToUpdate.forEach(function (roleToUpdate) {
roleToUpdate.data.permissions.splice(roleToUpdate.data.permissions.findIndex(function (permission) { return permission.resource === resourceId; }), 1);
var roleRef = firestore.collection(rolesPath).doc(roleToUpdate.id);
batch.update(roleRef, { data: roleToUpdate.data });
});
batch.delete(resourceRef);
batch.commit().then(function () {
resolve();
}).catch(function (error) {
reject(error);
});
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.updateResource = function (rootFirebasePath, resource) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/resources').replace('//', '/');
firestore.collection(path).doc(resource.id).set(resource.data).then(function () {
resolve();
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getResource = function (rootFirebasePath, resourceId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/resources').replace('//', '/');
firestore.collection(path).doc(resourceId).get().then(function (resourceDB) {
resolve({
id: resourceDB.id,
data: resourceDB.data()
});
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getResources = function (rootFirebasePath) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/resources').replace('//', '/');
firestore.collection(path).get().then(function (resourcesDB) {
if (resourcesDB.empty) {
resolve(null);
}
else {
resolve(resourcesDB.docs.map(function (resourceDB) {
return {
id: resourceDB.id,
data: resourceDB.data()
};
}));
}
}).catch(function (error) {
reject(error);
});
});
};
// endregion
//#region Roles
AuthorizatorService.prototype.addRole = function (rootFirebasePath, role) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).where('name', '==', role.data.name).get().then(function (roleDB) {
if (!roleDB.empty) {
reject({ key: 'exists', message: 'Role already exists' });
}
else {
firestore.collection(path).add(role.data).then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error adding role' });
});
}
});
});
};
AuthorizatorService.prototype.removeRole = function (rootFirebasePath, roleId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).doc(roleId).delete().then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error removing role' });
});
});
};
AuthorizatorService.prototype.updateRole = function (rootFirebasePath, role) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).doc(role.id).set(role.data).then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error updating role' });
});
});
};
AuthorizatorService.prototype.getRole = function (rootFirebasePath, roleId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).doc(roleId).get().then(function (roleDB) {
resolve({
id: roleDB.id,
data: roleDB.data()
});
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getRoles = function (rootFirebasePath) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
if (!rootFirebasePath) {
rootFirebasePath = '';
}
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).get().then(function (rolesDB) {
if (rolesDB.empty) {
resolve(null);
}
else {
resolve(rolesDB.docs.map(function (roleDB) {
return {
id: roleDB.id,
data: roleDB.data()
};
}));
}
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getRolesByResource = function (rootFirebasePath, resourceId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).where('data.resources', 'array-contains', resourceId).get().then(function (rolesDB) {
if (rolesDB.empty) {
resolve(null);
}
else {
resolve(rolesDB.docs.map(function (roleDB) {
return {
id: roleDB.id,
data: roleDB.data()
};
}));
}
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getRolesByUser = function (rootFirebasePath, userId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).where('users', 'array-contains', userId).get().then(function (rolesDB) {
if (rolesDB.empty) {
resolve(null);
}
else {
resolve(rolesDB.docs.map(function (roleDB) {
return {
id: roleDB.id,
data: roleDB.data()
};
}));
}
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.updateRolePermissions = function (rootFirebasePath, role) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
rootFirebasePath = rootFirebasePath || '';
var path = (rootFirebasePath + '/roles').replace('//', '/');
firestore.collection(path).doc(role.id).get().then(function (roleDB) {
if (!roleDB.exists) {
reject({ key: 'notexists', message: 'Role not exists' });
}
else {
firestore.collection(path).doc(role.id).update({ permissions: role.data.permissions }).then(function () {
resolve();
}).catch(function (error) {
console.error(error);
reject({ key: 'defaulterror', message: 'Error updating permissions' });
});
}
});
});
};
// endregion
//#region Roles
AuthorizatorService.prototype.removeUserFromRole = function (rootFirebasePath, userId) {
var _this = this;
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var usersPath = (rootFirebasePath + '/users').replace('//', '/');
var rolesPath = (rootFirebasePath + '/roles').replace('//', '/');
_this.getRolesByUser(rootFirebasePath, userId).then(function (rolesDB) {
var batch = firestore.batch();
var rolesToUpdate = rolesDB;
rolesToUpdate.forEach(function (roleToUpdate) {
roleToUpdate.data.users.splice(roleToUpdate.data.users.findIndex(function (user) { return user === userId; }), 1);
var roleRef = firestore.collection(rolesPath).doc(roleToUpdate.id);
batch.update(roleRef, { data: roleToUpdate.data });
});
var userRef = firestore.collection(usersPath).doc(userId);
batch.delete(userRef);
batch.commit().then(function () {
resolve();
}).catch(function (error) {
reject(error);
});
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService.prototype.getUsersByResource = function (rootFirebasePath, resourceId) {
return new Promise(function (resolve, reject) {
var firestore = firebase.firestore();
var path = (rootFirebasePath + '/users').replace('//', '/');
firestore.collection(path).where('data.resources', 'array-contains', resourceId).get().then(function (usersDB) {
if (usersDB.empty) {
resolve(null);
}
else {
resolve(usersDB.docs.map(function (userDB) {
return {
id: userDB.id,
data: userDB.data()
};
}));
}
}).catch(function (error) {
reject(error);
});
});
};
AuthorizatorService = __decorate([
Injectable(),
__metadata("design:paramtypes", [])
], AuthorizatorService);
return AuthorizatorService;
}());
export { AuthorizatorService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aG9yaXphdG9yLnNlcnZpY2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9hbmd1bGFyLWZpcmViYXNlLWF1dGhvcml6YXRvci8iLCJzb3VyY2VzIjpbImxpYi9zZXJ2aWNlcy9hdXRob3JpemF0b3Iuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEtBQUssUUFBUSxNQUFNLFVBQVUsQ0FBQztBQUdyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxzQkFBc0IsRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuSCxPQUFPLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV0QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEQsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHdkQ7SUFDRSxtQkFBb0IsTUFBYyxFQUFVLG1CQUF3QztRQUFoRSxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQVUsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtJQUFHLENBQUM7SUFFaEYsZ0NBQVksR0FBcEIsVUFBcUIsZ0JBQXdCLEVBQUUsUUFBZ0I7UUFBL0QsaUJBa0VDO1FBakVDLE9BQU8sSUFBSSxVQUFVLENBQUMsVUFBQSxRQUFRO1lBQzVCLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxVQUFBLElBQUk7Z0JBQ3JDLElBQUksSUFBSSxFQUFFO29CQUNSLElBQUksUUFBUSxFQUFFO3dCQUNaLE9BQU8sQ0FBQyxHQUFHLENBQUM7NEJBQ1YsS0FBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDOzRCQUM5RCxLQUFJLENBQUMsbUJBQW1C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QyxJQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdkMsSUFBTSxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzlELFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFBLE9BQU87Z0JBQ2pHLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRTtvQkFDakIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO2lCQUNmO3FCQUFNO29CQUNMLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFBLE1BQU07d0JBQzdCLE9BQU87NEJBQ0wsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFOzRCQUNiLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFO3lCQUNULENBQUM7b0JBQ2YsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDTDtZQUNILENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFBLEtBQUs7Z0JBQ1osTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2hCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBcFpVLG1CQUFtQjtRQUQvQixVQUFVLEVBQUU7O09BQ0EsbUJBQW1CLENBc1ovQjtJQUFELDBCQUFDO0NBQUEsQUF0WkQsSUFzWkM7U0F0WlksbUJBQW1CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVzb3VyY2VPYmogfSBmcm9tICcuLi9jbGFzc2VzL3Jlc291cmNlLW9iaic7XG5pbXBvcnQgKiBhcyBmaXJlYmFzZSBmcm9tICdmaXJlYmFzZSc7XG5pbXBvcnQgeyBSb2xlT2JqIH0gZnJvbSAnLi4vY2xhc3Nlcy9yb2xlLW9iaic7XG5pbXBvcnQgeyBVc2VyT2JqIH0gZnJvbSAnLi4vY2xhc3Nlcy91c2VyLW9iaic7XG5pbXBvcnQgeyBSb3V0ZXIsIENhbkFjdGl2YXRlLCBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCBSb3V0ZXJTdGF0ZVNuYXBzaG90LCBBY3RpdmF0ZWRSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgUGVybWlzc2lvbk9iaiB9IGZyb20gJy4uL2NsYXNzZXMvcGVybWlzc2lvbi1vYmonO1xuaW1wb3J0IHsgT3BlcmF0aW9uIH0gZnJvbSAnLi4vY2xhc3Nlcy9wZXJtaXNzaW9uLW9iaic7XG5pbXBvcnQgeyB0YWtlLCBtYXAsIGNhdGNoRXJyb3IgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdXRoR3VhcmQgaW1wbGVtZW50cyBDYW5BY3RpdmF0ZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsIHByaXZhdGUgYXV0aG9yaXphdG9yc2VydmljZTogQXV0aG9yaXphdG9yU2VydmljZSkge31cblxuICBwcml2YXRlIGlzQXV0aG9yaXplZChyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHJlc291cmNlOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZShvYnNlcnZlciA9PiB7XG4gICAgICBmaXJlYmFzZS5hdXRoKCkub25BdXRoU3RhdGVDaGFuZ2VkKHVzZXIgPT4ge1xuICAgICAgICBpZiAodXNlcikge1xuICAgICAgICAgIGlmIChyZXNvdXJjZSkge1xuICAgICAgICAgICAgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICB0aGlzLmF1dGhvcml6YXRvcnNlcnZpY2UuZ2V0VXNlcihyb290RmlyZWJhc2VQYXRoLCB1c2VyLmVtYWlsKSxcbiAgICAgICAgICAgICAgdGhpcy5hdXRob3JpemF0b3JzZXJ2aWNlLmdldFJvbGVzQnlVc2VyKHJvb3RGaXJlYmFzZVBhdGgsIHVzZXIuZW1haWwpXG4gICAgICAgICAgICBdKS50aGVuKHZhbHVlcyA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHVzZXJEQjogVXNlck9iaiA9IHZhbHVlc1swXTtcbiAgICAgICAgICAgICAgY29uc3Qgcm9sZXNEQjogUm9sZU9ialtdID0gdmFsdWVzWzFdIHx8IFtdO1xuICAgICAgICAgICAgICBjb25zdCByZXNvdXJjZVBlcm1pc3Npb25zQnlVc2VyOiBQZXJtaXNzaW9uT2JqW10gPSBbXTtcbiAgICAgICAgICAgICAgY29uc3QgcmVzb3VyY2VQZXJtaXNzaW9uc0J5Um9sZXM6IFBlcm1pc3Npb25PYmpbXSA9IFtdO1xuICAgICAgICAgICAgICBpZiAodXNlckRCICYmIHVzZXJEQi5kYXRhLnBlcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgdXNlckRCLmRhdGEucGVybWlzc2lvbnMuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgcGVybWlzc2lvbiA9PiBwZXJtaXNzaW9uLnJlc291cmNlID09PSByZXNvdXJjZSB8fCBwZXJtaXNzaW9uLnJlc291cmNlID09PSAnb3duZXInXG4gICAgICAgICAgICAgICAgKS5mb3JFYWNoKHBlcm1pc3Npb24gPT4ge1xuICAgICAgICAgICAgICAgICAgcmVzb3VyY2VQZXJtaXNzaW9uc0J5VXNlci5wdXNoKHBlcm1pc3Npb24pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJvbGVzREIuZm9yRWFjaChyb2xEQiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJvbERCLmRhdGEucGVybWlzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgIHJvbERCLmRhdGEucGVybWlzc2lvbnMuZmlsdGVyKHBlcm1pc3Npb24gPT4gcGVybWlzc2lvbi5yZXNvdXJjZSA9PT0gcmVzb3VyY2UpLmZvckVhY2gocGVybWlzc2lvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc291cmNlUGVybWlzc2lvbnNCeVJvbGVzLnB1c2gocGVybWlzc2lvbik7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBpZiAocmVzb3VyY2VQZXJtaXNzaW9uc0J5VXNlciAmJiByZXNvdXJjZVBlcm1pc3Npb25zQnlVc2VyLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAgICAgICByZXNvdXJjZVBlcm1pc3Npb25zQnlVc2VyLmZpbmRJbmRleChcbiAgICAgICAgICAgICAgICAgIHBlcm1pc3Npb24gPT4gcGVybWlzc2lvbi5vcGVyYXRpb25zICYmIHBlcm1pc3Npb24ub3BlcmF0aW9ucy5maW5kSW5kZXgob3BlcmF0aW9uID0+IG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uLkRlbnkpID4gLTFcbiAgICAgICAgICAgICAgICApID09PSAtMVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoJ2F1dGhvcml6ZWQnKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzb3VyY2VQZXJtaXNzaW9uc0J5Um9sZXMgJiYgcmVzb3VyY2VQZXJtaXNzaW9uc0J5Um9sZXMubGVuZ3RoID4gMCAmJlxuICAgICAgICAgICAgICAgICAgcmVzb3VyY2VQZXJtaXNzaW9uc0J5Um9sZXMuZmluZEluZGV4KFxuICAgICAgICAgICAgICAgICAgICBwZXJtaXNzaW9uID0+IHBlcm1pc3Npb24ub3BlcmF0aW9ucy5maW5kSW5kZXgob3BlcmF0aW9uID0+IG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uLkRlbnkpID4gLTFcbiAgICAgICAgICAgICAgICAgICkgPT09IC0xXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoJ2F1dGhvcml6ZWQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignVW5hdXRob3JpemVkIHJlc291cmNlJyk7XG4gICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KCd1bmF1dGhvcml6ZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyBwZXJtaXNzaW9ucyBmcm9tIGRhdGFiYXNlJyk7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KCd1bmF1dGhvcml6ZWQnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdSZXNvdXJjZSBub3QgcmVjZWl2ZWQnKTtcbiAgICAgICAgICAgIG9ic2VydmVyLm5leHQoJ3VuYXV0aG9yaXplZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdVbmF1dGhlbnRpY2F0ZWQgdXNlcicpO1xuICAgICAgICAgIG9ic2VydmVyLm5leHQoJ3VuYXV0aGVudGljYXRlZCcpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXJyID0+IHtcbiAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyKTtcbiAgICAgIH0sXG4gICAgICAoKSA9PiB7XG4gICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGNhbkFjdGl2YXRlKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCBzdGF0ZTogUm91dGVyU3RhdGVTbmFwc2hvdCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIGxldCByb290RmlyZWJhc2VQYXRoOiBzdHJpbmcgPSByb3V0ZS5kYXRhLnJvb3RGaXJlYmFzZVBhdGg7XG4gICAgY29uc3QgcmVzb3VyY2UgPSByb3V0ZS5kYXRhLnJlc291cmNlO1xuICAgIGNvbnN0IGFub255bW91c1JvdXRlID0gcm91dGUuZGF0YS5hbm9ueW1vdXNSb3V0ZSB8fCAnLyc7XG4gICAgY29uc3QgdW5hdXRob3JpemVkUm91dGUgPSByb3V0ZS5kYXRhLnVuYXV0aG9yaXplZFJvdXRlIHx8ICcvJztcbiAgICBjb25zdCBmaW5kVmFyaWFibGUgPSByb290RmlyZWJhc2VQYXRoLmluZGV4T2YoJzonKTtcbiAgICBpZiAoZmluZFZhcmlhYmxlID4gLTEpIHtcbiAgICAgIGNvbnN0IHZhcmlhYmxlRW5kID0gcm9vdEZpcmViYXNlUGF0aC5pbmRleE9mKCcvJywgZmluZFZhcmlhYmxlKTtcbiAgICAgIGxldCB2YXJpYWJsZUZvdW5kO1xuICAgICAgaWYgKHZhcmlhYmxlRW5kID4gLTEpIHtcbiAgICAgICAgdmFyaWFibGVGb3VuZCA9IHJvb3RGaXJlYmFzZVBhdGguc3Vic3RyaW5nKGZpbmRWYXJpYWJsZSArIDEsIHZhcmlhYmxlRW5kKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhcmlhYmxlRm91bmQgPSByb290RmlyZWJhc2VQYXRoLnN1YnN0cmluZyhmaW5kVmFyaWFibGUgKyAxKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4aXN0c1ZhcmlhYmxlID0gT2JqZWN0LmtleXMocm91dGUucGFyYW1zKS5maW5kSW5kZXgoa2V5ID0+IGtleSA9PT0gdmFyaWFibGVGb3VuZCk7XG4gICAgICBpZiAoZXhpc3RzVmFyaWFibGUgPiAtMSkge1xuICAgICAgICByb290RmlyZWJhc2VQYXRoID0gcm9vdEZpcmViYXNlUGF0aC5yZXBsYWNlKCc6JyArIHZhcmlhYmxlRm91bmQsIHJvdXRlLnBhcmFtc1t2YXJpYWJsZUZvdW5kXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuaXNBdXRob3JpemVkKHJvb3RGaXJlYmFzZVBhdGgsIHJlc291cmNlKS5waXBlKFxuICAgICAgdGFrZSgxKSxcbiAgICAgIG1hcChpc0F1dGggPT4ge1xuICAgICAgICBpZiAoaXNBdXRoID09PSAndW5hdXRoZW50aWNhdGVkJykge1xuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFthbm9ueW1vdXNSb3V0ZV0sIHsgcXVlcnlQYXJhbXM6IHsgcmV0dXJuVXJsOiBzdGF0ZS51cmwgfX0pO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNBdXRoID09PSAndW5hdXRob3JpemVkJykge1xuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFt1bmF1dGhvcml6ZWRSb3V0ZV0sIHsgcXVlcnlQYXJhbXM6IHsgcmV0dXJuVXJsOiBzdGF0ZS51cmwgfX0pO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNBdXRoID09PSAnYXV0aG9yaXplZCcpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKGVycikgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBnZXR0aW5nIGF1dGhlbnRpY2F0ZWQgdXNlcicpO1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgIC8vIG5vdCByZXNvdXJjZSBzZW5kZWQgc28gcmVkaXJlY3QgdG8gdW5hdXRob3JpemVkIHBhZ2Ugd2l0aCB0aGUgcmV0dXJuIHVybFxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYW5vbnltb3VzUm91dGVdLCB7IHF1ZXJ5UGFyYW1zOiB7IHJldHVyblVybDogc3RhdGUudXJsIH19KTtcbiAgICAgICAgcmV0dXJuIG9mKGZhbHNlKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aG9yaXphdG9yU2VydmljZSB7XG5cbiAgY29uc3RydWN0b3IoKSB7IH1cblxuICAvLyNyZWdpb24gVXNlcnNcbiAgYWRkVXNlcihyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHVzZXI6IFVzZXJPYmopOiBQcm9taXNlPG51bGw+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICByb290RmlyZWJhc2VQYXRoID0gcm9vdEZpcmViYXNlUGF0aCB8fCAnJztcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvdXNlcnMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2ModXNlci5pZCkuZ2V0KCkudGhlbih1c2VyREIgPT4ge1xuICAgICAgICBpZiAodXNlckRCLmV4aXN0cykge1xuICAgICAgICAgIHJlamVjdCh7IGtleTogJ2V4aXN0cycsIG1lc3NhZ2U6ICdVc2VyIGFscmVhZHkgZXhpc3RzJyB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2ModXNlci5pZCkuc2V0KHVzZXIuZGF0YSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICByZWplY3QoIHsga2V5OiAnZGVmYXVsdGVycm9yJywgbWVzc2FnZTogJ0Vycm9yIGFkZGluZyB1c2VyJyB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVVc2VyKHJvb3RGaXJlYmFzZVBhdGg6IHN0cmluZywgdXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPG51bGw+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICByb290RmlyZWJhc2VQYXRoID0gcm9vdEZpcmViYXNlUGF0aCB8fCAnJztcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvdXNlcnMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2ModXNlcklkKS5kZWxldGUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgcmVqZWN0KCB7IGtleTogJ2RlZmF1bHRlcnJvcicsIG1lc3NhZ2U6ICdFcnJvciByZW1vdmluZyB1c2VyJyB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0VXNlcihyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxVc2VyT2JqPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGZpcmVzdG9yZSA9IGZpcmViYXNlLmZpcmVzdG9yZSgpO1xuICAgICAgY29uc3QgcGF0aCA9IChyb290RmlyZWJhc2VQYXRoICsgJy91c2VycycpLnJlcGxhY2UoJy8vJywgJy8nKTtcbiAgICAgIGZpcmVzdG9yZS5jb2xsZWN0aW9uKHBhdGgpLmRvYyh1c2VySWQpLmdldCgpLnRoZW4odXNlckRCID0+IHtcbiAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IHVzZXJEQi5pZCxcbiAgICAgICAgICBkYXRhOiB1c2VyREIuZGF0YSgpXG4gICAgICAgIH0gYXMgVXNlck9iaik7XG4gICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldFVzZXJzKHJvb3RGaXJlYmFzZVBhdGg6IHN0cmluZyk6IFByb21pc2U8VXNlck9ialtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGZpcmVzdG9yZSA9IGZpcmViYXNlLmZpcmVzdG9yZSgpO1xuICAgICAgaWYgKCFyb290RmlyZWJhc2VQYXRoKSB7XG4gICAgICAgIHJvb3RGaXJlYmFzZVBhdGggPSAnJztcbiAgICAgIH1cbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvdXNlcnMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5nZXQoKS50aGVuKHVzZXJzREIgPT4ge1xuICAgICAgICBpZiAodXNlcnNEQi5lbXB0eSkge1xuICAgICAgICAgIHJlc29sdmUobnVsbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZSh1c2Vyc0RCLmRvY3MubWFwKHVzZXJEQiA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBpZDogdXNlckRCLmlkLFxuICAgICAgICAgICAgICBkYXRhOiB1c2VyREIuZGF0YSgpXG4gICAgICAgICAgICB9IGFzIFVzZXJPYmo7XG4gICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHVwZGF0ZVVzZXJQZXJtaXNzaW9ucyhyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHVzZXI6IFVzZXJPYmopIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICByb290RmlyZWJhc2VQYXRoID0gcm9vdEZpcmViYXNlUGF0aCB8fCAnJztcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvdXNlcnMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2ModXNlci5pZCkuZ2V0KCkudGhlbih1c2VyREIgPT4ge1xuICAgICAgICBpZiAoIXVzZXJEQi5leGlzdHMpIHtcbiAgICAgICAgICByZWplY3QoeyBrZXk6ICdub3RleGlzdHMnLCBtZXNzYWdlOiAnVXNlciBub3QgZXhpc3RzJyB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2ModXNlci5pZCkudXBkYXRlKFxuICAgICAgICAgICAgeyBwZXJtaXNzaW9uczogdXNlci5kYXRhLnBlcm1pc3Npb25zIH1cbiAgICAgICAgICApLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgcmVqZWN0KCB7IGtleTogJ2RlZmF1bHRlcnJvcicsIG1lc3NhZ2U6ICdFcnJvciB1cGRhdGluZyBwZXJtaXNzaW9ucycgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8vI2VuZHJlZ2lvblxuXG4gIC8vI3JlZ2lvbiBSZXNvdXJjZXNcbiAgYWRkUmVzb3VyY2Uocm9vdEZpcmViYXNlUGF0aDogc3RyaW5nLCByZXNvdXJjZTogUmVzb3VyY2VPYmopOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcmVzb3VyY2VzJykucmVwbGFjZSgnLy8nLCAnLycpO1xuICAgICAgZmlyZXN0b3JlLmNvbGxlY3Rpb24ocGF0aCkuYWRkKHJlc291cmNlLmRhdGEpLnRoZW4ocmVzb3VyY2VDcmVhdGVkID0+IHtcbiAgICAgICAgcmVzb2x2ZShyZXNvdXJjZUNyZWF0ZWQuaWQpO1xuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVSZXNvdXJjZShyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHJlc291cmNlSWQ6IHN0cmluZyk6IFByb21pc2U8bnVsbD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IHJlc291cmNlUGF0aCA9IChyb290RmlyZWJhc2VQYXRoICsgJy9yZXNvdXJjZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBjb25zdCB1c2Vyc1BhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvdXNlcnMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBjb25zdCByb2xlc1BhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcm9sZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBjb25zdCByZXNvdXJjZVJlZiA9IGZpcmVzdG9yZS5jb2xsZWN0aW9uKHJlc291cmNlUGF0aCkuZG9jKHJlc291cmNlSWQpO1xuICAgICAgUHJvbWlzZS5hbGwoW1xuICAgICAgICB0aGlzLmdldFVzZXJzQnlSZXNvdXJjZShyb290RmlyZWJhc2VQYXRoLCByZXNvdXJjZUlkKSxcbiAgICAgICAgdGhpcy5nZXRSb2xlc0J5UmVzb3VyY2Uocm9vdEZpcmViYXNlUGF0aCwgcmVzb3VyY2VJZClcbiAgICAgIF0pLnRoZW4odmFsdWVzID0+IHtcbiAgICAgICAgY29uc3QgYmF0Y2ggPSBmaXJlc3RvcmUuYmF0Y2goKTtcbiAgICAgICAgY29uc3QgdXNlcnNUb1VwZGF0ZTogVXNlck9ialtdID0gdmFsdWVzWzBdO1xuICAgICAgICBjb25zdCByb2xlc1RvVXBkYXRlOiBSb2xlT2JqW10gPSB2YWx1ZXNbMV07XG4gICAgICAgIHVzZXJzVG9VcGRhdGUuZm9yRWFjaCh1c2VyVG9VcGRhdGUgPT4ge1xuICAgICAgICAgIHVzZXJUb1VwZGF0ZS5kYXRhLnBlcm1pc3Npb25zLnNwbGljZShcbiAgICAgICAgICAgIHVzZXJUb1VwZGF0ZS5kYXRhLnBlcm1pc3Npb25zLmZpbmRJbmRleChwZXJtaXNzaW9uID0+IHBlcm1pc3Npb24ucmVzb3VyY2UgPT09IHJlc291cmNlSWQpLCAxXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCB1c2VyUmVmID0gZmlyZXN0b3JlLmNvbGxlY3Rpb24odXNlcnNQYXRoKS5kb2ModXNlclRvVXBkYXRlLmlkKTtcbiAgICAgICAgICBiYXRjaC51cGRhdGUodXNlclJlZiwgeyBkYXRhOiB1c2VyVG9VcGRhdGUuZGF0YSB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJvbGVzVG9VcGRhdGUuZm9yRWFjaChyb2xlVG9VcGRhdGUgPT4ge1xuICAgICAgICAgIHJvbGVUb1VwZGF0ZS5kYXRhLnBlcm1pc3Npb25zLnNwbGljZShcbiAgICAgICAgICAgIHJvbGVUb1VwZGF0ZS5kYXRhLnBlcm1pc3Npb25zLmZpbmRJbmRleChwZXJtaXNzaW9uID0+IHBlcm1pc3Npb24ucmVzb3VyY2UgPT09IHJlc291cmNlSWQpLCAxXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCByb2xlUmVmID0gZmlyZXN0b3JlLmNvbGxlY3Rpb24ocm9sZXNQYXRoKS5kb2Mocm9sZVRvVXBkYXRlLmlkKTtcbiAgICAgICAgICBiYXRjaC51cGRhdGUocm9sZVJlZiwgeyBkYXRhOiByb2xlVG9VcGRhdGUuZGF0YSB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGJhdGNoLmRlbGV0ZShyZXNvdXJjZVJlZik7XG4gICAgICAgIGJhdGNoLmNvbW1pdCgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVSZXNvdXJjZShyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHJlc291cmNlOiBSZXNvdXJjZU9iaik6IFByb21pc2U8bnVsbD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcmVzb3VyY2VzJykucmVwbGFjZSgnLy8nLCAnLycpO1xuICAgICAgZmlyZXN0b3JlLmNvbGxlY3Rpb24ocGF0aCkuZG9jKHJlc291cmNlLmlkKS5zZXQocmVzb3VyY2UuZGF0YSkudGhlbigoKSA9PiB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0UmVzb3VyY2Uocm9vdEZpcmViYXNlUGF0aDogc3RyaW5nLCByZXNvdXJjZUlkOiBzdHJpbmcpOiBQcm9taXNlPFJlc291cmNlT2JqPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGZpcmVzdG9yZSA9IGZpcmViYXNlLmZpcmVzdG9yZSgpO1xuICAgICAgY29uc3QgcGF0aCA9IChyb290RmlyZWJhc2VQYXRoICsgJy9yZXNvdXJjZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2MocmVzb3VyY2VJZCkuZ2V0KCkudGhlbihyZXNvdXJjZURCID0+IHtcbiAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IHJlc291cmNlREIuaWQsXG4gICAgICAgICAgZGF0YTogcmVzb3VyY2VEQi5kYXRhKClcbiAgICAgICAgfSBhcyBSZXNvdXJjZU9iaik7XG4gICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldFJlc291cmNlcyhyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcpOiBQcm9taXNlPFJlc291cmNlT2JqW10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICBjb25zdCBwYXRoID0gKHJvb3RGaXJlYmFzZVBhdGggKyAnL3Jlc291cmNlcycpLnJlcGxhY2UoJy8vJywgJy8nKTtcbiAgICAgIGZpcmVzdG9yZS5jb2xsZWN0aW9uKHBhdGgpLmdldCgpLnRoZW4ocmVzb3VyY2VzREIgPT4ge1xuICAgICAgICBpZiAocmVzb3VyY2VzREIuZW1wdHkpIHtcbiAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocmVzb3VyY2VzREIuZG9jcy5tYXAocmVzb3VyY2VEQiA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBpZDogcmVzb3VyY2VEQi5pZCxcbiAgICAgICAgICAgICAgZGF0YTogcmVzb3VyY2VEQi5kYXRhKClcbiAgICAgICAgICAgIH0gYXMgUmVzb3VyY2VPYmo7XG4gICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvLyBlbmRyZWdpb25cblxuICAvLyNyZWdpb24gUm9sZXNcbiAgYWRkUm9sZShyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHJvbGU6IFJvbGVPYmopOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIHJvb3RGaXJlYmFzZVBhdGggPSByb290RmlyZWJhc2VQYXRoIHx8ICcnO1xuICAgICAgY29uc3QgcGF0aCA9IChyb290RmlyZWJhc2VQYXRoICsgJy9yb2xlcycpLnJlcGxhY2UoJy8vJywgJy8nKTtcbiAgICAgIGZpcmVzdG9yZS5jb2xsZWN0aW9uKHBhdGgpLndoZXJlKCduYW1lJywgJz09Jywgcm9sZS5kYXRhLm5hbWUpLmdldCgpLnRoZW4ocm9sZURCID0+IHtcbiAgICAgICAgaWYgKCFyb2xlREIuZW1wdHkpIHtcbiAgICAgICAgICByZWplY3QoeyBrZXk6ICdleGlzdHMnLCBtZXNzYWdlOiAnUm9sZSBhbHJlYWR5IGV4aXN0cycgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmlyZXN0b3JlLmNvbGxlY3Rpb24ocGF0aCkuYWRkKHJvbGUuZGF0YSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICByZWplY3QoIHsga2V5OiAnZGVmYXVsdGVycm9yJywgbWVzc2FnZTogJ0Vycm9yIGFkZGluZyByb2xlJyB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVSb2xlKHJvb3RGaXJlYmFzZVBhdGg6IHN0cmluZywgcm9sZUlkOiBzdHJpbmcpOiBQcm9taXNlPG51bGw+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICByb290RmlyZWJhc2VQYXRoID0gcm9vdEZpcmViYXNlUGF0aCB8fCAnJztcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcm9sZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2Mocm9sZUlkKS5kZWxldGUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgcmVqZWN0KCB7IGtleTogJ2RlZmF1bHRlcnJvcicsIG1lc3NhZ2U6ICdFcnJvciByZW1vdmluZyByb2xlJyB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlUm9sZShyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHJvbGU6IFJvbGVPYmopOiBQcm9taXNlPG51bGw+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICByb290RmlyZWJhc2VQYXRoID0gcm9vdEZpcmViYXNlUGF0aCB8fCAnJztcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcm9sZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2Mocm9sZS5pZCkuc2V0KHJvbGUuZGF0YSkudGhlbigoKSA9PiB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgIHJlamVjdCggeyBrZXk6ICdkZWZhdWx0ZXJyb3InLCBtZXNzYWdlOiAnRXJyb3IgdXBkYXRpbmcgcm9sZScgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldFJvbGUocm9vdEZpcmViYXNlUGF0aDogc3RyaW5nLCByb2xlSWQ6IHN0cmluZyk6IFByb21pc2U8Um9sZU9iaj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcm9sZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS5kb2Mocm9sZUlkKS5nZXQoKS50aGVuKHJvbGVEQiA9PiB7XG4gICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgIGlkOiByb2xlREIuaWQsXG4gICAgICAgICAgZGF0YTogcm9sZURCLmRhdGEoKVxuICAgICAgICB9IGFzIFJvbGVPYmopO1xuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXRSb2xlcyhyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcpOiBQcm9taXNlPFJvbGVPYmpbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGlmICghcm9vdEZpcmViYXNlUGF0aCkge1xuICAgICAgICByb290RmlyZWJhc2VQYXRoID0gJyc7XG4gICAgICB9XG4gICAgICBjb25zdCBwYXRoID0gKHJvb3RGaXJlYmFzZVBhdGggKyAnL3JvbGVzJykucmVwbGFjZSgnLy8nLCAnLycpO1xuICAgICAgZmlyZXN0b3JlLmNvbGxlY3Rpb24ocGF0aCkuZ2V0KCkudGhlbihyb2xlc0RCID0+IHtcbiAgICAgICAgaWYgKHJvbGVzREIuZW1wdHkpIHtcbiAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocm9sZXNEQi5kb2NzLm1hcChyb2xlREIgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaWQ6IHJvbGVEQi5pZCxcbiAgICAgICAgICAgICAgZGF0YTogcm9sZURCLmRhdGEoKVxuICAgICAgICAgICAgfSBhcyBSb2xlT2JqO1xuICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXRSb2xlc0J5UmVzb3VyY2Uocm9vdEZpcmViYXNlUGF0aDogc3RyaW5nLCByZXNvdXJjZUlkOiBzdHJpbmcpOiBQcm9taXNlPFJvbGVPYmpbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcm9sZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS53aGVyZSgnZGF0YS5yZXNvdXJjZXMnLCAnYXJyYXktY29udGFpbnMnLCByZXNvdXJjZUlkKS5nZXQoKS50aGVuKHJvbGVzREIgPT4ge1xuICAgICAgICBpZiAocm9sZXNEQi5lbXB0eSkge1xuICAgICAgICAgIHJlc29sdmUobnVsbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShyb2xlc0RCLmRvY3MubWFwKHJvbGVEQiA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBpZDogcm9sZURCLmlkLFxuICAgICAgICAgICAgICBkYXRhOiByb2xlREIuZGF0YSgpXG4gICAgICAgICAgICB9IGFzIFJvbGVPYmo7XG4gICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldFJvbGVzQnlVc2VyKHJvb3RGaXJlYmFzZVBhdGg6IHN0cmluZywgdXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPFJvbGVPYmpbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IHBhdGggPSAocm9vdEZpcmViYXNlUGF0aCArICcvcm9sZXMnKS5yZXBsYWNlKCcvLycsICcvJyk7XG4gICAgICBmaXJlc3RvcmUuY29sbGVjdGlvbihwYXRoKS53aGVyZSgndXNlcnMnLCAnYXJyYXktY29udGFpbnMnLCB1c2VySWQpLmdldCgpLnRoZW4ocm9sZXNEQiA9PiB7XG4gICAgICAgIGlmIChyb2xlc0RCLmVtcHR5KSB7XG4gICAgICAgICAgcmVzb2x2ZShudWxsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHJvbGVzREIuZG9jcy5tYXAocm9sZURCID0+IHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGlkOiByb2xlREIuaWQsXG4gICAgICAgICAgICAgIGRhdGE6IHJvbGVEQi5kYXRhKClcbiAgICAgICAgICAgIH0gYXMgUm9sZU9iajtcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlUm9sZVBlcm1pc3Npb25zKHJvb3RGaXJlYmFzZVBhdGg6IHN0cmluZywgcm9sZTogUm9sZU9iaikge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBmaXJlYmFzZS5maXJlc3RvcmUoKTtcbiAgICAgIHJvb3RGaXJlYmFzZVBhdGggPSByb290RmlyZWJhc2VQYXRoIHx8ICcnO1xuICAgICAgY29uc3QgcGF0aCA9IChyb290RmlyZWJhc2VQYXRoICsgJy9yb2xlcycpLnJlcGxhY2UoJy8vJywgJy8nKTtcbiAgICAgIGZpcmVzdG9yZS5jb2xsZWN0aW9uKHBhdGgpLmRvYyhyb2xlLmlkKS5nZXQoKS50aGVuKHJvbGVEQiA9PiB7XG4gICAgICAgIGlmICghcm9sZURCLmV4aXN0cykge1xuICAgICAgICAgIHJlamVjdCh7IGtleTogJ25vdGV4aXN0cycsIG1lc3NhZ2U6ICdSb2xlIG5vdCBleGlzdHMnIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZpcmVzdG9yZS5jb2xsZWN0aW9uKHBhdGgpLmRvYyhyb2xlLmlkKS51cGRhdGUoXG4gICAgICAgICAgICB7IHBlcm1pc3Npb25zOiByb2xlLmRhdGEucGVybWlzc2lvbnMgfVxuICAgICAgICAgICkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICByZWplY3QoIHsga2V5OiAnZGVmYXVsdGVycm9yJywgbWVzc2FnZTogJ0Vycm9yIHVwZGF0aW5nIHBlcm1pc3Npb25zJyB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8jcmVnaW9uIFJvbGVzXG4gIHJlbW92ZVVzZXJGcm9tUm9sZShyb290RmlyZWJhc2VQYXRoOiBzdHJpbmcsIHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxudWxsPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGZpcmVzdG9yZSA9IGZpcmViYXNlLmZpcmVzdG9yZSgpO1xuICAgICAgY29uc3QgdXNlcnNQYXRoID0gKHJvb3RGaXJlYmFzZVBhdGggKyAnL3VzZXJzJykucmVwbGFjZSgnLy8nLCAnLycpO1xuICAgICAgY29uc3Qgcm9sZXNQYXRoID0gKHJvb3RGaXJlYmFzZVBhdGggKyAnL3JvbGVzJykucmVwbGFjZSgnLy8nLCAnLycpO1xuICAgICAgdGhpcy5nZXRSb2xlc0J5VXNlcihyb290RmlyZWJhc2VQYXRoLCB1c2VySWQpLnRoZW4ocm9sZXNEQiA9PiB7XG4gICAgICAgIGNvbnN0IGJhdGNoID0gZmlyZXN0b3JlLmJhdGNoKCk7XG4gICAgICAgIGNvbnN0IHJvbGVzVG9VcGRhdGU6IFJvbGVPYmpbXSA9IHJvbGVzREI7XG4gICAgICAgIHJvbGVzVG9VcGRhdGUuZm9yRWFjaChyb2xlVG9VcGRhdGUgPT4ge1xuICAgICAgICAgIHJvbGVUb1VwZGF0ZS5kYXRhLnVzZXJzLnNwbGljZShyb2xlVG9VcGRhdGUuZGF0YS51c2Vycy5maW5kSW5kZXgodXNlciA9PiB1c2VyID09PSB1c2VySWQpLCAxKTtcbiAgICAgICAgICBjb25zdCByb2xlUmVmID0gZmlyZXN0b3JlLmNvbGxlY3Rpb24ocm9sZXNQYXRoKS5kb2Mocm9sZVRvVXBkYXRlLmlkKTtcbiAgICAgICAgICBiYXRjaC51cGRhdGUocm9sZVJlZiwgeyBkYXRhOiByb2xlVG9VcGRhdGUuZGF0YSB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHVzZXJSZWYgPSBmaXJlc3RvcmUuY29sbGVjdGlvbih1c2Vyc1BhdGgpLmRvYyh1c2VySWQpO1xuICAgICAgICBiYXRjaC5kZWxldGUodXNlclJlZik7XG4gICAgICAgIGJhdGNoLmNvbW1pdCgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG5cbiAgZ2V0VXNlcnNCeVJlc291cmNlKHJvb3RGaXJlYmFzZVBhdGg6IHN0cmluZywgcmVzb3VyY2VJZDogc3RyaW5nKTogUHJvbWlzZTxVc2VyT2JqW10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgZmlyZXN0b3JlID0gZmlyZWJhc2UuZmlyZXN0b3JlKCk7XG4gICAgICBjb25zdCBwYXRoID0gKHJvb3RGaXJlYmFzZVBhdGggKyAnL3VzZXJzJykucmVwbGFjZSgnLy8nLCAnLycpO1xuICAgICAgZmlyZXN0b3JlLmNvbGxlY3Rpb24ocGF0aCkud2hlcmUoJ2RhdGEucmVzb3VyY2VzJywgJ2FycmF5LWNvbnRhaW5zJywgcmVzb3VyY2VJZCkuZ2V0KCkudGhlbih1c2Vyc0RCID0+IHtcbiAgICAgICAgaWYgKHVzZXJzREIuZW1wdHkpIHtcbiAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUodXNlcnNEQi5kb2NzLm1hcCh1c2VyREIgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaWQ6IHVzZXJEQi5pZCxcbiAgICAgICAgICAgICAgZGF0YTogdXNlckRCLmRhdGEoKVxuICAgICAgICAgICAgfSBhcyBVc2VyT2JqO1xuICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLy8gZW5kcmVnaW9uXG59XG4iXX0=