tedious
Version:
A TDS driver, for connecting to MS SQLServer databases.
112 lines (88 loc) • 19.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getParameterEncryptionMetadata = void 0;
var _types = require("./types");
var _cekEntry = require("./cek-entry");
var _keyCrypto = require("./key-crypto");
var _dataType = require("../data-type");
var _request = _interopRequireDefault(require("../request"));
var _rpcrequestPayload = _interopRequireDefault(require("../rpcrequest-payload"));
var _packet = require("../packet");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// This code is based on the `mssql-jdbc` library published under the conditions of MIT license.
// Copyright (c) 2019 Microsoft Corporation
const getParameterEncryptionMetadata = (connection, request, callback) => {
if (request.cryptoMetadataLoaded === true) {
return callback();
}
const metadataRequest = new _request.default('sp_describe_parameter_encryption', error => {
if (error) {
return callback(error);
}
const decryptSymmetricKeyPromises = [];
const cekList = [];
let paramCount = 0;
for (const columns of resultRows) {
try {
const isFirstRecordSet = columns.some(col => (col && col.metadata && col.metadata.colName) === 'database_id');
if (isFirstRecordSet === true) {
const currentOrdinal = columns[_types.DescribeParameterEncryptionResultSet1.KeyOrdinal].value;
let cekEntry;
if (!cekList[currentOrdinal]) {
cekEntry = new _cekEntry.CEKEntry(currentOrdinal);
cekList[cekEntry.ordinal] = cekEntry;
} else {
cekEntry = cekList[currentOrdinal];
}
cekEntry.add(columns[_types.DescribeParameterEncryptionResultSet1.EncryptedKey].value, columns[_types.DescribeParameterEncryptionResultSet1.DbId].value, columns[_types.DescribeParameterEncryptionResultSet1.KeyId].value, columns[_types.DescribeParameterEncryptionResultSet1.KeyVersion].value, columns[_types.DescribeParameterEncryptionResultSet1.KeyMdVersion].value, columns[_types.DescribeParameterEncryptionResultSet1.KeyPath].value, columns[_types.DescribeParameterEncryptionResultSet1.ProviderName].value, columns[_types.DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm].value);
} else {
paramCount++;
const paramName = columns[_types.DescribeParameterEncryptionResultSet2.ParameterName].value;
const paramIndex = request.parameters.findIndex(param => paramName === `@${param.name}`);
const cekOrdinal = columns[_types.DescribeParameterEncryptionResultSet2.ColumnEncryptionKeyOrdinal].value;
const cekEntry = cekList[cekOrdinal];
if (cekEntry && cekList.length < cekOrdinal) {
return callback(new Error(`Internal error. The referenced column encryption key ordinal "${cekOrdinal}" is missing in the encryption metadata returned by sp_describe_parameter_encryption. Max ordinal is "${cekList.length}".`));
}
const encType = columns[_types.DescribeParameterEncryptionResultSet2.ColumnEncrytionType].value;
if (_types.SQLServerEncryptionType.PlainText !== encType) {
request.parameters[paramIndex].cryptoMetadata = {
cekEntry: cekEntry,
ordinal: cekOrdinal,
cipherAlgorithmId: columns[_types.DescribeParameterEncryptionResultSet2.ColumnEncryptionAlgorithm].value,
encryptionType: encType,
normalizationRuleVersion: Buffer.from([columns[_types.DescribeParameterEncryptionResultSet2.NormalizationRuleVersion].value])
};
decryptSymmetricKeyPromises.push((0, _keyCrypto.decryptSymmetricKey)(request.parameters[paramIndex].cryptoMetadata, connection.config.options));
} else if (request.parameters[paramIndex].forceEncrypt === true) {
return callback(new Error(`Cannot execute statement or procedure ${request.sqlTextOrProcedure} because Force Encryption was set as true for parameter ${paramIndex + 1} and the database expects this parameter to be sent as plaintext. This may be due to a configuration error.`));
}
}
} catch {
return callback(new Error(`Internal error. Unable to parse parameter encryption metadata in statement or procedure "${request.sqlTextOrProcedure}"`));
}
}
if (paramCount !== request.parameters.length) {
return callback(new Error(`Internal error. Metadata for some parameters in statement or procedure "${request.sqlTextOrProcedure}" is missing in the resultset returned by sp_describe_parameter_encryption.`));
}
return Promise.all(decryptSymmetricKeyPromises).then(() => {
request.cryptoMetadataLoaded = true;
process.nextTick(callback);
}, error => {
process.nextTick(callback, error);
});
});
metadataRequest.addParameter('tsql', _dataType.typeByName.NVarChar, request.sqlTextOrProcedure);
if (request.parameters.length) {
metadataRequest.addParameter('params', _dataType.typeByName.NVarChar, metadataRequest.makeParamsParameter(request.parameters));
}
const resultRows = [];
metadataRequest.on('row', columns => {
resultRows.push(columns);
});
connection.makeRequest(metadataRequest, _packet.TYPE.RPC_REQUEST, new _rpcrequestPayload.default(metadataRequest.sqlTextOrProcedure, metadataRequest.parameters, connection.currentTransactionDescriptor(), connection.config.options, connection.databaseCollation));
};
exports.getParameterEncryptionMetadata = getParameterEncryptionMetadata;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZXRQYXJhbWV0ZXJFbmNyeXB0aW9uTWV0YWRhdGEiLCJjb25uZWN0aW9uIiwicmVxdWVzdCIsImNhbGxiYWNrIiwiY3J5cHRvTWV0YWRhdGFMb2FkZWQiLCJtZXRhZGF0YVJlcXVlc3QiLCJSZXF1ZXN0IiwiZXJyb3IiLCJkZWNyeXB0U3ltbWV0cmljS2V5UHJvbWlzZXMiLCJjZWtMaXN0IiwicGFyYW1Db3VudCIsImNvbHVtbnMiLCJyZXN1bHRSb3dzIiwiaXNGaXJzdFJlY29yZFNldCIsInNvbWUiLCJjb2wiLCJtZXRhZGF0YSIsImNvbE5hbWUiLCJjdXJyZW50T3JkaW5hbCIsIkRlc2NyaWJlUGFyYW1ldGVyRW5jcnlwdGlvblJlc3VsdFNldDEiLCJLZXlPcmRpbmFsIiwidmFsdWUiLCJjZWtFbnRyeSIsIkNFS0VudHJ5Iiwib3JkaW5hbCIsImFkZCIsIkVuY3J5cHRlZEtleSIsIkRiSWQiLCJLZXlJZCIsIktleVZlcnNpb24iLCJLZXlNZFZlcnNpb24iLCJLZXlQYXRoIiwiUHJvdmlkZXJOYW1lIiwiS2V5RW5jcnlwdGlvbkFsZ29yaXRobSIsInBhcmFtTmFtZSIsIkRlc2NyaWJlUGFyYW1ldGVyRW5jcnlwdGlvblJlc3VsdFNldDIiLCJQYXJhbWV0ZXJOYW1lIiwicGFyYW1JbmRleCIsInBhcmFtZXRlcnMiLCJmaW5kSW5kZXgiLCJwYXJhbSIsIm5hbWUiLCJjZWtPcmRpbmFsIiwiQ29sdW1uRW5jcnlwdGlvbktleU9yZGluYWwiLCJsZW5ndGgiLCJFcnJvciIsImVuY1R5cGUiLCJDb2x1bW5FbmNyeXRpb25UeXBlIiwiU1FMU2VydmVyRW5jcnlwdGlvblR5cGUiLCJQbGFpblRleHQiLCJjcnlwdG9NZXRhZGF0YSIsImNpcGhlckFsZ29yaXRobUlkIiwiQ29sdW1uRW5jcnlwdGlvbkFsZ29yaXRobSIsImVuY3J5cHRpb25UeXBlIiwibm9ybWFsaXphdGlvblJ1bGVWZXJzaW9uIiwiQnVmZmVyIiwiZnJvbSIsIk5vcm1hbGl6YXRpb25SdWxlVmVyc2lvbiIsInB1c2giLCJjb25maWciLCJvcHRpb25zIiwiZm9yY2VFbmNyeXB0Iiwic3FsVGV4dE9yUHJvY2VkdXJlIiwiUHJvbWlzZSIsImFsbCIsInRoZW4iLCJwcm9jZXNzIiwibmV4dFRpY2siLCJhZGRQYXJhbWV0ZXIiLCJUWVBFUyIsIk5WYXJDaGFyIiwibWFrZVBhcmFtc1BhcmFtZXRlciIsIm9uIiwibWFrZVJlcXVlc3QiLCJUWVBFIiwiUlBDX1JFUVVFU1QiLCJScGNSZXF1ZXN0UGF5bG9hZCIsImN1cnJlbnRUcmFuc2FjdGlvbkRlc2NyaXB0b3IiLCJkYXRhYmFzZUNvbGxhdGlvbiJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hbHdheXMtZW5jcnlwdGVkL2dldC1wYXJhbWV0ZXItZW5jcnlwdGlvbi1tZXRhZGF0YS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGlzIGNvZGUgaXMgYmFzZWQgb24gdGhlIGBtc3NxbC1qZGJjYCBsaWJyYXJ5IHB1Ymxpc2hlZCB1bmRlciB0aGUgY29uZGl0aW9ucyBvZiBNSVQgbGljZW5zZS5cbi8vIENvcHlyaWdodCAoYykgMjAxOSBNaWNyb3NvZnQgQ29ycG9yYXRpb25cblxuaW1wb3J0IHsgU1FMU2VydmVyRW5jcnlwdGlvblR5cGUsIENyeXB0b01ldGFkYXRhLCBEZXNjcmliZVBhcmFtZXRlckVuY3J5cHRpb25SZXN1bHRTZXQxLCBEZXNjcmliZVBhcmFtZXRlckVuY3J5cHRpb25SZXN1bHRTZXQyIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBDRUtFbnRyeSB9IGZyb20gJy4vY2VrLWVudHJ5JztcbmltcG9ydCB7IGRlY3J5cHRTeW1tZXRyaWNLZXkgfSBmcm9tICcuL2tleS1jcnlwdG8nO1xuaW1wb3J0IHsgdHlwZUJ5TmFtZSBhcyBUWVBFUywgUGFyYW1ldGVyIH0gZnJvbSAnLi4vZGF0YS10eXBlJztcbmltcG9ydCBSZXF1ZXN0IGZyb20gJy4uL3JlcXVlc3QnO1xuaW1wb3J0IENvbm5lY3Rpb24gZnJvbSAnLi4vY29ubmVjdGlvbic7XG5pbXBvcnQgUnBjUmVxdWVzdFBheWxvYWQgZnJvbSAnLi4vcnBjcmVxdWVzdC1wYXlsb2FkJztcbmltcG9ydCB7IFRZUEUgfSBmcm9tICcuLi9wYWNrZXQnO1xuXG5leHBvcnQgY29uc3QgZ2V0UGFyYW1ldGVyRW5jcnlwdGlvbk1ldGFkYXRhID0gKGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHJlcXVlc3Q6IFJlcXVlc3QsIGNhbGxiYWNrOiAoZXJyb3I/OiBFcnJvcikgPT4gdm9pZCkgPT4ge1xuICBpZiAocmVxdWVzdC5jcnlwdG9NZXRhZGF0YUxvYWRlZCA9PT0gdHJ1ZSkge1xuICAgIHJldHVybiBjYWxsYmFjaygpO1xuICB9XG5cbiAgY29uc3QgbWV0YWRhdGFSZXF1ZXN0ID0gbmV3IFJlcXVlc3QoJ3NwX2Rlc2NyaWJlX3BhcmFtZXRlcl9lbmNyeXB0aW9uJywgKGVycm9yKSA9PiB7XG4gICAgaWYgKGVycm9yKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soZXJyb3IpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlY3J5cHRTeW1tZXRyaWNLZXlQcm9taXNlczogUHJvbWlzZTx2b2lkPltdID0gW107XG4gICAgY29uc3QgY2VrTGlzdDogQ0VLRW50cnlbXSA9IFtdO1xuICAgIGxldCBwYXJhbUNvdW50ID0gMDtcblxuICAgIGZvciAoY29uc3QgY29sdW1ucyBvZiByZXN1bHRSb3dzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBpc0ZpcnN0UmVjb3JkU2V0ID0gY29sdW1ucy5zb21lKChjb2w6IGFueSkgPT4gKGNvbCAmJiBjb2wubWV0YWRhdGEgJiYgY29sLm1ldGFkYXRhLmNvbE5hbWUpID09PSAnZGF0YWJhc2VfaWQnKTtcbiAgICAgICAgaWYgKGlzRmlyc3RSZWNvcmRTZXQgPT09IHRydWUpIHtcbiAgICAgICAgICBjb25zdCBjdXJyZW50T3JkaW5hbCA9IGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0MS5LZXlPcmRpbmFsXS52YWx1ZTtcbiAgICAgICAgICBsZXQgY2VrRW50cnk6IENFS0VudHJ5O1xuICAgICAgICAgIGlmICghY2VrTGlzdFtjdXJyZW50T3JkaW5hbF0pIHtcbiAgICAgICAgICAgIGNla0VudHJ5ID0gbmV3IENFS0VudHJ5KGN1cnJlbnRPcmRpbmFsKTtcbiAgICAgICAgICAgIGNla0xpc3RbY2VrRW50cnkub3JkaW5hbF0gPSBjZWtFbnRyeTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2VrRW50cnkgPSBjZWtMaXN0W2N1cnJlbnRPcmRpbmFsXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY2VrRW50cnkuYWRkKGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0MS5FbmNyeXB0ZWRLZXldLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5zW0Rlc2NyaWJlUGFyYW1ldGVyRW5jcnlwdGlvblJlc3VsdFNldDEuRGJJZF0udmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0MS5LZXlJZF0udmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0MS5LZXlWZXJzaW9uXS52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uc1tEZXNjcmliZVBhcmFtZXRlckVuY3J5cHRpb25SZXN1bHRTZXQxLktleU1kVmVyc2lvbl0udmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0MS5LZXlQYXRoXS52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uc1tEZXNjcmliZVBhcmFtZXRlckVuY3J5cHRpb25SZXN1bHRTZXQxLlByb3ZpZGVyTmFtZV0udmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0MS5LZXlFbmNyeXB0aW9uQWxnb3JpdGhtXS52YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFyYW1Db3VudCsrO1xuICAgICAgICAgIGNvbnN0IHBhcmFtTmFtZTogc3RyaW5nID0gY29sdW1uc1tEZXNjcmliZVBhcmFtZXRlckVuY3J5cHRpb25SZXN1bHRTZXQyLlBhcmFtZXRlck5hbWVdLnZhbHVlO1xuICAgICAgICAgIGNvbnN0IHBhcmFtSW5kZXg6IG51bWJlciA9IHJlcXVlc3QucGFyYW1ldGVycy5maW5kSW5kZXgoKHBhcmFtOiBQYXJhbWV0ZXIpID0+IHBhcmFtTmFtZSA9PT0gYEAke3BhcmFtLm5hbWV9YCk7XG4gICAgICAgICAgY29uc3QgY2VrT3JkaW5hbDogbnVtYmVyID0gY29sdW1uc1tEZXNjcmliZVBhcmFtZXRlckVuY3J5cHRpb25SZXN1bHRTZXQyLkNvbHVtbkVuY3J5cHRpb25LZXlPcmRpbmFsXS52YWx1ZTtcbiAgICAgICAgICBjb25zdCBjZWtFbnRyeTogQ0VLRW50cnkgPSBjZWtMaXN0W2Nla09yZGluYWxdO1xuXG4gICAgICAgICAgaWYgKGNla0VudHJ5ICYmIGNla0xpc3QubGVuZ3RoIDwgY2VrT3JkaW5hbCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBFcnJvcihgSW50ZXJuYWwgZXJyb3IuIFRoZSByZWZlcmVuY2VkIGNvbHVtbiBlbmNyeXB0aW9uIGtleSBvcmRpbmFsIFwiJHtjZWtPcmRpbmFsfVwiIGlzIG1pc3NpbmcgaW4gdGhlIGVuY3J5cHRpb24gbWV0YWRhdGEgcmV0dXJuZWQgYnkgc3BfZGVzY3JpYmVfcGFyYW1ldGVyX2VuY3J5cHRpb24uIE1heCBvcmRpbmFsIGlzIFwiJHtjZWtMaXN0Lmxlbmd0aH1cIi5gKSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZW5jVHlwZSA9IGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0Mi5Db2x1bW5FbmNyeXRpb25UeXBlXS52YWx1ZTtcbiAgICAgICAgICBpZiAoU1FMU2VydmVyRW5jcnlwdGlvblR5cGUuUGxhaW5UZXh0ICE9PSBlbmNUeXBlKSB7XG4gICAgICAgICAgICByZXF1ZXN0LnBhcmFtZXRlcnNbcGFyYW1JbmRleF0uY3J5cHRvTWV0YWRhdGEgPSB7XG4gICAgICAgICAgICAgIGNla0VudHJ5OiBjZWtFbnRyeSxcbiAgICAgICAgICAgICAgb3JkaW5hbDogY2VrT3JkaW5hbCxcbiAgICAgICAgICAgICAgY2lwaGVyQWxnb3JpdGhtSWQ6IGNvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0Mi5Db2x1bW5FbmNyeXB0aW9uQWxnb3JpdGhtXS52YWx1ZSxcbiAgICAgICAgICAgICAgZW5jcnlwdGlvblR5cGU6IGVuY1R5cGUsXG4gICAgICAgICAgICAgIG5vcm1hbGl6YXRpb25SdWxlVmVyc2lvbjogQnVmZmVyLmZyb20oW2NvbHVtbnNbRGVzY3JpYmVQYXJhbWV0ZXJFbmNyeXB0aW9uUmVzdWx0U2V0Mi5Ob3JtYWxpemF0aW9uUnVsZVZlcnNpb25dLnZhbHVlXSksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZGVjcnlwdFN5bW1ldHJpY0tleVByb21pc2VzLnB1c2goZGVjcnlwdFN5bW1ldHJpY0tleShyZXF1ZXN0LnBhcmFtZXRlcnNbcGFyYW1JbmRleF0uY3J5cHRvTWV0YWRhdGEgYXMgQ3J5cHRvTWV0YWRhdGEsIGNvbm5lY3Rpb24uY29uZmlnLm9wdGlvbnMpKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHJlcXVlc3QucGFyYW1ldGVyc1twYXJhbUluZGV4XS5mb3JjZUVuY3J5cHQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhuZXcgRXJyb3IoYENhbm5vdCBleGVjdXRlIHN0YXRlbWVudCBvciBwcm9jZWR1cmUgJHtyZXF1ZXN0LnNxbFRleHRPclByb2NlZHVyZX0gYmVjYXVzZSBGb3JjZSBFbmNyeXB0aW9uIHdhcyBzZXQgYXMgdHJ1ZSBmb3IgcGFyYW1ldGVyICR7cGFyYW1JbmRleCArIDF9IGFuZCB0aGUgZGF0YWJhc2UgZXhwZWN0cyB0aGlzIHBhcmFtZXRlciB0byBiZSBzZW50IGFzIHBsYWludGV4dC4gVGhpcyBtYXkgYmUgZHVlIHRvIGEgY29uZmlndXJhdGlvbiBlcnJvci5gKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBFcnJvcihgSW50ZXJuYWwgZXJyb3IuIFVuYWJsZSB0byBwYXJzZSBwYXJhbWV0ZXIgZW5jcnlwdGlvbiBtZXRhZGF0YSBpbiBzdGF0ZW1lbnQgb3IgcHJvY2VkdXJlIFwiJHtyZXF1ZXN0LnNxbFRleHRPclByb2NlZHVyZX1cImApKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocGFyYW1Db3VudCAhPT0gcmVxdWVzdC5wYXJhbWV0ZXJzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBFcnJvcihgSW50ZXJuYWwgZXJyb3IuIE1ldGFkYXRhIGZvciBzb21lIHBhcmFtZXRlcnMgaW4gc3RhdGVtZW50IG9yIHByb2NlZHVyZSBcIiR7cmVxdWVzdC5zcWxUZXh0T3JQcm9jZWR1cmV9XCIgaXMgbWlzc2luZyBpbiB0aGUgcmVzdWx0c2V0IHJldHVybmVkIGJ5IHNwX2Rlc2NyaWJlX3BhcmFtZXRlcl9lbmNyeXB0aW9uLmApKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoZGVjcnlwdFN5bW1ldHJpY0tleVByb21pc2VzKS50aGVuKCgpID0+IHtcbiAgICAgIHJlcXVlc3QuY3J5cHRvTWV0YWRhdGFMb2FkZWQgPSB0cnVlO1xuICAgICAgcHJvY2Vzcy5uZXh0VGljayhjYWxsYmFjayk7XG4gICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICBwcm9jZXNzLm5leHRUaWNrKGNhbGxiYWNrLCBlcnJvcik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIG1ldGFkYXRhUmVxdWVzdC5hZGRQYXJhbWV0ZXIoJ3RzcWwnLCBUWVBFUy5OVmFyQ2hhciwgcmVxdWVzdC5zcWxUZXh0T3JQcm9jZWR1cmUpO1xuICBpZiAocmVxdWVzdC5wYXJhbWV0ZXJzLmxlbmd0aCkge1xuICAgIG1ldGFkYXRhUmVxdWVzdC5hZGRQYXJhbWV0ZXIoJ3BhcmFtcycsIFRZUEVTLk5WYXJDaGFyLCBtZXRhZGF0YVJlcXVlc3QubWFrZVBhcmFtc1BhcmFtZXRlcihyZXF1ZXN0LnBhcmFtZXRlcnMpKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdFJvd3M6IGFueVtdID0gW107XG5cbiAgbWV0YWRhdGFSZXF1ZXN0Lm9uKCdyb3cnLCAoY29sdW1uczogYW55KSA9PiB7XG4gICAgcmVzdWx0Um93cy5wdXNoKGNvbHVtbnMpO1xuICB9KTtcblxuICBjb25uZWN0aW9uLm1ha2VSZXF1ZXN0KG1ldGFkYXRhUmVxdWVzdCwgVFlQRS5SUENfUkVRVUVTVCwgbmV3IFJwY1JlcXVlc3RQYXlsb2FkKG1ldGFkYXRhUmVxdWVzdC5zcWxUZXh0T3JQcm9jZWR1cmUhLCBtZXRhZGF0YVJlcXVlc3QucGFyYW1ldGVycywgY29ubmVjdGlvbi5jdXJyZW50VHJhbnNhY3Rpb25EZXNjcmlwdG9yKCksIGNvbm5lY3Rpb24uY29uZmlnLm9wdGlvbnMsIGNvbm5lY3Rpb24uZGF0YWJhc2VDb2xsYXRpb24pKTtcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFHQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7OztBQVZBO0FBQ0E7QUFXTyxNQUFNQSw4QkFBOEIsR0FBRyxDQUFDQyxVQUFELEVBQXlCQyxPQUF6QixFQUEyQ0MsUUFBM0MsS0FBaUY7RUFDN0gsSUFBSUQsT0FBTyxDQUFDRSxvQkFBUixLQUFpQyxJQUFyQyxFQUEyQztJQUN6QyxPQUFPRCxRQUFRLEVBQWY7RUFDRDs7RUFFRCxNQUFNRSxlQUFlLEdBQUcsSUFBSUMsZ0JBQUosQ0FBWSxrQ0FBWixFQUFpREMsS0FB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