PHP WebShell

Текущая директория: /opt/BitGoJS/modules/bitgo/dist/test/unit

Просмотр файла: bitgo.js

"use strict";
//
// Tests for BitGo Object
//
Object.defineProperty(exports, "__esModule", { value: true });
const crypto = require("crypto");
const nock = require("nock");
const should = require("should");
const assert = require("assert");
const sdk_core_1 = require("@bitgo/sdk-core");
const utxo_lib_1 = require("@bitgo/utxo-lib");
const _ = require("lodash");
const BitGoJS = require("../../src/index");
const rp = require('request-promise');
const sdk_test_1 = require("@bitgo/sdk-test");
const bitgo_1 = require("../../src/bitgo");
nock.disableNetConnect();
describe('BitGo Prototype Methods', function () {
    describe('Version', () => {
        it('version', function () {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const version = bitgo.version();
            version.should.be.a.String();
        });
    });
    describe('validate', () => {
        it('should get', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.getValidate().should.equal(true);
        });
        it('should set', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.setValidate(false);
            bitgo.getValidate().should.equal(false);
            bitgo['_validate'].should.equal(false);
        });
    });
    describe('Environments', () => {
        it('production', () => {
            BitGoJS.setNetwork('testnet');
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod' });
            BitGoJS.getNetwork().should.equal('bitcoin');
        });
        it('staging', () => {
            BitGoJS.setNetwork('testnet');
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'staging' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
        it('test', () => {
            BitGoJS.setNetwork('bitcoin');
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'test' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
        it('dev', () => {
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'dev' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
        it('custom network (prod)', () => {
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { customBitcoinNetwork: 'bitcoin', customRootURI: 'http://rooturi.example' });
            BitGoJS.getNetwork().should.equal('bitcoin');
        });
        it('custom network (testnet)', () => {
            sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { customBitcoinNetwork: 'testnet', customRootURI: 'http://rooturi.example' });
            BitGoJS.getNetwork().should.equal('testnet');
        });
    });
    describe('HMAC request verification', () => {
        it('throws if HMAC request verification is disabled for non-prod environments', function () {
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod', hmacVerification: false })).should.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'test', hmacVerification: false })).should.not.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminProd', hmacVerification: false })).should.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminTest', hmacVerification: false })).should.not.throw(/Cannot disable request HMAC verification in environment/);
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, {
                env: 'dev',
                customRootURI: 'http://rooturi.example',
                hmacVerification: false,
            })).should.not.throw(/Cannot disable request HMAC verification in environment/);
        });
        it('allows disabling of HMAC request verification only for dev environments', function () {
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'dev', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'latest', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminDev', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'adminLatest', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'local', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'localNonSecure', hmacVerification: false })).should.not.throw();
            (() => sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, {
                env: 'branch',
                customRootURI: 'http://rooturi.example',
                hmacVerification: false,
            })).should.not.throw();
        });
    });
    describe('Authenticate in Microservices', () => {
        let bitgo;
        const authenticateRequest = {
            username: 'test@bitgo.com',
            password: 'password',
            otp: '000000',
            extensible: false,
            extensionAddress: 'address',
            forceSMS: false,
        };
        it('goes to microservices', async function () {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock', microservicesUri: 'https://microservices.uri' });
            const scope = nock(BitGoJS.Environments[bitgo.getEnv()].uri)
                .post('/api/auth/v1/session')
                .reply(200, {
                user: {
                    username: 'test@bitgo.com',
                },
                access_token: 'token12356',
            });
            await bitgo.authenticate(authenticateRequest);
            scope.isDone().should.be.true();
        });
        it('goes to microservices even when microservicesUri is not specified', async function () {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const scope = nock(BitGoJS.Environments[bitgo.getEnv()].uri)
                .post('/api/auth/v1/session')
                .reply(200, {
                user: {
                    username: 'test@bitgo.com',
                },
                access_token: 'token12356',
            });
            await bitgo.authenticate(authenticateRequest);
            scope.isDone().should.be.true();
        });
    });
    describe('Verify Address', () => {
        let bitgo;
        before(() => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
        });
        it('errors', () => {
            (() => bitgo.verifyAddress()).should.throw();
            (() => bitgo.verifyAddress({})).should.throw();
            bitgo.verifyAddress({ address: 'xyzzy' }).should.be.false();
        });
        it('standard', () => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod' });
            bitgo.verifyAddress({ address: '1Bu3bhwRmevHLAy1JrRB6AfcxfgDG2vXRd' }).should.be.true();
            // wrong version byte:
            bitgo.verifyAddress({ address: '9Ef7HsuByGBogqkjoF5Yng7MYkq5UCdmZz' }).should.be.false();
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.verifyAddress({ address: 'n4DNhSiEaodqaiF9tLYXTCh4kFbdUzxBHs' }).should.be.true();
        });
        it('p2sh', () => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'prod' });
            bitgo.verifyAddress({ address: '3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC' }).should.be.true();
            // wrong version byte:
            bitgo.verifyAddress({ address: 'HV8swrGkmeN7Xig4vENr93aQSrX4iHjg7D' }).should.be.false();
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.verifyAddress({ address: '2NEeFWbfu4EA1rcKx48e82Mj8d6FKcWawZw' }).should.be.true();
        });
    });
    describe('Encrypt/Decrypt', () => {
        const password = 'mickey mouse';
        const secret = 'this is a secret';
        it('invalid password', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const opaque = bitgo.encrypt({ password: password, input: secret });
            (() => bitgo.decrypt({ password: 'hack hack', input: opaque })).should.throw();
        });
        it('valid password', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const opaque = bitgo.encrypt({ password: password, input: secret });
            bitgo.decrypt({ password: password, input: opaque }).should.equal(secret);
        });
    });
    describe('Password Generation', () => {
        it('generates a random password', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            const password = bitgo.generateRandomPassword();
            should.exist(password);
        });
        it('generates a random password with a numWords argument', () => {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
            bitgo.initializeTestVars();
            for (let i = 0; i < 1000; i++) {
                const password = bitgo.generateRandomPassword(10);
                should.exist(password);
                // randomly generated password should be 55 characters roughly 92.5% of the time,
                // 54 characters roughly 7.5% of the time, 53 characters 0.001% of the time,
                // and fewer than 53 characters very, very rarely
                password.length.should.be.within(53, 55);
            }
        });
    });
    describe('Shamir Secret Sharing', () => {
        const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
        const seed = '8cc57dac9cdae42bf7848a2d12f2874d31eca1f9de8fe3f8fa13e7857b545d59';
        const xpub = 'xpub661MyMwAqRbcEusRjkJ64BXgR8ddYsXbuDJfbRc3eZcZVEa2ygswDiFZQpHFsA5N211YDvi2N898h4KrcXcfsR8PLhjJaPUwCUqg1ptBBHN';
        const passwords = ['mickey', 'mouse', 'donald', 'duck'];
        it('should fail to split secret with wrong m', () => {
            (() => bitgo.splitSecret({
                seed,
                passwords: ['abc'],
                m: 0,
            })).should.throw('m must be a positive integer greater than or equal to 2');
        });
        it('should fail to split secret with bad password count', () => {
            (() => bitgo.splitSecret({
                seed,
                passwords: ['abc'],
                m: 2,
            })).should.throw('passwords array length cannot be less than m');
        });
        it('should split and fail to reconstitute secret with bad passwords', () => {
            const splitSecret = bitgo.splitSecret({ seed, passwords: passwords, m: 3 });
            const shards = _.at(splitSecret.seedShares, [0, 2]);
            const subsetPasswords = _.at(passwords, [0, 3]);
            (() => bitgo.reconstituteSecret({
                shards,
                passwords: subsetPasswords,
                xpub,
            })).should.throw(/ccm: tag doesn't match/);
        });
        it('should split and reconstitute secret', () => {
            const splitSecret = bitgo.splitSecret({ seed, passwords: passwords, m: 2 });
            const shards = _.at(splitSecret.seedShares, [0, 2]);
            const subsetPasswords = _.at(passwords, [0, 2]);
            const reconstitutedSeed = bitgo.reconstituteSecret({ shards, passwords: subsetPasswords });
            reconstitutedSeed.seed.should.equal(seed);
            reconstitutedSeed.xpub.should.equal('xpub661MyMwAqRbcEusRjkJ64BXgR8ddYsXbuDJfbRc3eZcZVEa2ygswDiFZQpHFsA5N211YDvi2N898h4KrcXcfsR8PLhjJaPUwCUqg1ptBBHN');
            reconstitutedSeed.xprv.should.equal('xprv9s21ZrQH143K2Rnxdim5h3aws6o99QokXzP4o3CS6E5acSEtS9Zgfuw5ZWujhTHTWEAZDfmP3yxA1Ccn6myVkGEpRrT4xWgaEpoW7YiBAtC');
        });
        it('should split and incorrectly verify secret', () => {
            const splitSecret = bitgo.splitSecret({ seed, passwords: passwords, m: 3 });
            const isValid = bitgo.verifyShards({ shards: splitSecret.seedShares, passwords, m: 2 });
            isValid.should.equal(false);
        });
        it('should split and verify secret', () => {
            const splitSecret = bitgo.splitSecret({ seed, passwords: passwords, m: 2 });
            const isValid = bitgo.verifyShards({ shards: splitSecret.seedShares, passwords, m: 2, xpub });
            isValid.should.equal(true);
        });
        it('should split and verify secret with many parts', () => {
            const allPws = ['0', '1', '2', '3', '4', '5', '6', '7'];
            const splitSecret = bitgo.splitSecret({ seed, passwords: allPws, m: 3 });
            const isValid = bitgo.verifyShards({ shards: splitSecret.seedShares, passwords: allPws, m: 3, xpub });
            isValid.should.equal(true);
        });
    });
    describe('ECDH sharing secret', () => {
        function getKey(seed) {
            return utxo_lib_1.ECPair.fromPrivateKey(utxo_lib_1.bip32.fromSeed(crypto.createHash('sha256').update(seed).digest()).privateKey);
        }
        it('should calculate a new ECDH sharing secret correctly', () => {
            for (let i = 0; i < 256; i++) {
                const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo);
                const eckey1 = getKey(`${i}.a`);
                const eckey2 = getKey(`${i}.b`);
                const sharingKey1 = bitgo.getECDHSecret({ eckey: eckey1, otherPubKeyHex: eckey2.publicKey.toString('hex') });
                const sharingKey2 = bitgo.getECDHSecret({ eckey: eckey2, otherPubKeyHex: eckey1.publicKey.toString('hex') });
                sharingKey1.should.equal(sharingKey2);
                switch (i) {
                    case 0:
                        sharingKey1.should.eql('465ffe5745325998b83fb39631347148e24d4f21b3f3b54739c264d5c42db4b8');
                        break;
                    case 1:
                        sharingKey1.should.eql('61ff44fc1af8061a433a314b7b8be8ae352c10f62aac5887047dbaa5643b818d');
                        break;
                }
            }
        });
    });
    describe('change password', function () {
        let bitgo;
        let bgUrl;
        before(async function () {
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, {
                access_token: 'access_token',
                user: { username: 'update_pw_tester@bitgo.com' },
            });
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            bitgo.initializeTestVars();
            bitgo.setValidate(false);
            await bitgo.authenticateChangePWTestUser(bitgo.testUserOTP());
            bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
        });
        const oldPassword = 'oldPassword';
        const newPassword = 'newPassword';
        const otherPassword = 'otherPassword';
        describe('should fail to change the password', function changePWFail() {
            it('wrong arguments', async function () {
                await bitgo.changePassword({ newPassword: '5678' }).should.be.rejectedWith('expected string oldPassword');
                await bitgo
                    .changePassword({ oldPassword: 1234, newPassword: '5678' })
                    .should.be.rejectedWith('expected string oldPassword');
                await bitgo.changePassword({ oldPassword: '1234' }).should.be.rejectedWith('expected string newPassword');
                await bitgo
                    .changePassword({ oldPassword: '1234', newPassword: 5678 })
                    .should.be.rejectedWith('expected string newPassword');
            });
            it('incorrect old password', async function () {
                nock(bgUrl).post('/api/v1/user/verifypassword').reply(200, { valid: false });
                await bitgo
                    .changePassword({ oldPassword, newPassword })
                    .should.be.rejectedWith('the provided oldPassword is incorrect');
            });
        });
        it('successful password change', async function () {
            nock(bgUrl).post('/api/v1/user/verifypassword').reply(200, { valid: true });
            nock(bgUrl)
                .post('/api/v1/user/encrypted')
                .reply(200, {
                version: 1,
                keychains: {
                    xpub11: bitgo.encrypt({ input: 'xprv11', password: oldPassword }),
                    xpub12: bitgo.encrypt({ input: 'xprv12', password: oldPassword }),
                    xpub13: bitgo.encrypt({ input: 'xprv13', password: otherPassword }),
                    xpub14: bitgo.encrypt({ input: 'xprv14', password: oldPassword }),
                },
            });
            nock(bgUrl)
                .get('/api/v2/tbtc/key')
                .query(true)
                .reply(200, {
                keys: [
                    {
                        pub: 'xpub21',
                        encryptedPrv: bitgo.encrypt({ input: 'xprv21', password: oldPassword }),
                    },
                    {
                        pub: 'xpub22',
                        encryptedPrv: bitgo.encrypt({ input: 'xprv22', password: otherPassword }),
                    },
                ],
            });
            nock(bgUrl).post('/api/v1/user/changepassword').reply(200, {});
            await bitgo.changePassword({ oldPassword, newPassword });
        });
        afterEach(function afterChangePassword() {
            nock.pendingMocks().should.be.empty();
        });
    });
    describe('HMAC Handling', () => {
        let bitgo;
        const token = 'v2x5b735fed2486593f8fea19113e5c717308f90a5fb00e740e46c7bfdcc078cfd0';
        before(() => {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock', accessToken: token });
        });
        it('should correctly calculate request headers', () => {
            const originalDateNow = Date.now;
            Date.now = () => 1521589882510;
            const fetchMeUrl = bitgo.url('/user/me');
            const requestHeaders = bitgo.calculateRequestHeaders({ url: fetchMeUrl, token });
            Date.now = originalDateNow;
            requestHeaders.timestamp.should.equal(1521589882510);
            requestHeaders.tokenHash.should.equal('a85af08e6723e41acd6a3fb9ef58422082e673df33c58e1db175bb740a2c934d');
            requestHeaders.hmac.should.equal('6de77d5a5446a3e5649456c11480706a71071b15639c3c787af65bdb02ecf1ec');
        });
        it('should correctly handle authentication response', () => {
            const responseJson = {
                encryptedToken: '{"iv":"EqxVaGTLY4naAYkuBaTz0w==","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"4S4dBYcgL4s=","ct":"FgBRJljb8iSYxnAjMi4Qotr7sTKbSmWnlfHZShMSi8YeeE3kiS8bpHNUwAPhY8tgouh3UsEwrJnY+54MvqFD7yd19pG1V4CVssr8"}',
                derivationPath: 'm/999999/104490948/173846667',
                encryptedECDHXprv: '{"iv":"QKHEF2GNcwOJwy6+pwANRA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"W2sVFvXDlOw=","ct":"8BTCqS25X37kLzmzQdGenhXH6znn9qEmkszAeS8kLnRdqKSiUiC7bTAVgg/Np5yrV7F7Jyiq+MTpVT76EoUT+PMJzArv0gUQKC2JPB3JuVKeAAVWBQmhWfkEwRfyv4hq4WMxwZtocwBqThvd2pJm9HE51GX4/Wo="}',
            };
            const parsedAuthenticationData = bitgo.handleTokenIssuance(responseJson, 'test@bitgo.com');
            parsedAuthenticationData.token.should.equal(token);
            parsedAuthenticationData.ecdhXprv.should.equal('xprv9s21ZrQH143K3si1bKGp7KqgCQv39ttQ7aUwWzVdytgHd8HtDCHyEp14mxfhiT3qHTq4BaSrA7uUkG6AJTfPJBsRu63drvBqYuMZyTxepH7');
        });
        it('should correctly verify a response hmac', async function () {
            const url = bitgo
                .coin('tltc')
                .url('/wallet/5941b202b42fcbc707170d5b597491d9/address/QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE?segwit=1');
            const requestHeaderData = bitgo.calculateRequestHeaders({ url, token });
            const requestHeaders = {
                'BitGo-Auth-Version': '2.0',
                'Content-Type': 'application/json',
                'Auth-Timestamp': requestHeaderData.timestamp,
                Authorization: 'Bearer ' + requestHeaderData.tokenHash,
                HMAC: requestHeaderData.hmac,
            };
            const responseBody = '{"id":"5a7ca8bcaf52c8e807c575fb692609ec","address":"QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE","chain":0,"index":2,"coin":"tltc","wallet":"5941b202b42fcbc707170d5b597491d9","coinSpecific":{"redeemScript":"522102835bcfd130f7a56f72c905b782d90b66e22f88ad3309cf72af5138a7d44be8b3210322c7f42a1eb212868eab78db7ba64846075d98c7f4c7aa25a02e57871039e0cd210265825be0d5bf957fb72abd7c23bf0836a78a15f951a073467cd5c99e03ce7ab753ae"},"balance":{"updated":"2018-02-28T23:48:07.341Z","numTx":1,"numUnspents":1,"totalReceived":20000000}}';
            nock('https://bitgo.fakeurl', { reqheaders: requestHeaders })
                .get('/api/v2/tltc/wallet/5941b202b42fcbc707170d5b597491d9/address/QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE?segwit=1')
                .reply(200, responseBody, {
                hmac: '30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec',
                timestamp: '1521590532925',
            });
            const responseData = (await rp({
                uri: url,
                method: 'GET',
                headers: requestHeaders,
                transform: (body, response) => {
                    // verify the response headers
                    const url = response.request.href;
                    const hmac = response.headers.hmac;
                    const timestamp = response.headers.timestamp;
                    const statusCode = response.statusCode;
                    const verificationParams = {
                        url,
                        hmac,
                        timestamp,
                        token,
                        statusCode,
                        text: body,
                    };
                    return bitgo.verifyResponse(verificationParams);
                },
            }));
            responseData.signatureSubject.should.equal('1521590532925|/api/v2/tltc/wallet/5941b202b42fcbc707170d5b597491d9/address/QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE?segwit=1|200|{"id":"5a7ca8bcaf52c8e807c575fb692609ec","address":"QNc4RFAcbvqmtrR1kR2wbGLCx6tEvojFYE","chain":0,"index":2,"coin":"tltc","wallet":"5941b202b42fcbc707170d5b597491d9","coinSpecific":{"redeemScript":"522102835bcfd130f7a56f72c905b782d90b66e22f88ad3309cf72af5138a7d44be8b3210322c7f42a1eb212868eab78db7ba64846075d98c7f4c7aa25a02e57871039e0cd210265825be0d5bf957fb72abd7c23bf0836a78a15f951a073467cd5c99e03ce7ab753ae"},"balance":{"updated":"2018-02-28T23:48:07.341Z","numTx":1,"numUnspents":1,"totalReceived":20000000}}');
            responseData.expectedHmac.should.equal('30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec');
            responseData.isValid.should.equal(true);
        });
        it('should include request body as part of the hmac', async function () {
            const url = 'https://bitgo.fakeurl';
            const body = { test: 'test' };
            const fixedUnixTime = 1627374646;
            const originalDateNow = Date.now;
            Date.now = () => fixedUnixTime;
            try {
                nock(url)
                    .post('/', body)
                    .reply(201, undefined, {
                    hmac: '677e0c9a65ca384415945cb19b40ae38eaadfbce3ccce8c5d7bf37c1973b2553',
                    timestamp: String(fixedUnixTime),
                });
                const resp = (await bitgo.post(url).send(body));
                resp.req.headers['hmac'].should.equal('4425a4004ef2724add25b4dd019d21c66394653a049d82e37df3a2c356b5706d');
            }
            finally {
                Date.now = originalDateNow;
            }
        });
        it('should recognize trailing slash inconsistency', () => {
            const verificationParams = {
                url: 'https://google.com/api',
                hmac: '30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec',
                timestamp: '1521590532925',
                token: token,
                statusCode: 200,
                text: 'fakedata',
            };
            const verificationDetails = bitgo.verifyResponse(verificationParams);
            verificationDetails.signatureSubject.should.equal('1521590532925|/api|200|fakedata');
            verificationDetails.signatureSubject.should.not.equal('1521590532925|/api/|200|fakedata');
            verificationDetails.expectedHmac.should.equal('2064f2adb168ef8808f6a42f588d7d6bc14e98e8b41239c6bbb7349e52f2249a');
            verificationDetails.isValid.should.equal(false);
        });
        it('should auto-amend trailing slash', () => {
            const verificationParams = {
                url: 'https://google.com',
                hmac: '30a5943043ab4b0503d807f0cca7dac3a670e8785331322567db5189432b87ec',
                timestamp: '1521590532925',
                token: token,
                statusCode: 200,
                text: 'fakedata',
            };
            const verificationDetails = bitgo.verifyResponse(verificationParams);
            verificationDetails.signatureSubject.should.equal('1521590532925|/|200|fakedata');
            verificationDetails.expectedHmac.should.equal('51c6d024f261e166e8a323f8fa36a9bb8d4d02b076334c2a9ae0a49efc5724d4');
            verificationDetails.isValid.should.equal(false);
        });
        it('should throw if hmac validation is enabled, and no valid hmac headers are returned', async function () {
            const url = 'https://fakeurl.invalid';
            const scope = nock(url).get('/').reply(200);
            // test suite bitgo object has hmac verification enabled, so it should throw when the nock responds
            await bitgo.get(url).should.be.rejectedWith(/invalid response HMAC, possible man-in-the-middle-attack/);
            scope.done();
        });
        it('should not enforce hmac verification if hmac verification is disabled', async function () {
            const bg = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock', hmacVerification: false, accessToken: token });
            const url = 'https://fakeurl.invalid';
            const scope = nock(url).get('/').reply(200, { ok: 1 });
            const res = (await bg.get(url));
            res.body.should.have.property('ok', 1);
            scope.done();
        });
    });
    describe('Token Definitions at Startup', function () {
        it('Should return a non-empty list of tokens before the server responds', async function () {
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            bitgo.initializeTestVars();
            const constants = bitgo.getConstants();
            constants.should.have.propertyByPath('eth', 'tokens', 'length').greaterThan(0);
        });
        after(function tokenDefinitionsAfter() {
            nock.pendingMocks().should.be.empty();
        });
    });
    describe('superagent wrappers', function () {
        let bitgo;
        let bgUrl;
        before(function () {
            bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            bitgo.initializeTestVars();
            bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
            nock(bgUrl).patch('/').reply(200);
        });
        it('PATCH requests', async function () {
            const res = await bitgo.patch(bgUrl);
            res.status.should.equal(200);
        });
        after(function () {
            nock.pendingMocks().should.be.empty();
        });
    });
    describe('preprocessAuthenticationParams', () => {
        const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
        it('should fail if passed non-string username or password', function () {
            (() => bitgo.preprocessAuthenticationParams({ username: 123 })).should.throw(/expected string username/);
            (() => bitgo.preprocessAuthenticationParams({ username: 'abc', password: {} })).should.throw(/expected string password/);
        });
    });
    describe('authenticate', function () {
        afterEach(function ensureNoPendingMocks() {
            nock.pendingMocks().should.be.empty();
        });
        it('should get the ecdhKeychain if ensureEcdhKeychain is set and user already has ecdhKeychain', async function () {
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, {
                access_token: 'access_token',
                user: { username: 'auth-test@bitgo.com' },
            });
            nock('https://bitgo.fakeurl')
                .get('/api/v1/user/settings')
                .reply(200, {
                settings: {
                    ecdhKeychain: 'some-existing-xpub',
                },
            });
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const response = await bitgo.authenticate({
                username: 'auth-test@bitgo.com',
                password: 'password123',
                otp: '000000',
                ensureEcdhKeychain: true,
            });
            should.exist(response.user.ecdhKeychain);
            response.user.ecdhKeychain.should.equal('some-existing-xpub');
        });
        it('should create the ecdhKeychain if ensureEcdhKeychain is set and the user does not already have ecdhKeychain', async function () {
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, {
                access_token: 'access_token',
                user: { username: 'auth-test@bitgo.com' },
            });
            /**
             * This is {} because want to make sure the user has no ecdhXpub set before we set it
             */
            nock('https://bitgo.fakeurl').get('/api/v1/user/settings').reply(200, {
                settings: {},
            });
            nock('https://bitgo.fakeurl').post('/api/v1/keychain').reply(200, {
                xpub: 'some-xpub',
            });
            nock('https://bitgo.fakeurl')
                .put('/api/v2/user/settings')
                .reply(200, {
                settings: {
                    ecdhKeychain: 'some-xpub',
                },
            });
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const response = await bitgo.authenticate({
                username: 'auth-test@bitgo.com',
                password: 'password123',
                otp: '000000',
                ensureEcdhKeychain: true,
            });
            should.exist(response.user.ecdhKeychain);
            response.user.ecdhKeychain.should.equal('some-xpub');
        });
    });
    describe('passkey authentication', () => {
        afterEach(function ensureNoPendingMocks() {
            nock.cleanAll();
            nock.pendingMocks().should.be.empty();
        });
        it('should authenticate with a passkey', async () => {
            const userId = '123';
            const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "${userId}"}}`;
            const keyPair = await (0, sdk_core_1.generateGPGKeyPair)('secp256k1');
            nock('https://bitgo.fakeurl')
                .persist()
                .get('/api/v1/client/constants')
                .reply(200, { ttl: 3600, constants: { passkeyBitGoGpgKey: keyPair.publicKey } });
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, async (uri, requestBody) => {
                assert(typeof requestBody === 'object');
                should.exist(requestBody.userId);
                should.exist(requestBody.passkey);
                requestBody.userId.should.equal(userId);
                requestBody.passkey.should.equal(passkey);
                return {
                    access_token: 'access_token',
                    user: { username: 'auth-test@bitgo.com' },
                };
            });
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            const response = await bitgo.authenticateWithPasskey(passkey);
            should.exist(response.access_token);
            response.access_token.should.equal('access_token');
        });
        it('should throw - invalid userHandle', async () => {
            const passkey = `{"id": "id", "response": {"authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": 123}}`;
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            try {
                await bitgo.validatePasskeyResponse(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                assert.equal(e.message, 'userHandle is missing');
            }
        });
        it('should throw - invalid authenticatorData', async () => {
            const passkey = `{"id": "id", "response": { "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            try {
                await bitgo.validatePasskeyResponse(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                assert.equal(e.message, 'authenticatorData is missing');
            }
        });
        it('should throw - invalid passkey json', async () => {
            const passkey = `{{"id": "id", "response": { "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
            const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
            try {
                await bitgo.validatePasskeyResponse(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                console.log(e);
                assert(e.message.includes('JSON'));
            }
        });
        it('should throw - missing access token', async () => {
            const passkey = `{"id": "id", "response": { "authenticatorData": "123", "clientDataJSON": "123", "signature": "123", "userHandle": "123"}}`;
            nock('https://bitgo.fakeurl')
                .post('/api/auth/v1/session')
                .reply(200, async () => {
                return {
                    user: { username: 'auth-test@bitgo.com' },
                };
            });
            try {
                const bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
                await bitgo.authenticateWithPasskey(passkey);
                assert.fail('Expected error not thrown');
            }
            catch (e) {
                assert.equal(e.message, 'Failed to login. Please contact support@bitgo.com');
            }
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Z28uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvYml0Z28udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLEVBQUU7QUFDRix5QkFBeUI7QUFDekIsRUFBRTs7QUFFRixpQ0FBaUM7QUFDakMsNkJBQTZCO0FBQzdCLGlDQUFpQztBQUNqQyxpQ0FBa0M7QUFFbEMsOENBQTZEO0FBQzdELDhDQUFnRDtBQUNoRCw0QkFBNEI7QUFDNUIsMkNBQTJDO0FBQzNDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBRXRDLDhDQUE0QztBQUM1QywyQ0FBd0M7QUFFeEMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7QUFFekIsUUFBUSxDQUFDLHlCQUF5QixFQUFFO0lBQ2xDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFO1FBQ3ZCLEVBQUUsQ0FBQyxTQUFTLEVBQUU7WUFDWixNQUFNLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxhQUFLLENBQUMsQ0FBQztZQUN4QyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUMzQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDaEMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtRQUN4QixFQUFFLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtZQUNwQixNQUFNLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxhQUFLLENBQUMsQ0FBQztZQUN4QyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztR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QUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNmLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILEVBQUUsQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRCxNQUFNLE9BQU8sR0FBRywySEFBMkgsQ0FBQztZQUM1SSxJQUFJLENBQUMsdUJBQXVCLENBQUM7aUJBQzFCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQztpQkFDNUIsS0FBSyxDQUFDLEdBQUcsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDckIsT0FBTztvQkFDTCxJQUFJLEVBQUUsRUFBRSxRQUFRLEVBQUUscUJBQXFCLEVBQUU7aUJBQzFDLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztZQUVMLElBQUksQ0FBQztnQkFDSCxNQUFNLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxhQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztnQkFDekQsTUFBTSxLQUFLLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzdDLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUMzQyxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsbURBQW1ELENBQUMsQ0FBQztZQUMvRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy9cbi8vIFRlc3RzIGZvciBCaXRHbyBPYmplY3Rcbi8vXG5cbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgbm9jayBmcm9tICdub2NrJztcbmltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpO1xuXG5pbXBvcnQgeyBjb21tb24sIGdlbmVyYXRlR1BHS2V5UGFpciB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBiaXAzMiwgRUNQYWlyIH0gZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCAqIGFzIEJpdEdvSlMgZnJvbSAnLi4vLi4vc3JjL2luZGV4JztcbmNvbnN0IHJwID0gcmVxdWlyZSgncmVxdWVzdC1wcm9taXNlJyk7XG5cbmltcG9ydCB7IFRlc3RCaXRHbyB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uL3NyYy9iaXRnbyc7XG5cbm5vY2suZGlzYWJsZU5ldENvbm5lY3QoKTtcblxuZGVzY3JpYmUoJ0JpdEdvIFByb3RvdHlwZSBNZXRob2RzJywgZnVuY3Rpb24gKCkge1xuICBkZXNjcmliZSgnVmVyc2lvbicsICgpID0+IHtcbiAgICBpdCgndmVyc2lvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgICAgY29uc3QgdmVyc2lvbiA9IGJpdGdvLnZlcnNpb24oKTtcbiAgICAgIHZlcnNpb24uc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2YWxpZGF0ZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGdldCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICAgIGJpdGdvLmdldFZhbGlkYXRlKCkuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICBiaXRnby5zZXRWYWxpZGF0ZShmYWxzZSk7XG4gICAgICBiaXRnby5nZXRWYWxpZGF0ZSgpLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgICBiaXRnb1snX3ZhbGlkYXRlJ10uc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0Vudmlyb25tZW50cycsICgpID0+IHtcbiAgICBpdCgncHJvZHVjdGlvbicsICgpID0+IHtcbiAgICAgIEJpdEdvSlMuc2V0TmV0d29yaygndGVzdG5ldCcpO1xuICAgICAgVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3Byb2QnIH0pO1xuICAgICAgQml0R29KUy5nZXROZXR3b3JrKCkuc2hvdWxkLmVxdWFsKCdiaXRjb2luJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc3RhZ2luZycsICgpID0+IHtcbiAgICAgIEJpdEdvSlMuc2V0TmV0d29yaygndGVzdG5ldCcpO1xuICAgICAgVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3N0YWdpbmcnIH0pO1xuICAgICAgQml0R29KUy5nZXROZXR3b3JrKCkuc2hvdWxkLmVxdWFsKCd0ZXN0bmV0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgndGVzdCcsICgpID0+IHtcbiAgICAgIEJpdEdvSlMuc2V0TmV0d29yaygnYml0Y29pbicpO1xuICAgICAgVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgICAgQml0R29KUy5nZXROZXR3b3JrKCkuc2hvdWxkLmVxdWFsKCd0ZXN0bmV0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGV2JywgKCkgPT4ge1xuICAgICAgVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ2RldicgfSk7XG4gICAgICBCaXRHb0pTLmdldE5ldHdvcmsoKS5zaG91bGQuZXF1YWwoJ3Rlc3RuZXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdjdXN0b20gbmV0d29yayAocHJvZCknLCAoKSA9PiB7XG4gICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgY3VzdG9tQml0Y29pbk5ldHdvcms6ICdiaXRjb2luJywgY3VzdG9tUm9vdFVSSTogJ2h0dHA6Ly9yb290dXJpLmV4YW1wbGUnIH0pO1xuICAgICAgQml0R29KUy5nZXROZXR3b3JrKCkuc2hvdWxkLmVxdWFsKCdiaXRjb2luJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnY3VzdG9tIG5ldHdvcmsgKHRlc3RuZXQpJywgKCkgPT4ge1xuICAgICAgVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGN1c3RvbUJpdGNvaW5OZXR3b3JrOiAndGVzdG5ldCcsIGN1c3RvbVJvb3RVUkk6ICdodHRwOi8vcm9vdHVyaS5leGFtcGxlJyB9KTtcbiAgICAgIEJpdEdvSlMuZ2V0TmV0d29yaygpLnNob3VsZC5lcXVhbCgndGVzdG5ldCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnSE1BQyByZXF1ZXN0IHZlcmlmaWNhdGlvbicsICgpID0+IHtcbiAgICBpdCgndGhyb3dzIGlmIEhNQUMgcmVxdWVzdCB2ZXJpZmljYXRpb24gaXMgZGlzYWJsZWQgZm9yIG5vbi1wcm9kIGVudmlyb25tZW50cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAncHJvZCcsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlIH0pKS5zaG91bGQudGhyb3coXG4gICAgICAgIC9DYW5ub3QgZGlzYWJsZSByZXF1ZXN0IEhNQUMgdmVyaWZpY2F0aW9uIGluIGVudmlyb25tZW50L1xuICAgICAgKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAndGVzdCcsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlIH0pKS5zaG91bGQubm90LnRocm93KFxuICAgICAgICAvQ2Fubm90IGRpc2FibGUgcmVxdWVzdCBITUFDIHZlcmlmaWNhdGlvbiBpbiBlbnZpcm9ubWVudC9cbiAgICAgICk7XG4gICAgICAoKCkgPT4gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ2FkbWluUHJvZCcsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlIH0pKS5zaG91bGQudGhyb3coXG4gICAgICAgIC9DYW5ub3QgZGlzYWJsZSByZXF1ZXN0IEhNQUMgdmVyaWZpY2F0aW9uIGluIGVudmlyb25tZW50L1xuICAgICAgKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnYWRtaW5UZXN0JywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC5ub3QudGhyb3coXG4gICAgICAgIC9DYW5ub3QgZGlzYWJsZSByZXF1ZXN0IEhNQUMgdmVyaWZpY2F0aW9uIGluIGVudmlyb25tZW50L1xuICAgICAgKTtcbiAgICAgICgoKSA9PlxuICAgICAgICBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHtcbiAgICAgICAgICBlbnY6ICdkZXYnLFxuICAgICAgICAgIGN1c3RvbVJvb3RVUkk6ICdodHRwOi8vcm9vdHVyaS5leGFtcGxlJyxcbiAgICAgICAgICBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSxcbiAgICAgICAgfSkpLnNob3VsZC5ub3QudGhyb3coL0Nhbm5vdCBkaXNhYmxlIHJlcXVlc3QgSE1BQyB2ZXJpZmljYXRpb24gaW4gZW52aXJvbm1lbnQvKTtcbiAgICB9KTtcblxuICAgIGl0KCdhbGxvd3MgZGlzYWJsaW5nIG9mIEhNQUMgcmVxdWVzdCB2ZXJpZmljYXRpb24gb25seSBmb3IgZGV2IGVudmlyb25tZW50cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnZGV2JywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC5ub3QudGhyb3coKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbGF0ZXN0JywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC5ub3QudGhyb3coKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnYWRtaW5EZXYnLCBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSB9KSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgKCgpID0+IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdhZG1pbkxhdGVzdCcsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlIH0pKS5zaG91bGQubm90LnRocm93KCk7XG4gICAgICAoKCkgPT4gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ2xvY2FsJywgaG1hY1ZlcmlmaWNhdGlvbjogZmFsc2UgfSkpLnNob3VsZC5ub3QudGhyb3coKTtcbiAgICAgICgoKSA9PiBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbG9jYWxOb25TZWN1cmUnLCBobWFjVmVyaWZpY2F0aW9uOiBmYWxzZSB9KSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgKCgpID0+XG4gICAgICAgIFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywge1xuICAgICAgICAgIGVudjogJ2JyYW5jaCcsXG4gICAgICAgICAgY3VzdG9tUm9vdFVSSTogJ2h0dHA6Ly9yb290dXJpLmV4YW1wbGUnLFxuICAgICAgICAgIGhtYWNWZXJpZmljYXRpb246IGZhbHNlLFxuICAgICAgICB9KSkuc2hvdWxkLm5vdC50aHJvdygpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXV0aGVudGljYXRlIGluIE1pY3Jvc2VydmljZXMnLCAoKSA9PiB7XG4gICAgbGV0IGJpdGdvO1xuICAgIGNvbnN0IGF1dGhlbnRpY2F0ZVJlcXVlc3QgPSB7XG4gICAgICB1c2VybmFtZTogJ3Rlc3RAYml0Z28uY29tJyxcbiAgICAgIHBhc3N3b3JkOiAncGFzc3dvcmQnLFxuICAgICAgb3RwOiAnMDAwMDAwJyxcbiAgICAgIGV4dGVuc2libGU6IGZhbHNlLFxuICAgICAgZXh0ZW5zaW9uQWRkcmVzczogJ2FkZHJlc3MnLFxuICAgICAgZm9yY2VTTVM6IGZhbHNlLFxuICAgIH07XG5cbiAgICBpdCgnZ29lcyB0byBtaWNyb3NlcnZpY2VzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycsIG1pY3Jvc2VydmljZXNVcmk6ICdodHRwczovL21pY3Jvc2VydmljZXMudXJpJyB9IGFzIGFueSk7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soQml0R29KUy5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaSlcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHVzZXI6IHtcbiAgICAgICAgICAgIHVzZXJuYW1lOiAndGVzdEBiaXRnby5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYWNjZXNzX3Rva2VuOiAndG9rZW4xMjM1NicsXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGUoYXV0aGVudGljYXRlUmVxdWVzdCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2dvZXMgdG8gbWljcm9zZXJ2aWNlcyBldmVuIHdoZW4gbWljcm9zZXJ2aWNlc1VyaSBpcyBub3Qgc3BlY2lmaWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soQml0R29KUy5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaSlcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHVzZXI6IHtcbiAgICAgICAgICAgIHVzZXJuYW1lOiAndGVzdEBiaXRnby5jb20nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYWNjZXNzX3Rva2VuOiAndG9rZW4xMjM1NicsXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGUoYXV0aGVudGljYXRlUmVxdWVzdCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IEFkZHJlc3MnLCAoKSA9PiB7XG4gICAgbGV0IGJpdGdvO1xuICAgIGJlZm9yZSgoKSA9PiB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZXJyb3JzJywgKCkgPT4ge1xuICAgICAgKCgpID0+IGJpdGdvLnZlcmlmeUFkZHJlc3MoKSkuc2hvdWxkLnRocm93KCk7XG4gICAgICAoKCkgPT4gYml0Z28udmVyaWZ5QWRkcmVzcyh7fSkpLnNob3VsZC50aHJvdygpO1xuXG4gICAgICBiaXRnby52ZXJpZnlBZGRyZXNzKHsgYWRkcmVzczogJ3h5enp5JyB9KS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzdGFuZGFyZCcsICgpID0+IHtcbiAgICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3Byb2QnIH0pO1xuICAgICAgYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6ICcxQnUzYmh3Um1ldkhMQXkxSnJSQjZBZmN4ZmdERzJ2WFJkJyB9KS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgLy8gd3JvbmcgdmVyc2lvbiBieXRlOlxuICAgICAgYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6ICc5RWY3SHN1QnlHQm9ncWtqb0Y1WW5nN01Za3E1VUNkbVp6JyB9KS5zaG91bGQuYmUuZmFsc2UoKTtcblxuICAgICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6ICduNEROaFNpRWFvZHFhaUY5dExZWFRDaDRrRmJkVXp4QkhzJyB9KS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Ayc2gnLCAoKSA9PiB7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdwcm9kJyB9KTtcbiAgICAgIGJpdGdvLnZlcmlmeUFkZHJlc3MoeyBhZGRyZXNzOiAnM1FKbVYzcWZ2TDlTdVlvMzRZaWhBZjNzUkNXM3FTaW55QycgfSkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIC8vIHdyb25nIHZlcnNpb24gYnl0ZTpcbiAgICAgIGJpdGdvLnZlcmlmeUFkZHJlc3MoeyBhZGRyZXNzOiAnSFY4c3dyR2ttZU43WGlnNHZFTnI5M2FRU3JYNGlIamc3RCcgfSkuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICBiaXRnby52ZXJpZnlBZGRyZXNzKHsgYWRkcmVzczogJzJORWVGV2JmdTRFQTFyY0t4NDhlODJNajhkNkZLY1dhd1p3JyB9KS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRW5jcnlwdC9EZWNyeXB0JywgKCkgPT4ge1xuICAgIGNvbnN0IHBhc3N3b3JkID0gJ21pY2tleSBtb3VzZSc7XG4gICAgY29uc3Qgc2VjcmV0ID0gJ3RoaXMgaXMgYSBzZWNyZXQnO1xuXG4gICAgaXQoJ2ludmFsaWQgcGFzc3dvcmQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICAgIGNvbnN0IG9wYXF1ZSA9IGJpdGdvLmVuY3J5cHQoeyBwYXNzd29yZDogcGFzc3dvcmQsIGlucHV0OiBzZWNyZXQgfSk7XG4gICAgICAoKCkgPT4gYml0Z28uZGVjcnlwdCh7IHBhc3N3b3JkOiAnaGFjayBoYWNrJywgaW5wdXQ6IG9wYXF1ZSB9KSkuc2hvdWxkLnRocm93KCk7XG4gICAgfSk7XG5cbiAgICBpdCgndmFsaWQgcGFzc3dvcmQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbyk7XG4gICAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICAgIGNvbnN0IG9wYXF1ZSA9IGJpdGdvLmVuY3J5cHQoeyBwYXNzd29yZDogcGFzc3dvcmQsIGlucHV0OiBzZWNyZXQgfSk7XG4gICAgICBiaXRnby5kZWNyeXB0KHsgcGFzc3dvcmQ6IHBhc3N3b3JkLCBpbnB1dDogb3BhcXVlIH0pLnNob3VsZC5lcXVhbChzZWNyZXQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGFzc3dvcmQgR2VuZXJhdGlvbicsICgpID0+IHtcbiAgICBpdCgnZ2VuZXJhdGVzIGEgcmFuZG9tIHBhc3N3b3JkJywgKCkgPT4ge1xuICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBjb25zdCBwYXNzd29yZCA9IGJpdGdvLmdlbmVyYXRlUmFuZG9tUGFzc3dvcmQoKTtcbiAgICAgIHNob3VsZC5leGlzdChwYXNzd29yZCk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGVzIGEgcmFuZG9tIHBhc3N3b3JkIHdpdGggYSBudW1Xb3JkcyBhcmd1bWVudCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDAwOyBpKyspIHtcbiAgICAgICAgY29uc3QgcGFzc3dvcmQgPSBiaXRnby5nZW5lcmF0ZVJhbmRvbVBhc3N3b3JkKDEwKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHBhc3N3b3JkKTtcbiAgICAgICAgLy8gcmFuZG9tbHkgZ2VuZXJhdGVkIHBhc3N3b3JkIHNob3VsZCBiZSA1NSBjaGFyYWN0ZXJzIHJvdWdobHkgOTIuNSUgb2YgdGhlIHRpbWUsXG4gICAgICAgIC8vIDU0IGNoYXJhY3RlcnMgcm91Z2hseSA3LjUlIG9mIHRoZSB0aW1lLCA1MyBjaGFyYWN0ZXJzIDAuMDAxJSBvZiB0aGUgdGltZSxcbiAgICAgICAgLy8gYW5kIGZld2VyIHRoYW4gNTMgY2hhcmFjdGVycyB2ZXJ5LCB2ZXJ5IHJhcmVseVxuICAgICAgICBwYXNzd29yZC5sZW5ndGguc2hvdWxkLmJlLndpdGhpbig1MywgNTUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2hhbWlyIFNlY3JldCBTaGFyaW5nJywgKCkgPT4ge1xuICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICBjb25zdCBzZWVkID0gJzhjYzU3ZGFjOWNkYWU0MmJmNzg0OGEyZDEyZjI4NzRkMzFlY2ExZjlkZThmZTNmOGZhMTNlNzg1N2I1NDVkNTknO1xuICAgIGNvbnN0IHhwdWIgPVxuICAgICAgJ3hwdWI2NjFNeU13QXFSYmNFdXNSamtKNjRCWGdSOGRkWXNYYnVESmZiUmMzZVpjWlZFYTJ5Z3N3RGlGWlFwSEZzQTVOMjExWUR2aTJOODk4aDRLcmNYY2ZzUjhQTGhqSmFQVXdDVXFnMXB0QkJITic7XG4gICAgY29uc3QgcGFzc3dvcmRzID0gWydtaWNrZXknLCAnbW91c2UnLCAnZG9uYWxkJywgJ2R1Y2snXTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBzcGxpdCBzZWNyZXQgd2l0aCB3cm9uZyBtJywgKCkgPT4ge1xuICAgICAgKCgpID0+XG4gICAgICAgIGJpdGdvLnNwbGl0U2VjcmV0KHtcbiAgICAgICAgICBzZWVkLFxuICAgICAgICAgIHBhc3N3b3JkczogWydhYmMnXSxcbiAgICAgICAgICBtOiAwLFxuICAgICAgICB9KSkuc2hvdWxkLnRocm93KCdtIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAyJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gc3BsaXQgc2VjcmV0IHdpdGggYmFkIHBhc3N3b3JkIGNvdW50JywgKCkgPT4ge1xuICAgICAgKCgpID0+XG4gICAgICAgIGJpdGdvLnNwbGl0U2VjcmV0KHtcbiAgICAgICAgICBzZWVkLFxuICAgICAgICAgIHBhc3N3b3JkczogWydhYmMnXSxcbiAgICAgICAgICBtOiAyLFxuICAgICAgICB9KSkuc2hvdWxkLnRocm93KCdwYXNzd29yZHMgYXJyYXkgbGVuZ3RoIGNhbm5vdCBiZSBsZXNzIHRoYW4gbScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzcGxpdCBhbmQgZmFpbCB0byByZWNvbnN0aXR1dGUgc2VjcmV0IHdpdGggYmFkIHBhc3N3b3JkcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHNwbGl0U2VjcmV0ID0gYml0Z28uc3BsaXRTZWNyZXQoeyBzZWVkLCBwYXNzd29yZHM6IHBhc3N3b3JkcywgbTogMyB9KTtcbiAgICAgIGNvbnN0IHNoYXJkcyA9IF8uYXQoc3BsaXRTZWNyZXQuc2VlZFNoYXJlcywgWzAsIDJdKTtcbiAgICAgIGNvbnN0IHN1YnNldFBhc3N3b3JkcyA9IF8uYXQocGFzc3dvcmRzLCBbMCwgM10pO1xuICAgICAgKCgpID0+XG4gICAgICAgIGJpdGdvLnJlY29uc3RpdHV0ZVNlY3JldCh7XG4gICAgICAgICAgc2hhcmRzLFxuICAgICAgICAgIHBhc3N3b3Jkczogc3Vic2V0UGFzc3dvcmRzLFxuICAgICAgICAgIHhwdWIsXG4gICAgICAgIH0gYXMgYW55KSkuc2hvdWxkLnRocm93KC9jY206IHRhZyBkb2Vzbid0IG1hdGNoLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNwbGl0IGFuZCByZWNvbnN0aXR1dGUgc2VjcmV0JywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3BsaXRTZWNyZXQgPSBiaXRnby5zcGxpdFNlY3JldCh7IHNlZWQsIHBhc3N3b3JkczogcGFzc3dvcmRzLCBtOiAyIH0pO1xuICAgICAgY29uc3Qgc2hhcmRzID0gXy5hdChzcGxpdFNlY3JldC5zZWVkU2hhcmVzLCBbMCwgMl0pO1xuICAgICAgY29uc3Qgc3Vic2V0UGFzc3dvcmRzID0gXy5hdChwYXNzd29yZHMsIFswLCAyXSk7XG4gICAgICBjb25zdCByZWNvbnN0aXR1dGVkU2VlZCA9IGJpdGdvLnJlY29uc3RpdHV0ZVNlY3JldCh7IHNoYXJkcywgcGFzc3dvcmRzOiBzdWJzZXRQYXNzd29yZHMgfSk7XG4gICAgICByZWNvbnN0aXR1dGVkU2VlZC5zZWVkLnNob3VsZC5lcXVhbChzZWVkKTtcbiAgICAgIHJlY29uc3RpdHV0ZWRTZWVkLnhwdWIuc2hvdWxkLmVxdWFsKFxuICAgICAgICAneHB1YjY2MU15TXdBcVJiY0V1c1Jqa0o2NEJYZ1I4ZGRZc1hidURKZmJSYzNlWmNaVkVhMnlnc3dEaUZaUXBIRnNBNU4yMTFZRHZpMk44OThoNEtyY1hjZnNSOFBMaGpKYVBVd0NVcWcxcHRCQkhOJ1xuICAgICAgKTtcbiAgICAgIHJlY29uc3RpdHV0ZWRTZWVkLnhwcnYuc2hvdWxkLmVxdWFsKFxuICAgICAgICAneHBydjlzMjFaclFIMTQzSzJSbnhkaW01aDNhd3M2bzk5UW9rWHpQNG8zQ1M2RTVhY1NFdFM5WmdmdXc1Wld1amhUSFRXRUFaRGZtUDN5eEExQ2NuNm15VmtHRXBSclQ0eFdnYUVwb1c3WWlCQXRDJ1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3BsaXQgYW5kIGluY29ycmVjdGx5IHZlcmlmeSBzZWNyZXQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzcGxpdFNlY3JldCA9IGJpdGdvLnNwbGl0U2VjcmV0KHsgc2VlZCwgcGFzc3dvcmRzOiBwYXNzd29yZHMsIG06IDMgfSk7XG4gICAgICBjb25zdCBpc1ZhbGlkID0gYml0Z28udmVyaWZ5U2hhcmRzKHsgc2hhcmRzOiBzcGxpdFNlY3JldC5zZWVkU2hhcmVzLCBwYXNzd29yZHMsIG06IDIgfSBhcyBhbnkpO1xuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzcGxpdCBhbmQgdmVyaWZ5IHNlY3JldCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHNwbGl0U2VjcmV0ID0gYml0Z28uc3BsaXRTZWNyZXQoeyBzZWVkLCBwYXNzd29yZHM6IHBhc3N3b3JkcywgbTogMiB9KTtcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBiaXRnby52ZXJpZnlTaGFyZHMoeyBzaGFyZHM6IHNwbGl0U2VjcmV0LnNlZWRTaGFyZXMsIHBhc3N3b3JkcywgbTogMiwgeHB1YiB9KTtcbiAgICAgIGlzVmFsaWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzcGxpdCBhbmQgdmVyaWZ5IHNlY3JldCB3aXRoIG1hbnkgcGFydHMnLCAoKSA9PiB7XG4gICAgICBjb25zdCBhbGxQd3MgPSBbJzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNyddO1xuICAgICAgY29uc3Qgc3BsaXRTZWNyZXQgPSBiaXRnby5zcGxpdFNlY3JldCh7IHNlZWQsIHBhc3N3b3JkczogYWxsUHdzLCBtOiAzIH0pO1xuICAgICAgY29uc3QgaXNWYWxpZCA9IGJpdGdvLnZlcmlmeVNoYXJkcyh7IHNoYXJkczogc3BsaXRTZWNyZXQuc2VlZFNoYXJlcywgcGFzc3dvcmRzOiBhbGxQd3MsIG06IDMsIHhwdWIgfSk7XG4gICAgICBpc1ZhbGlkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0VDREggc2hhcmluZyBzZWNyZXQnLCAoKSA9PiB7XG4gICAgZnVuY3Rpb24gZ2V0S2V5KHNlZWQ6IHN0cmluZykge1xuICAgICAgcmV0dXJuIEVDUGFpci5mcm9tUHJpdmF0ZUtleShcbiAgICAgICAgYmlwMzIuZnJvbVNlZWQoY3J5cHRvLmNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShzZWVkKS5kaWdlc3QoKSkucHJpdmF0ZUtleSBhcyBCdWZmZXJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaXQoJ3Nob3VsZCBjYWxjdWxhdGUgYSBuZXcgRUNESCBzaGFyaW5nIHNlY3JldCBjb3JyZWN0bHknLCAoKSA9PiB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvKTtcbiAgICAgICAgY29uc3QgZWNrZXkxID0gZ2V0S2V5KGAke2l9LmFgKTtcbiAgICAgICAgY29uc3QgZWNrZXkyID0gZ2V0S2V5KGAke2l9LmJgKTtcbiAgICAgICAgY29uc3Qgc2hhcmluZ0tleTEgPSBiaXRnby5nZXRFQ0RIU2VjcmV0KHsgZWNrZXk6IGVja2V5MSwgb3RoZXJQdWJLZXlIZXg6IGVja2V5Mi5wdWJsaWNLZXkudG9TdHJpbmcoJ2hleCcpIH0pO1xuICAgICAgICBjb25zdCBzaGFyaW5nS2V5MiA9IGJpdGdvLmdldEVDREhTZWNyZXQoeyBlY2tleTogZWNrZXkyLCBvdGhlclB1YktleUhleDogZWNrZXkxLnB1YmxpY0tleS50b1N0cmluZygnaGV4JykgfSk7XG4gICAgICAgIHNoYXJpbmdLZXkxLnNob3VsZC5lcXVhbChzaGFyaW5nS2V5Mik7XG5cbiAgICAgICAgc3dpdGNoIChpKSB7XG4gICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgc2hhcmluZ0tleTEuc2hvdWxkLmVxbCgnNDY1ZmZlNTc0NTMyNTk5OGI4M2ZiMzk2MzEzNDcxNDhlMjRkNGYyMWIzZjNiNTQ3MzljMjY0ZDVjNDJkYjRiOCcpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgc2hhcmluZ0tleTEuc2hvdWxkLmVxbCgnNjFmZjQ0ZmMxYWY4MDYxYTQzM2EzMTRiN2I4YmU4YWUzNTJjMTBmNjJhYWM1ODg3MDQ3ZGJhYTU2NDNiODE4ZCcpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NoYW5nZSBwYXNzd29yZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgYml0Z287XG4gICAgbGV0IGJnVXJsO1xuXG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgICAgIC5wb3N0KCcvYXBpL2F1dGgvdjEvc2Vzc2lvbicpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBhY2Nlc3NfdG9rZW46ICdhY2Nlc3NfdG9rZW4nLFxuICAgICAgICAgIHVzZXI6IHsgdXNlcm5hbWU6ICd1cGRhdGVfcHdfdGVzdGVyQGJpdGdvLmNvbScgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBiaXRnby5zZXRWYWxpZGF0ZShmYWxzZSk7XG5cbiAgICAgIGF3YWl0IGJpdGdvLmF1dGhlbnRpY2F0ZUNoYW5nZVBXVGVzdFVzZXIoYml0Z28udGVzdFVzZXJPVFAoKSk7XG5cbiAgICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICAgIH0pO1xuXG4gICAgY29uc3Qgb2xkUGFzc3dvcmQgPSAnb2xkUGFzc3dvcmQnO1xuICAgIGNvbnN0IG5ld1Bhc3N3b3JkID0gJ25ld1Bhc3N3b3JkJztcbiAgICBjb25zdCBvdGhlclBhc3N3b3JkID0gJ290aGVyUGFzc3dvcmQnO1xuXG4gICAgZGVzY3JpYmUoJ3Nob3VsZCBmYWlsIHRvIGNoYW5nZSB0aGUgcGFzc3dvcmQnLCBmdW5jdGlvbiBjaGFuZ2VQV0ZhaWwoKSB7XG4gICAgICBpdCgnd3JvbmcgYXJndW1lbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBhd2FpdCBiaXRnby5jaGFuZ2VQYXNzd29yZCh7IG5ld1Bhc3N3b3JkOiAnNTY3OCcgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnZXhwZWN0ZWQgc3RyaW5nIG9sZFBhc3N3b3JkJyk7XG4gICAgICAgIGF3YWl0IGJpdGdvXG4gICAgICAgICAgLmNoYW5nZVBhc3N3b3JkKHsgb2xkUGFzc3dvcmQ6IDEyMzQsIG5ld1Bhc3N3b3JkOiAnNTY3OCcgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnZXhwZWN0ZWQgc3RyaW5nIG9sZFBhc3N3b3JkJyk7XG4gICAgICAgIGF3YWl0IGJpdGdvLmNoYW5nZVBhc3N3b3JkKHsgb2xkUGFzc3dvcmQ6ICcxMjM0JyB9KS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdleHBlY3RlZCBzdHJpbmcgbmV3UGFzc3dvcmQnKTtcbiAgICAgICAgYXdhaXQgYml0Z29cbiAgICAgICAgICAuY2hhbmdlUGFzc3dvcmQoeyBvbGRQYXNzd29yZDogJzEyMzQnLCBuZXdQYXNzd29yZDogNTY3OCB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdleHBlY3RlZCBzdHJpbmcgbmV3UGFzc3dvcmQnKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnaW5jb3JyZWN0IG9sZCBwYXNzd29yZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS91c2VyL3ZlcmlmeXBhc3N3b3JkJykucmVwbHkoMjAwLCB7IHZhbGlkOiBmYWxzZSB9KTtcbiAgICAgICAgYXdhaXQgYml0Z29cbiAgICAgICAgICAuY2hhbmdlUGFzc3dvcmQoeyBvbGRQYXNzd29yZCwgbmV3UGFzc3dvcmQgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgndGhlIHByb3ZpZGVkIG9sZFBhc3N3b3JkIGlzIGluY29ycmVjdCcpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc3VjY2Vzc2Z1bCBwYXNzd29yZCBjaGFuZ2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL3VzZXIvdmVyaWZ5cGFzc3dvcmQnKS5yZXBseSgyMDAsIHsgdmFsaWQ6IHRydWUgfSk7XG5cbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KCcvYXBpL3YxL3VzZXIvZW5jcnlwdGVkJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHZlcnNpb246IDEsXG4gICAgICAgICAga2V5Y2hhaW5zOiB7XG4gICAgICAgICAgICB4cHViMTE6IGJpdGdvLmVuY3J5cHQoeyBpbnB1dDogJ3hwcnYxMScsIHBhc3N3b3JkOiBvbGRQYXNzd29yZCB9KSxcbiAgICAgICAgICAgIHhwdWIxMjogYml0Z28uZW5jcnlwdCh7IGlucHV0OiAneHBydjEyJywgcGFzc3dvcmQ6IG9sZFBhc3N3b3JkIH0pLFxuICAgICAgICAgICAgeHB1YjEzOiBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6ICd4cHJ2MTMnLCBwYXNzd29yZDogb3RoZXJQYXNzd29yZCB9KSxcbiAgICAgICAgICAgIHhwdWIxNDogYml0Z28uZW5jcnlwdCh7IGlucHV0OiAneHBydjE0JywgcGFzc3dvcmQ6IG9sZFBhc3N3b3JkIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyL3RidGMva2V5JylcbiAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBrZXlzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHB1YjogJ3hwdWIyMScsXG4gICAgICAgICAgICAgIGVuY3J5cHRlZFBydjogYml0Z28uZW5jcnlwdCh7IGlucHV0OiAneHBydjIxJywgcGFzc3dvcmQ6IG9sZFBhc3N3b3JkIH0pLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcHViOiAneHB1YjIyJyxcbiAgICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6ICd4cHJ2MjInLCBwYXNzd29yZDogb3RoZXJQYXNzd29yZCB9KSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSk7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvdXNlci9jaGFuZ2VwYXNzd29yZCcpLnJlcGx5KDIwMCwge30pO1xuXG4gICAgICBhd2FpdCBiaXRnby5jaGFuZ2VQYXNzd29yZCh7IG9sZFBhc3N3b3JkLCBuZXdQYXNzd29yZCB9KTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiBhZnRlckNoYW5nZVBhc3N3b3JkKCkge1xuICAgICAgbm9jay5wZW5kaW5nTW9ja3MoKS5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0hNQUMgSGFuZGxpbmcnLCAoKSA9PiB7XG4gICAgbGV0IGJpdGdvO1xuICAgIGNvbnN0IHRva2VuID0gJ3YyeDViNzM1ZmVkMjQ4NjU5M2Y4ZmVhMTkxMTNlNWM3MTczMDhmOTBhNWZiMDBlNzQwZTQ2YzdiZmRjYzA3OGNmZDAnO1xuXG4gICAgYmVmb3JlKCgpID0+IHtcbiAgICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snLCBhY2Nlc3NUb2tlbjogdG9rZW4gfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNvcnJlY3RseSBjYWxjdWxhdGUgcmVxdWVzdCBoZWFkZXJzJywgKCkgPT4ge1xuICAgICAgY29uc3Qgb3JpZ2luYWxEYXRlTm93ID0gRGF0ZS5ub3c7XG4gICAgICBEYXRlLm5vdyA9ICgpID0+IDE1MjE1ODk4ODI1MTA7XG5cbiAgICAgIGNvbnN0IGZldGNoTWVVcmwgPSBiaXRnby51cmwoJy91c2VyL21lJyk7XG4gICAgICBjb25zdCByZXF1ZXN0SGVhZGVycyA9IGJpdGdvLmNhbGN1bGF0ZVJlcXVlc3RIZWFkZXJzKHsgdXJsOiBmZXRjaE1lVXJsLCB0b2tlbiB9KTtcbiAgICAgIERhdGUubm93ID0gb3JpZ2luYWxEYXRlTm93O1xuXG4gICAgICByZXF1ZXN0SGVhZGVycy50aW1lc3RhbXAuc2hvdWxkLmVxdWFsKDE1MjE1ODk4ODI1MTApO1xuICAgICAgcmVxdWVzdEhlYWRlcnMudG9rZW5IYXNoLnNob3VsZC5lcXVhbCgnYTg1YWYwOGU2NzIzZTQxYWNkNmEzZmI5ZWY1ODQyMjA4MmU2NzNkZjMzYzU4ZTFkYjE3NWJiNzQwYTJjOTM0ZCcpO1xuICAgICAgcmVxdWVzdEhlYWRlcnMuaG1hYy5zaG91bGQuZXF1YWwoJzZkZTc3ZDVhNTQ0NmEzZTU2NDk0NTZjMTE0ODA3MDZhNzEwNzFiMTU2MzljM2M3ODdhZjY1YmRiMDJlY2YxZWMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY29ycmVjdGx5IGhhbmRsZSBhdXRoZW50aWNhdGlvbiByZXNwb25zZScsICgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlSnNvbiA9IHtcbiAgICAgICAgZW5jcnlwdGVkVG9rZW46XG4gICAgICAgICAgJ3tcIml2XCI6XCJFcXhWYUdUTFk0bmFBWWt1QmFUejB3PT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAsXCJrc1wiOjEyOCxcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCI0UzRkQlljZ0w0cz1cIixcImN0XCI6XCJGZ0JSSmxqYjhpU1l4bkFqTWk0UW90cjdzVEtiU21XbmxmSFpTaE1TaThZZWVFM2tpUzhicEhOVXdBUGhZOHRnb3VoM1VzRXdySm5ZKzU0TXZxRkQ3eWQxOXBHMVY0Q1Zzc3I4XCJ9JyxcbiAgICAgICAgZGVyaXZhdGlvblBhdGg6ICdtLzk5OTk5OS8xMDQ0OTA5NDgvMTczODQ2NjY3JyxcbiAgICAgICAgZW5jcnlwdGVkRUNESFhwcnY6XG4gICAgICAgICAgJ3tcIml2XCI6XCJRS0hFRjJHTmN3T0p3eTYrcHdBTlJBPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiVzJzVkZ2WERsT3c9XCIsXCJjdFwiOlwiOEJUQ3FTMjVYMzdrTHptelFkR2VuaFhINnpubjlxRW1rc3pBZVM4a0xuUmRxS1NpVWlDN2JUQVZnZy9OcDV5clY3RjdKeWlxK01UcFZUNzZFb1VUK1BNSnpBcnYwZ1VRS0MySlBCM0p1VktlQUFWV0JRbWhXZmtFd1JmeXY0aHE0V014d1p0b2N3QnFUaHZkMnBKbTlIRTUxR1g0L1dvPVwifScsXG4gICAgICB9O1xuICAgICAgY29uc3QgcGFyc2VkQXV0aGVudGljYXRpb25EYXRhID0gYml0Z28uaGFuZGxlVG9rZW5Jc3N1YW5jZShyZXNwb25zZUpzb24sICd0ZXN0QGJpdGdvLmNvbScpO1xuICAgICAgcGFyc2VkQXV0aGVudGljYXRpb25EYXRhLnRva2VuLnNob3VsZC5lcXVhbCh0b2tlbik7XG4gICAgICBwYXJzZWRBdXRoZW50aWNhdGlvbkRhdGEuZWNkaFhwcnYuc2hvdWxkLmVxdWFsKFxuICAgICAgICAneHBydjlzMjFaclFIMTQzSzNzaTFiS0dwN0txZ0NRdjM5dHRRN2FVd1d6VmR5dGdIZDhIdERDSHlFcDE0bXhmaGlUM3FIVHE0QmFTckE3dVVrRzZBSlRmUEpCc1J1NjNkcnZCcVl1TVp5VHhlcEg3J1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY29ycmVjdGx5IHZlcmlmeSBhIHJlc3BvbnNlIGhtYWMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1cmwgPSBiaXRnb1xuICAgICAgICAuY29pbigndGx0YycpXG4gICAgICAgIC51cmwoJy93YWxsZXQvNTk0MWIyMDJiNDJmY2JjNzA3MTcwZDViNTk3NDkxZDkvYWRkcmVzcy9RTmM0UkZBY2J2cW10clIxa1Iyd2JHTEN4NnRFdm9qRllFP3NlZ3dpdD0xJyk7XG4gICAgICBjb25zdCByZXF1ZXN0SGVhZGVyRGF0YSA9IGJpdGdvLmNhbGN1bGF0ZVJlcXVlc3RIZWFkZXJzKHsgdXJsLCB0b2tlbiB9KTtcbiAgICAgIGNvbnN0IHJlcXVlc3RIZWFkZXJzID0ge1xuICAgICAgICAnQml0R28tQXV0aC1WZXJzaW9uJzogJzIuMCcsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICdBdXRoLVRpbWVzdGFtcCc6IHJlcXVlc3RIZWFkZXJEYXRhLnRpbWVzdGFtcCxcbiAgICAgICAgQXV0aG9yaXphdGlvbjogJ0JlYXJlciAnICsgcmVxdWVzdEhlYWRlckRhdGEudG9rZW5IYXNoLFxuICAgICAgICBITUFDOiByZXF1ZXN0SGVhZGVyRGF0YS5obWFjLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlQm9keSA9XG4gICAgICAgICd7XCJpZFwiOlwiNWE3Y2E4YmNhZjUyYzhlODA3YzU3NWZiNjkyNjA5ZWNcIixcImFkZHJlc3NcIjpcIlFOYzRSRkFjYnZxbXRyUjFrUjJ3YkdMQ3g2dEV2b2pGWUVcIixcImNoYWluXCI6MCxcImluZGV4XCI6MixcImNvaW5cIjpcInRsdGNcIixcIndhbGxldFwiOlwiNTk0MWIyMDJiNDJmY2JjNzA3MTcwZDViNTk3NDkxZDlcIixcImNvaW5TcGVjaWZpY1wiOntcInJlZGVlbVNjcmlwdFwiOlwiNTIyMTAyODM1YmNmZDEzMGY3YTU2ZjcyYzkwNWI3ODJkOTBiNjZlMjJmODhhZDMzMDljZjcyYWY1MTM4YTdkNDRiZThiMzIxMDMyMmM3ZjQyYTFlYjIxMjg2OGVhYjc4ZGI3YmE2NDg0NjA3NWQ5OGM3ZjRjN2FhMjVhMDJlNTc4NzEwMzllMGNkMjEwMjY1ODI1YmUwZDViZjk1N2ZiNzJhYmQ3YzIzYmYwODM2YTc4YTE1Zjk1MWEwNzM0NjdjZDVjOTllMDNjZTdhYjc1M2FlXCJ9LFwiYmFsYW5jZVwiOntcInVwZGF0ZWRcIjpcIjIwMTgtMDItMjhUMjM6NDg6MDcuMzQxWlwiLFwibnVtVHhcIjoxLFwibnVtVW5zcGVudHNcIjoxLFwidG90YWxSZWNlaXZlZFwiOjIwMDAwMDAwfX0nO1xuXG4gICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnLCB7IHJlcWhlYWRlcnM6IHJlcXVlc3RIZWFkZXJzIH0pXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvdGx0Yy93YWxsZXQvNTk0MWIyMDJiNDJmY2JjNzA3MTcwZDViNTk3NDkxZDkvYWRkcmVzcy9RTmM0UkZBY2J2cW10clIxa1Iyd2JHTEN4NnRFdm9qRllFP3NlZ3dpdD0xJylcbiAgICAgICAgLnJlcGx5KDIwMCwgcmVzcG9uc2VCb2R5LCB7XG4gICAgICAgICAgaG1hYzogJzMwYTU5NDMwNDNhYjRiMDUwM2Q4MDdmMGNjYTdkYWMzYTY3MGU4Nzg1MzMxMzIyNTY3ZGI1MTg5NDMyYjg3ZWMnLFxuICAgICAgICAgIHRpbWVzdGFtcDogJzE1MjE1OTA1MzI5MjUnLFxuICAgICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzcG9uc2VEYXRhID0gKGF3YWl0IHJwKHtcbiAgICAgICAgdXJpOiB1cmwsXG4gICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgIGhlYWRlcnM6IHJlcXVlc3RIZWFkZXJzLFxuICAgICAgICB0cmFuc2Zvcm06IChib2R5LCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIC8vIHZlcmlmeSB0aGUgcmVzcG9uc2UgaGVhZGVyc1xuICAgICAgICAgIGNvbnN0IHVybCA9IHJlc3BvbnNlLnJlcXVlc3QuaHJlZjtcbiAgICAgICAgICBjb25zdCBobWFjID0gcmVzcG9uc2UuaGVhZGVycy5obWFjO1xuICAgICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IHJlc3BvbnNlLmhlYWRlcnMudGltZXN0YW1wO1xuICAgICAgICAgIGNvbnN0IHN0YXR1c0NvZGUgPSByZXNwb25zZS5zdGF0dXNDb2RlO1xuICAgICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvblBhcmFtcyA9IHtcbiAgICAgICAgICAgIHVybCxcbiAgICAgICAgICAgIGhtYWMsXG4gICAgICAgICAgICB0aW1lc3RhbXAsXG4gICAgICAgICAgICB0b2tlbixcbiAgICAgICAgICAgIHN0YXR1c0NvZGUsXG4gICAgICAgICAgICB0ZXh0OiBib2R5LFxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIGJpdGdvLnZlcmlmeVJlc3BvbnNlKHZlcmlmaWNhdGlvblBhcmFtcyk7XG4gICAgICAgIH0sXG4gICAgICB9KSkgYXMgYW55O1xuICAgICAgcmVzcG9uc2VEYXRhLnNpZ25hdHVyZVN1YmplY3Quc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMTUyMTU5MDUzMjkyNXwvYXBpL3YyL3RsdGMvd2FsbGV0LzU5NDFiMjAyYjQyZmNiYzcwNzE3MGQ1YjU5NzQ5MWQ5L2FkZHJlc3MvUU5jNFJGQWNidnFtdHJSMWtSMndiR0xDeDZ0RXZvakZZRT9zZWd3aXQ9MXwyMDB8e1wiaWRcIjpcIjVhN2NhOGJjYWY1MmM4ZTgwN2M1NzVmYjY5MjYwOWVjXCIsXCJhZGRyZXNzXCI6XCJRTmM0UkZBY2J2cW10clIxa1Iyd2JHTEN4NnRFdm9qRllFXCIsXCJjaGFpblwiOjAsXCJpbmRleFwiOjIsXCJjb2luXCI6XCJ0bHRjXCIsXCJ3YWxsZXRcIjpcIjU5NDFiMjAyYjQyZmNiYzcwNzE3MGQ1YjU5NzQ5MWQ5XCIsXCJjb2luU3BlY2lmaWNcIjp7XCJyZWRlZW1TY3JpcHRcIjpcIjUyMjEwMjgzNWJjZmQxMzBmN2E1NmY3MmM5MDViNzgyZDkwYjY2ZTIyZjg4YWQzMzA5Y2Y3MmFmNTEzOGE3ZDQ0YmU4YjMyMTAzMjJjN2Y0MmExZWIyMTI4NjhlYWI3OGRiN2JhNjQ4NDYwNzVkOThjN2Y0YzdhYTI1YTAyZTU3ODcxMDM5ZTBjZDIxMDI2NTgyNWJlMGQ1YmY5NTdmYjcyYWJkN2MyM2JmMDgzNmE3OGExNWY5NTFhMDczNDY3Y2Q1Yzk5ZTAzY2U3YWI3NTNhZVwifSxcImJhbGFuY2VcIjp7XCJ1cGRhdGVkXCI6XCIyMDE4LTAyLTI4VDIzOjQ4OjA3LjM0MVpcIixcIm51bVR4XCI6MSxcIm51bVVuc3BlbnRzXCI6MSxcInRvdGFsUmVjZWl2ZWRcIjoyMDAwMDAwMH19J1xuICAgICAgKTtcbiAgICAgIHJlc3BvbnNlRGF0YS5leHBlY3RlZEhtYWMuc2hvdWxkLmVxdWFsKCczMGE1OTQzMDQzYWI0YjA1MDNkODA3ZjBjY2E3ZGFjM2E2NzBlODc4NTMzMTMyMjU2N2RiNTE4OTQzMmI4N2VjJyk7XG4gICAgICByZXNwb25zZURhdGEuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgcmVxdWVzdCBib2R5IGFzIHBhcnQgb2YgdGhlIGhtYWMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1cmwgPSAnaHR0cHM6Ly9iaXRnby5mYWtldXJsJztcbiAgICAgIGNvbnN0IGJvZHkgPSB7IHRlc3Q6ICd0ZXN0JyB9O1xuXG4gICAgICBjb25zdCBmaXhlZFVuaXhUaW1lID0gMTYyNzM3NDY0NjtcbiAgICAgIGNvbnN0IG9yaWdpbmFsRGF0ZU5vdyA9IERhdGUubm93O1xuICAgICAgRGF0ZS5ub3cgPSAoKSA9PiBmaXhlZFVuaXhUaW1lO1xuXG4gICAgICB0cnkge1xuICAgICAgICBub2NrKHVybClcbiAgICAgICAgICAucG9zdCgnLycsIGJvZHkpXG4gICAgICAgICAgLnJlcGx5KDIwMSwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgICBobWFjOiAnNjc3ZTBjOWE2NWNhMzg0NDE1OTQ1Y2IxOWI0MGFlMzhlYWFkZmJjZTNjY2NlOGM1ZDdiZjM3YzE5NzNiMjU1MycsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IFN0cmluZyhmaXhlZFVuaXhUaW1lKSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXNwID0gKGF3YWl0IGJpdGdvLnBvc3QodXJsKS5zZW5kKGJvZHkpKSBhcyBhbnk7XG4gICAgICAgIHJlc3AucmVxLmhlYWRlcnNbJ2htYWMnXS5zaG91bGQuZXF1YWwoJzQ0MjVhNDAwNGVmMjcyNGFkZDI1YjRkZDAxOWQyMWM2NjM5NDY1M2EwNDlkODJlMzdkZjNhMmMzNTZiNTcwNmQnKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIERhdGUubm93ID0gb3JpZ2luYWxEYXRlTm93O1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvZ25pemUgdHJhaWxpbmcgc2xhc2ggaW5jb25zaXN0ZW5jeScsICgpID0+IHtcbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvblBhcmFtcyA9IHtcbiAgICAgICAgdXJsOiAnaHR0cHM6Ly9nb29nbGUuY29tL2FwaScsXG4gICAgICAgIGhtYWM6ICczMGE1OTQzMDQzYWI0YjA1MDNkODA3ZjBjY2E3ZGFjM2E2NzBlODc4NTMzMTMyMjU2N2RiNTE4OTQzMmI4N2VjJyxcbiAgICAgICAgdGltZXN0YW1wOiAnMTUyMTU5MDUzMjkyNScsXG4gICAgICAgIHRva2VuOiB0b2tlbixcbiAgICAgICAgc3RhdHVzQ29kZTogMjAwLFxuICAgICAgICB0ZXh0OiAnZmFrZWRhdGEnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbkRldGFpbHMgPSBiaXRnby52ZXJpZnlSZXNwb25zZSh2ZXJpZmljYXRpb25QYXJhbXMpO1xuICAgICAgdmVyaWZpY2F0aW9uRGV0YWlscy5zaWduYXR1cmVTdWJqZWN0LnNob3VsZC5lcXVhbCgnMTUyMTU5MDUzMjkyNXwvYXBpfDIwMHxmYWtlZGF0YScpO1xuICAgICAgdmVyaWZpY2F0aW9uRGV0YWlscy5zaWduYXR1cmVTdWJqZWN0LnNob3VsZC5ub3QuZXF1YWwoJzE1MjE1OTA1MzI5MjV8L2FwaS98MjAwfGZha2VkYXRhJyk7XG4gICAgICB2ZXJpZmljYXRpb25EZXRhaWxzLmV4cGVjdGVkSG1hYy5zaG91bGQuZXF1YWwoJzIwNjRmMmFkYjE2OGVmODgwOGY2YTQyZjU4OGQ3ZDZiYzE0ZTk4ZThiNDEyMzljNmJiYjczNDllNTJmMjI0OWEnKTtcbiAgICAgIHZlcmlmaWNhdGlvbkRldGFpbHMuaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhdXRvLWFtZW5kIHRyYWlsaW5nIHNsYXNoJywgKCkgPT4ge1xuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uUGFyYW1zID0ge1xuICAgICAgICB1cmw6ICdodHRwczovL2dvb2dsZS5jb20nLFxuICAgICAgICBobWFjOiAnMzBhNTk0MzA0M2FiNGIwNTAzZDgwN2YwY2NhN2RhYzNhNjcwZTg3ODUzMzEzMjI1NjdkYjUxODk0MzJiODdlYycsXG4gICAgICAgIHRpbWVzdGFtcDogJzE1MjE1OTA1MzI5MjUnLFxuICAgICAgICB0b2tlbjogdG9rZW4sXG4gICAgICAgIHN0YXR1c0NvZGU6IDIwMCxcbiAgICAgICAgdGV4dDogJ2Zha2VkYXRhJyxcbiAgICAgIH07XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb25EZXRhaWxzID0gYml0Z28udmVyaWZ5UmVzcG9uc2UodmVyaWZpY2F0aW9uUGFyYW1zKTtcbiAgICAgIHZlcmlmaWNhdGlvbkRldGFpbHMuc2lnbmF0dXJlU3ViamVjdC5zaG91bGQuZXF1YWwoJzE1MjE1OTA1MzI5MjV8L3wyMDB8ZmFrZWRhdGEnKTtcbiAgICAgIHZlcmlmaWNhdGlvbkRldGFpbHMuZXhwZWN0ZWRIbWFjLnNob3VsZC5lcXVhbCgnNTFjNmQwMjRmMjYxZTE2NmU4YTMyM2Y4ZmEzNmE5YmI4ZDRkMDJiMDc2MzM0YzJhOWFlMGE0OWVmYzU3MjRkNCcpO1xuICAgICAgdmVyaWZpY2F0aW9uRGV0YWlscy5pc1ZhbGlkLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIGhtYWMgdmFsaWRhdGlvbiBpcyBlbmFibGVkLCBhbmQgbm8gdmFsaWQgaG1hYyBoZWFkZXJzIGFyZSByZXR1cm5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVybCA9ICdodHRwczovL2Zha2V1cmwuaW52YWxpZCc7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2sodXJsKS5nZXQoJy8nKS5yZXBseSgyMDApO1xuXG4gICAgICAvLyB0ZXN0IHN1aXRlIGJpdGdvIG9iamVjdCBoYXMgaG1hYyB2ZXJpZmljYXRpb24gZW5hYmxlZCwgc28gaXQgc2hvdWxkIHRocm93IHdoZW4gdGhlIG5vY2sgcmVzcG9uZHNcbiAgICAgIGF3YWl0IGJpdGdvLmdldCh1cmwpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2ludmFsaWQgcmVzcG9uc2UgSE1BQywgcG9zc2libGUgbWFuLWluLXRoZS1taWRkbGUtYXR0YWNrLyk7XG4gICAgICBzY29wZS5kb25lKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCBlbmZvcmNlIGhtYWMgdmVyaWZpY2F0aW9uIGlmIGhtYWMgdmVyaWZpY2F0aW9uIGlzIGRpc2FibGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmcgPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycsIGhtYWNWZXJpZmljYXRpb246IGZhbHNlLCBhY2Nlc3NUb2tlbjogdG9rZW4gfSk7XG4gICAgICBjb25zdCB1cmwgPSAnaHR0cHM6Ly9mYWtldXJsLmludmFsaWQnO1xuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKHVybCkuZ2V0KCcvJykucmVwbHkoMjAwLCB7IG9rOiAxIH0pO1xuXG4gICAgICBjb25zdCByZXMgPSAoYXdhaXQgYmcuZ2V0KHVybCkpIGFzIGFueTtcbiAgICAgIHJlcy5ib2R5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdvaycsIDEpO1xuICAgICAgc2NvcGUuZG9uZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVG9rZW4gRGVmaW5pdGlvbnMgYXQgU3RhcnR1cCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnU2hvdWxkIHJldHVybiBhIG5vbi1lbXB0eSBsaXN0IG9mIHRva2VucyBiZWZvcmUgdGhlIHNlcnZlciByZXNwb25kcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBjb25zdCBjb25zdGFudHMgPSBiaXRnby5nZXRDb25zdGFudHMoKTtcbiAgICAgIGNvbnN0YW50cy5zaG91bGQuaGF2ZS5wcm9wZXJ0eUJ5UGF0aCgnZXRoJywgJ3Rva2VucycsICdsZW5ndGgnKS5ncmVhdGVyVGhhbigwKTtcbiAgICB9KTtcblxuICAgIGFmdGVyKGZ1bmN0aW9uIHRva2VuRGVmaW5pdGlvbnNBZnRlcigpIHtcbiAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdzdXBlcmFnZW50IHdyYXBwZXJzJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBiaXRnbztcbiAgICBsZXQgYmdVcmw7XG4gICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG5cbiAgICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuXG4gICAgICBub2NrKGJnVXJsKS5wYXRjaCgnLycpLnJlcGx5KDIwMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnUEFUQ0ggcmVxdWVzdHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiaXRnby5wYXRjaChiZ1VybCk7XG4gICAgICByZXMuc3RhdHVzLnNob3VsZC5lcXVhbCgyMDApO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgbm9jay5wZW5kaW5nTW9ja3MoKS5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ByZXByb2Nlc3NBdXRoZW50aWNhdGlvblBhcmFtcycsICgpID0+IHtcbiAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgcGFzc2VkIG5vbi1zdHJpbmcgdXNlcm5hbWUgb3IgcGFzc3dvcmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAoKCkgPT4gYml0Z28ucHJlcHJvY2Vzc0F1dGhlbnRpY2F0aW9uUGFyYW1zKHsgdXNlcm5hbWU6IDEyMyB9IGFzIGFueSkpLnNob3VsZC50aHJvdygvZXhwZWN0ZWQgc3RyaW5nIHVzZXJuYW1lLyk7XG4gICAgICAoKCkgPT4gYml0Z28ucHJlcHJvY2Vzc0F1dGhlbnRpY2F0aW9uUGFyYW1zKHsgdXNlcm5hbWU6ICdhYmMnLCBwYXNzd29yZDoge30gfSBhcyBhbnkpKS5zaG91bGQudGhyb3coXG4gICAgICAgIC9leHBlY3RlZCBzdHJpbmcgcGFzc3dvcmQvXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYXV0aGVudGljYXRlJywgZnVuY3Rpb24gKCkge1xuICAgIGFmdGVyRWFjaChmdW5jdGlvbiBlbnN1cmVOb1BlbmRpbmdNb2NrcygpIHtcbiAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdldCB0aGUgZWNkaEtleWNoYWluIGlmIGVuc3VyZUVjZGhLZXljaGFpbiBpcyBzZXQgYW5kIHVzZXIgYWxyZWFkeSBoYXMgZWNkaEtleWNoYWluJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGFjY2Vzc190b2tlbjogJ2FjY2Vzc190b2tlbicsXG4gICAgICAgICAgdXNlcjogeyB1c2VybmFtZTogJ2F1dGgtdGVzdEBiaXRnby5jb20nIH0sXG4gICAgICAgIH0pO1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLmdldCgnL2FwaS92MS91c2VyL3NldHRpbmdzJylcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIHNldHRpbmdzOiB7XG4gICAgICAgICAgICBlY2RoS2V5Y2hhaW46ICdzb21lLWV4aXN0aW5nLXhwdWInLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYml0Z28uYXV0aGVudGljYXRlKHtcbiAgICAgICAgdXNlcm5hbWU6ICdhdXRoLXRlc3RAYml0Z28uY29tJyxcbiAgICAgICAgcGFzc3dvcmQ6ICdwYXNzd29yZDEyMycsXG4gICAgICAgIG90cDogJzAwMDAwMCcsXG4gICAgICAgIGVuc3VyZUVjZGhLZXljaGFpbjogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBzaG91bGQuZXhpc3QocmVzcG9uc2UudXNlci5lY2RoS2V5Y2hhaW4pO1xuICAgICAgcmVzcG9uc2UudXNlci5lY2RoS2V5Y2hhaW4uc2hvdWxkLmVxdWFsKCdzb21lLWV4aXN0aW5nLXhwdWInKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSB0aGUgZWNkaEtleWNoYWluIGlmIGVuc3VyZUVjZGhLZXljaGFpbiBpcyBzZXQgYW5kIHRoZSB1c2VyIGRvZXMgbm90IGFscmVhZHkgaGF2ZSBlY2RoS2V5Y2hhaW4nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgICAgICAucG9zdCgnL2FwaS9hdXRoL3YxL3Nlc3Npb24nKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgYWNjZXNzX3Rva2VuOiAnYWNjZXNzX3Rva2VuJyxcbiAgICAgICAgICB1c2VyOiB7IHVzZXJuYW1lOiAnYXV0aC10ZXN0QGJpdGdvLmNvbScgfSxcbiAgICAgICAgfSk7XG4gICAgICAvKipcbiAgICAgICAqIFRoaXMgaXMge30gYmVjYXVzZSB3YW50IHRvIG1ha2Ugc3VyZSB0aGUgdXNlciBoYXMgbm8gZWNkaFhwdWIgc2V0IGJlZm9yZSB3ZSBzZXQgaXRcbiAgICAgICAqL1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJykuZ2V0KCcvYXBpL3YxL3VzZXIvc2V0dGluZ3MnKS5yZXBseSgyMDAsIHtcbiAgICAgICAgc2V0dGluZ3M6IHt9LFxuICAgICAgfSk7XG4gICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKS5wb3N0KCcvYXBpL3YxL2tleWNoYWluJykucmVwbHkoMjAwLCB7XG4gICAgICAgIHhwdWI6ICdzb21lLXhwdWInLFxuICAgICAgfSk7XG4gICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgICAgICAucHV0KCcvYXBpL3YyL3VzZXIvc2V0dGluZ3MnKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgc2V0dGluZ3M6IHtcbiAgICAgICAgICAgIGVjZGhLZXljaGFpbjogJ3NvbWUteHB1YicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBiaXRnby5hdXRoZW50aWNhdGUoe1xuICAgICAgICB1c2VybmFtZTogJ2F1dGgtdGVzdEBiaXRnby5jb20nLFxuICAgICAgICBwYXNzd29yZDogJ3Bhc3N3b3JkMTIzJyxcbiAgICAgICAgb3RwOiAnMDAwMDAwJyxcbiAgICAgICAgZW5zdXJlRWNkaEtleWNoYWluOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChyZXNwb25zZS51c2VyLmVjZGhLZXljaGFpbik7XG4gICAgICByZXNwb25zZS51c2VyLmVjZGhLZXljaGFpbi5zaG91bGQuZXF1YWwoJ3NvbWUteHB1YicpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncGFzc2tleSBhdXRoZW50aWNhdGlvbicsICgpID0+IHtcbiAgICBhZnRlckVhY2goZnVuY3Rpb24gZW5zdXJlTm9QZW5kaW5nTW9ja3MoKSB7XG4gICAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhdXRoZW50aWNhdGUgd2l0aCBhIHBhc3NrZXknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB1c2VySWQgPSAnMTIzJztcbiAgICAgIGNvbnN0IHBhc3NrZXkgPSBge1wiaWRcIjogXCJpZFwiLCBcInJlc3BvbnNlXCI6IHtcImF1dGhlbnRpY2F0b3JEYXRhXCI6IFwiMTIzXCIsIFwiY2xpZW50RGF0YUpTT05cIjogXCIxMjNcIiwgXCJzaWduYXR1cmVcIjogXCIxMjNcIiwgXCJ1c2VySGFuZGxlXCI6IFwiJHt1c2VySWR9XCJ9fWA7XG4gICAgICBjb25zdCBrZXlQYWlyID0gYXdhaXQgZ2VuZXJhdGVHUEdLZXlQYWlyKCdzZWNwMjU2azEnKTtcblxuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnBlcnNpc3QoKVxuICAgICAgICAuZ2V0KCcvYXBpL3YxL2NsaWVudC9jb25zdGFudHMnKVxuICAgICAgICAucmVwbHkoMjAwLCB7IHR0bDogMzYwMCwgY29uc3RhbnRzOiB7IHBhc3NrZXlCaXRHb0dwZ0tleToga2V5UGFpci5wdWJsaWNLZXkgfSB9KTtcblxuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwgYXN5bmMgKHVyaSwgcmVxdWVzdEJvZHkpID0+IHtcbiAgICAgICAgICBhc3NlcnQodHlwZW9mIHJlcXVlc3RCb2R5ID09PSAnb2JqZWN0Jyk7XG4gICAgICAgICAgc2hvdWxkLmV4aXN0KHJlcXVlc3RCb2R5LnVzZXJJZCk7XG4gICAgICAgICAgc2hvdWxkLmV4aXN0KHJlcXVlc3RCb2R5LnBhc3NrZXkpO1xuICAgICAgICAgIHJlcXVlc3RCb2R5LnVzZXJJZC5zaG91bGQuZXF1YWwodXNlcklkKTtcbiAgICAgICAgICByZXF1ZXN0Qm9keS5wYXNza2V5LnNob3VsZC5lcXVhbChwYXNza2V5KTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYWNjZXNzX3Rva2VuOiAnYWNjZXNzX3Rva2VuJyxcbiAgICAgICAgICAgIHVzZXI6IHsgdXNlcm5hbWU6ICdhdXRoLXRlc3RAYml0Z28uY29tJyB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYml0Z28uYXV0aGVudGljYXRlV2l0aFBhc3NrZXkocGFzc2tleSk7XG4gICAgICBzaG91bGQuZXhpc3QocmVzcG9uc2UuYWNjZXNzX3Rva2VuKTtcbiAgICAgIHJlc3BvbnNlLmFjY2Vzc190b2tlbi5zaG91bGQuZXF1YWwoJ2FjY2Vzc190b2tlbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyAtIGludmFsaWQgdXNlckhhbmRsZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhc3NrZXkgPSBge1wiaWRcIjogXCJpZFwiLCBcInJlc3BvbnNlXCI6IHtcImF1dGhlbnRpY2F0b3JEYXRhXCI6IFwiMTIzXCIsIFwiY2xpZW50RGF0YUpTT05cIjogXCIxMjNcIiwgXCJzaWduYXR1cmVcIjogXCIxMjNcIiwgXCJ1c2VySGFuZGxlXCI6IDEyM319YDtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYml0Z28udmFsaWRhdGVQYXNza2V5UmVzcG9uc2UocGFzc2tleSk7XG4gICAgICAgIGFzc2VydC5mYWlsKCdFeHBlY3RlZCBlcnJvciBub3QgdGhyb3duJyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGFzc2VydC5lcXVhbChlLm1lc3NhZ2UsICd1c2VySGFuZGxlIGlzIG1pc3NpbmcnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHRocm93IC0gaW52YWxpZCBhdXRoZW50aWNhdG9yRGF0YScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhc3NrZXkgPSBge1wiaWRcIjogXCJpZFwiLCBcInJlc3BvbnNlXCI6IHsgXCJjbGllbnREYXRhSlNPTlwiOiBcIjEyM1wiLCBcInNpZ25hdHVyZVwiOiBcIjEyM1wiLCBcInVzZXJIYW5kbGVcIjogXCIxMjNcIn19YDtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYml0Z28udmFsaWRhdGVQYXNza2V5UmVzcG9uc2UocGFzc2tleSk7XG4gICAgICAgIGFzc2VydC5mYWlsKCdFeHBlY3RlZCBlcnJvciBub3QgdGhyb3duJyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGFzc2VydC5lcXVhbChlLm1lc3NhZ2UsICdhdXRoZW50aWNhdG9yRGF0YSBpcyBtaXNzaW5nJyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCB0aHJvdyAtIGludmFsaWQgcGFzc2tleSBqc29uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcGFzc2tleSA9IGB7e1wiaWRcIjogXCJpZFwiLCBcInJlc3BvbnNlXCI6IHsgXCJjbGllbnREYXRhSlNPTlwiOiBcIjEyM1wiLCBcInNpZ25hdHVyZVwiOiBcIjEyM1wiLCBcInVzZXJIYW5kbGVcIjogXCIxMjNcIn19YDtcbiAgICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYml0Z28udmFsaWRhdGVQYXNza2V5UmVzcG9uc2UocGFzc2tleSk7XG4gICAgICAgIGFzc2VydC5mYWlsKCdFeHBlY3RlZCBlcnJvciBub3QgdGhyb3duJyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgICBhc3NlcnQoZS5tZXNzYWdlLmluY2x1ZGVzKCdKU09OJykpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgdGhyb3cgLSBtaXNzaW5nIGFjY2VzcyB0b2tlbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhc3NrZXkgPSBge1wiaWRcIjogXCJpZFwiLCBcInJlc3BvbnNlXCI6IHsgXCJhdXRoZW50aWNhdG9yRGF0YVwiOiBcIjEyM1wiLCBcImNsaWVudERhdGFKU09OXCI6IFwiMTIzXCIsIFwic2lnbmF0dXJlXCI6IFwiMTIzXCIsIFwidXNlckhhbmRsZVwiOiBcIjEyM1wifX1gO1xuICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnBvc3QoJy9hcGkvYXV0aC92MS9zZXNzaW9uJylcbiAgICAgICAgLnJlcGx5KDIwMCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB1c2VyOiB7IHVzZXJuYW1lOiAnYXV0aC10ZXN0QGJpdGdvLmNvbScgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgICAgIGF3YWl0IGJpdGdvLmF1dGhlbnRpY2F0ZVdpdGhQYXNza2V5KHBhc3NrZXkpO1xuICAgICAgICBhc3NlcnQuZmFpbCgnRXhwZWN0ZWQgZXJyb3Igbm90IHRocm93bicpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBhc3NlcnQuZXF1YWwoZS5tZXNzYWdlLCAnRmFpbGVkIHRvIGxvZ2luLiBQbGVhc2UgY29udGFjdCBzdXBwb3J0QGJpdGdvLmNvbScpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19

Выполнить команду


Для локальной разработки. Не используйте в интернете!