PHP WebShell
Текущая директория: /opt/BitGoJS/modules/express/dist/test/integration
Просмотр файла: bitgoExpress.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @prettier
*/
const should = require("should");
require("should-http");
const supertest_1 = require("supertest");
const config_1 = require("../../src/config");
const expressApp_1 = require("../../src/expressApp");
const nock = require("nock");
const sdk_core_1 = require("@bitgo/sdk-core");
describe('Bitgo Express', function () {
let agent;
before(function () {
nock.restore();
const args = {
...config_1.DefaultConfig,
debug: false,
env: 'test',
logfile: '/dev/null',
};
const app = (0, expressApp_1.app)(args);
agent = (0, supertest_1.agent)(app);
});
describe('verify address', function () {
describe('failure', function () {
it('should mark as invalid bad btc address', async function () {
const res = await agent
.post('/api/v2/btc/verifyaddress')
.send({ address: '3P14159f73E4gFr7JterCCQh9QjiTjiZrR' });
res.should.have.status(200);
res.body.isValid.should.equal(false);
});
it('should mark as invalid bad ltc address', async function () {
const res = await agent
.post('/api/v2/ltc/verifyaddress')
.send({ address: '3Ps3MeHaYm2s5WPsRo1kHkCvS8EFawzG7R' });
res.should.have.status(200);
res.body.isValid.should.equal(false);
});
it('should mark as invalid bad tltc address', async function () {
const res = await agent
.post('/api/v2/tltc/verifyaddress')
.send({ address: 'QeKCcxtfqprzZsWZihRgxJk2QJrrLMjS4s' });
res.should.have.status(200);
res.body.isValid.should.equal(false);
});
it('should mark as invalid bad tltc address when not allowing old script hash version', async function () {
const res = await agent
.post('/api/v2/ltc/verifyaddress')
.send({ address: '3Ps3MeHaYm2s5WPsRo1kHkCvS8EFawzG7Q' });
res.should.have.status(200);
res.body.isValid.should.equal(false);
});
it('should mark as invalid bad eth address', async function () {
const res = await agent
.post('/api/v2/eth/verifyaddress')
.send({ address: '0xd4a4aa09f57b7e83cd817ec24df9f86daf253d1' });
res.should.have.status(200);
res.body.isValid.should.equal(false);
});
it('should mark as invalid bad xrp address', async function () {
const res = await agent
.post('/api/v2/xrp/verifyaddress')
.send({ address: 'rw5bfvumHWZirKLG5gUQ89dyqtiUUbmxP' });
res.should.have.status(200);
res.body.isValid.should.equal(false);
});
});
describe('success', function () {
it('should verify valid btc address', async function () {
const res = await agent
.post('/api/v2/btc/verifyaddress')
.send({ address: '3P14159f73E4gFr7JterCCQh9QjiTjiZrG' });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should verify valid tbtc address', async function () {
const res = await agent
.post('/api/v2/tbtc/verifyaddress')
.send({ address: '2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc' });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should verify valid ltc address', async function () {
const res = await agent
.post('/api/v2/ltc/verifyaddress')
.send({ address: 'MW5BfXhYVstHt1fmXg167PTKkpphfP6xQ3' });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should verify old-style P2SH ltc address when allowing old script hash version', async function () {
const res = await agent.post('/api/v2/ltc/verifyaddress').send({
address: '3Ps3MeHaYm2s5WPsRo1kHkCvS8EFawzG7Q',
supportOldScriptHashVersion: true,
});
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should verify tltc address', async function () {
const res = await agent
.post('/api/v2/tltc/verifyaddress')
.send({ address: 'QeKCcxtfqprzZsWZihRgxJk2QJrrLMjS4c' });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should verify valid eth address', async function () {
const res = await agent
.post('/api/v2/eth/verifyaddress')
.send({ address: '0xd4a4aa09f57b7e83cd817ec24df9f86daf253d1d' });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should verify valid xrp address', async function () {
const res = await agent
.post('/api/v2/xrp/verifyaddress')
.send({ address: 'rw5bfvumHWZirKLG5gUQ89dyqtiUUbmxPD' });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
});
});
describe('Request body size limits', () => {
it('should handle request bodies <=20mb', async function () {
// actual number of bytes sent will be roughly 6x the number of bytes in
// the buffer. Therefore, to create a request body between 12mb and 20mb,
// we should create a buffer with between 2e6 and 3.3e6 bytes
const numBytes = Math.floor(Math.random() * 2e6 + 1.3e6);
const res = await agent
.post('/api/v2/btc/verifyaddress')
.send({ address: '3P14159f73E4gFr7JterCCQh9QjiTjiZrG', garbage: Buffer.alloc(numBytes).toString('utf8') });
res.should.have.status(200);
res.body.isValid.should.equal(true);
});
it('should fail for request bodies >20mb', async function () {
// actual number of bytes sent will be roughly 6x the number of bytes in
// the buffer. Therefore, to create a request body between 20mb and 25mb,
// we should create a buffer with between 3.334e6 and 4.166e6 bytes.
// we use 3.5e6 instead to give a bit of buffer space (no pun intended)
const numBytes = Math.floor(Math.random() * 0.826e6 + 3.5e6);
const res = await agent
.post('/api/v2/btc/verifyaddress')
.send({ address: '3P14159f73E4gFr7JterCCQh9QjiTjiZrG', garbage: Buffer.alloc(numBytes).toString('utf8') });
res.should.have.status(413);
});
});
it('should not proxy a non-api route', async function () {
const res = await agent.get('/info/solutions').send();
res.should.have.status(404);
});
it('should proxy the oauth/token route', async function () {
const res = await agent.post('/oauth/token').send();
res.should.not.have.status(404);
});
it('should handle coinless routes', async function () {
const routes = [
agent.get('/api/v2/reports/'),
agent.get('/api/v2/wallet/balances/merged/'),
agent.get('/api/v2/enterprise/1234/'),
agent.post('/api/v2/sendlabels/'),
agent.put('/api/v2/sendlabels/123'),
agent.delete('/api/v2/sendlabels/323'),
];
for (const res of await Promise.all(routes)) {
res.should.have.status(401);
}
});
it('should handle coinless routes with multiple query params', async function () {
const res = await agent.get('/api/v2/market/latest?coin=tbtc&coin=tltc');
res.should.have.status(200);
should.exist(res.body.marketData);
res.body.marketData.should.have.length(2);
res.body.marketData[0].should.have.property('coin', 'tbtc');
res.body.marketData[1].should.have.property('coin', 'tltc');
});
it('should handle coinless routes with a single query param', async function () {
const res = await agent.get('/api/v2/market/latest?coin=tbtc');
res.should.have.status(200);
should.exist(res.body.marketData);
res.body.marketData.should.have.length(1);
res.body.marketData[0].should.have.property('coin', 'tbtc');
});
it('should pass POST body data to the proxy target url', async function () {
const path = '/api/v2/post';
const body = { some: 'data' };
const serverResponse = { testResponse: 'server response' };
// client constants are retrieved upon BitGo
// object creation so they need to be nocked
const scopes = [
nock(sdk_core_1.Environments.test.uri).get('/api/v1/client/constants').reply(200, {}),
nock(sdk_core_1.Environments.test.uri).post(path, body).reply(200, serverResponse),
];
const postRes = await agent.post(path).send(body);
postRes.should.have.status(200);
postRes.should.have.property('body', serverResponse);
scopes.forEach((s) => s.done());
});
describe('proxy error handling', () => {
let agent;
before(() => {
const args = {
...config_1.DefaultConfig,
debug: true,
env: 'test',
timeout: 500,
};
const app = (0, expressApp_1.app)(args);
agent = (0, supertest_1.agent)(app);
if (!nock.isActive()) {
nock.activate();
}
nock.disableNetConnect();
nock.enableNetConnect('127.0.0.1');
});
after(() => {
if (nock.isActive()) {
nock.restore();
}
});
it('should handle ECONNRESET errors from the proxy server', async function () {
const path = '/api/v2/fakeroute';
// client constants are retrieved upon BitGo
// object creation so they need to be nocked
nock(sdk_core_1.Environments.test.uri).get('/api/v1/client/constants').reply(200, {});
// first request to ping endpoint should time out
nock(sdk_core_1.Environments.test.uri).get(path).delayConnection(1000).reply(200);
// we should return 503 in the case of a timeout
let pingRes = await agent.get(path).send({});
pingRes.should.have.status(503);
nock(sdk_core_1.Environments.test.uri).get(path).reply(200);
pingRes = await agent.get(path).send({});
pingRes.should.have.status(200);
});
it('should handle log4j injection string', async function () {
const res = await agent.get('/').query('a=${jndi:dns://3.127.145.40:53/}').send({});
res.should.have.status(404);
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYml0Z29FeHByZXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC9pbnRlZ3JhdGlvbi9iaXRnb0V4cHJlc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7R0FFRztBQUNILGlDQUFpQztBQUNqQyx1QkFBcUI7QUFFckIseUNBQStDO0FBQy9DLDZDQUFpRDtBQUNqRCxxREFBeUQ7QUFDekQsNkJBQTZCO0FBQzdCLDhDQUErQztBQUUvQyxRQUFRLENBQUMsZUFBZSxFQUFFO0lBQ3hCLElBQUksS0FBSyxDQUFDO0lBQ1YsTUFBTSxDQUFDO1FBQ0wsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRWYsTUFBTSxJQUFJLEdBQUc7WUFDWCxHQUFHLHNCQUFhO1lBQ2hCLEtBQUssRUFBRSxLQUFLO1lBQ1osR0FBRyxFQUFFLE1BQWU7WUFDcEIsT0FBTyxFQUFFLFdBQVc7U0FDckIsQ0FBQztRQUVGLE1BQU0sR0FBRyxHQUFHLElBQUEsZ0JBQVUsRUFBQyxJQUFJLENBQUMsQ0FBQztRQUM3QixLQUFLLEdBQUcsSUFBQSxpQkFBUyxFQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGdCQUFnQixFQUFFO1FBQ3pCLFFBQVEsQ0FBQyxTQUFTLEVBQUU7WUFDbEIsRUFBRSxDQUFDLHdDQUF3QyxFQUFFLEtBQUs7Z0JBQ2hELE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSztxQkFDcEIsSUFBSSxDQUFDLDJCQUEyQixDQUFDO3FCQUNqQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsb0NBQW9DLEVBQUUsQ0FBQyxDQUFDO2dCQUUzRCxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzVCLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkMsQ0FB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aURBQWlEO1lBQ2pELElBQUksQ0FBQyx1QkFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUV2RSxnREFBZ0Q7WUFDaEQsSUFBSSxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUM3QyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFaEMsSUFBSSxDQUFDLHVCQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFakQsT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEtBQUs7WUFDOUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwRixHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0ICogYXMgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgJ3Nob3VsZC1odHRwJztcblxuaW1wb3J0IHsgYWdlbnQgYXMgc3VwZXJ0ZXN0IH0gZnJvbSAnc3VwZXJ0ZXN0JztcbmltcG9ydCB7IERlZmF1bHRDb25maWcgfSBmcm9tICcuLi8uLi9zcmMvY29uZmlnJztcbmltcG9ydCB7IGFwcCBhcyBleHByZXNzQXBwIH0gZnJvbSAnLi4vLi4vc3JjL2V4cHJlc3NBcHAnO1xuaW1wb3J0ICogYXMgbm9jayBmcm9tICdub2NrJztcbmltcG9ydCB7IEVudmlyb25tZW50cyB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5cbmRlc2NyaWJlKCdCaXRnbyBFeHByZXNzJywgZnVuY3Rpb24gKCkge1xuICBsZXQgYWdlbnQ7XG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5yZXN0b3JlKCk7XG5cbiAgICBjb25zdCBhcmdzID0ge1xuICAgICAgLi4uRGVmYXVsdENvbmZpZyxcbiAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICAgIGVudjogJ3Rlc3QnIGFzIGNvbnN0LFxuICAgICAgbG9nZmlsZTogJy9kZXYvbnVsbCcsXG4gICAgfTtcblxuICAgIGNvbnN0IGFwcCA9IGV4cHJlc3NBcHAoYXJncyk7XG4gICAgYWdlbnQgPSBzdXBlcnRlc3QoYXBwKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZlcmlmeSBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGRlc2NyaWJlKCdmYWlsdXJlJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCBtYXJrIGFzIGludmFsaWQgYmFkIGJ0YyBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudFxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YyL2J0Yy92ZXJpZnlhZGRyZXNzJylcbiAgICAgICAgICAuc2VuZCh7IGFkZHJlc3M6ICczUDE0MTU5ZjczRTRnRnI3SnRlckNDUWg5UWppVGppWnJSJyB9KTtcblxuICAgICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LmlzVmFsaWQuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG1hcmsgYXMgaW52YWxpZCBiYWQgbHRjIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvbHRjL3ZlcmlmeWFkZHJlc3MnKVxuICAgICAgICAgIC5zZW5kKHsgYWRkcmVzczogJzNQczNNZUhhWW0yczVXUHNSbzFrSGtDdlM4RUZhd3pHN1InIH0pO1xuXG4gICAgICAgIHJlcy5zaG91bGQuaGF2ZS5zdGF0dXMoMjAwKTtcbiAgICAgICAgcmVzLmJvZHkuaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgbWFyayBhcyBpbnZhbGlkIGJhZCB0bHRjIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvdGx0Yy92ZXJpZnlhZGRyZXNzJylcbiAgICAgICAgICAuc2VuZCh7IGFkZHJlc3M6ICdRZUtDY3h0ZnFwcnpac1daaWhSZ3hKazJRSnJyTE1qUzRzJyB9KTtcblxuICAgICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LmlzVmFsaWQuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG1hcmsgYXMgaW52YWxpZCBiYWQgdGx0YyBhZGRyZXNzIHdoZW4gbm90IGFsbG93aW5nIG9sZCBzY3JpcHQgaGFzaCB2ZXJzaW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudFxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YyL2x0Yy92ZXJpZnlhZGRyZXNzJylcbiAgICAgICAgICAuc2VuZCh7IGFkZHJlc3M6ICczUHMzTWVIYVltMnM1V1BzUm8xa0hrQ3ZTOEVGYXd6RzdRJyB9KTtcblxuICAgICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LmlzVmFsaWQuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG1hcmsgYXMgaW52YWxpZCBiYWQgZXRoIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvZXRoL3ZlcmlmeWFkZHJlc3MnKVxuICAgICAgICAgIC5zZW5kKHsgYWRkcmVzczogJzB4ZDRhNGFhMDlmNTdiN2U4M2NkODE3ZWMyNGRmOWY4NmRhZjI1M2QxJyB9KTtcblxuICAgICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LmlzVmFsaWQuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG1hcmsgYXMgaW52YWxpZCBiYWQgeHJwIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIveHJwL3ZlcmlmeWFkZHJlc3MnKVxuICAgICAgICAgIC5zZW5kKHsgYWRkcmVzczogJ3J3NWJmdnVtSFdaaXJLTEc1Z1VRODlkeXF0aVVVYm14UCcgfSk7XG5cbiAgICAgICAgcmVzLnNob3VsZC5oYXZlLnN0YXR1cygyMDApO1xuICAgICAgICByZXMuYm9keS5pc1ZhbGlkLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdzdWNjZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgYnRjIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvYnRjL3ZlcmlmeWFkZHJlc3MnKVxuICAgICAgICAgIC5zZW5kKHsgYWRkcmVzczogJzNQMTQxNTlmNzNFNGdGcjdKdGVyQ0NRaDlRamlUamlackcnIH0pO1xuXG4gICAgICAgIHJlcy5zaG91bGQuaGF2ZS5zdGF0dXMoMjAwKTtcbiAgICAgICAgcmVzLmJvZHkuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgdGJ0YyBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudFxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YyL3RidGMvdmVyaWZ5YWRkcmVzcycpXG4gICAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiAnMk16UXdTU25CSFdIcVNBcXRUVlE2djQ3WHRhaXNySmExVmMnIH0pO1xuXG4gICAgICAgIHJlcy5zaG91bGQuaGF2ZS5zdGF0dXMoMjAwKTtcbiAgICAgICAgcmVzLmJvZHkuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgbHRjIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjIvbHRjL3ZlcmlmeWFkZHJlc3MnKVxuICAgICAgICAgIC5zZW5kKHsgYWRkcmVzczogJ01XNUJmWGhZVnN0SHQxZm1YZzE2N1BUS2twcGhmUDZ4UTMnIH0pO1xuXG4gICAgICAgIHJlcy5zaG91bGQuaGF2ZS5zdGF0dXMoMjAwKTtcbiAgICAgICAgcmVzLmJvZHkuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgb2xkLXN0eWxlIFAyU0ggbHRjIGFkZHJlc3Mgd2hlbiBhbGxvd2luZyBvbGQgc2NyaXB0IGhhc2ggdmVyc2lvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgYWdlbnQucG9zdCgnL2FwaS92Mi9sdGMvdmVyaWZ5YWRkcmVzcycpLnNlbmQoe1xuICAgICAgICAgIGFkZHJlc3M6ICczUHMzTWVIYVltMnM1V1BzUm8xa0hrQ3ZTOEVGYXd6RzdRJyxcbiAgICAgICAgICBzdXBwb3J0T2xkU2NyaXB0SGFzaFZlcnNpb246IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlcy5zaG91bGQuaGF2ZS5zdGF0dXMoMjAwKTtcbiAgICAgICAgcmVzLmJvZHkuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdGx0YyBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudFxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YyL3RsdGMvdmVyaWZ5YWRkcmVzcycpXG4gICAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiAnUWVLQ2N4dGZxcHJ6WnNXWmloUmd4SmsyUUpyckxNalM0YycgfSk7XG5cbiAgICAgICAgcmVzLnNob3VsZC5oYXZlLnN0YXR1cygyMDApO1xuICAgICAgICByZXMuYm9keS5pc1ZhbGlkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSB2YWxpZCBldGggYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgYWdlbnRcbiAgICAgICAgICAucG9zdCgnL2FwaS92Mi9ldGgvdmVyaWZ5YWRkcmVzcycpXG4gICAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiAnMHhkNGE0YWEwOWY1N2I3ZTgzY2Q4MTdlYzI0ZGY5Zjg2ZGFmMjUzZDFkJyB9KTtcblxuICAgICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LmlzVmFsaWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IHZhbGlkIHhycCBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudFxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YyL3hycC92ZXJpZnlhZGRyZXNzJylcbiAgICAgICAgICAuc2VuZCh7IGFkZHJlc3M6ICdydzViZnZ1bUhXWmlyS0xHNWdVUTg5ZHlxdGlVVWJteFBEJyB9KTtcblxuICAgICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LmlzVmFsaWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZXF1ZXN0IGJvZHkgc2l6ZSBsaW1pdHMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgcmVxdWVzdCBib2RpZXMgPD0yMG1iJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gYWN0dWFsIG51bWJlciBvZiBieXRlcyBzZW50IHdpbGwgYmUgcm91Z2hseSA2eCB0aGUgbnVtYmVyIG9mIGJ5dGVzIGluXG4gICAgICAvLyB0aGUgYnVmZmVyLiBUaGVyZWZvcmUsIHRvIGNyZWF0ZSBhIHJlcXVlc3QgYm9keSBiZXR3ZWVuIDEybWIgYW5kIDIwbWIsXG4gICAgICAvLyB3ZSBzaG91bGQgY3JlYXRlIGEgYnVmZmVyIHdpdGggYmV0d2VlbiAyZTYgYW5kIDMuM2U2IGJ5dGVzXG4gICAgICBjb25zdCBudW1CeXRlcyA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDJlNiArIDEuM2U2KTtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgIC5wb3N0KCcvYXBpL3YyL2J0Yy92ZXJpZnlhZGRyZXNzJylcbiAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiAnM1AxNDE1OWY3M0U0Z0ZyN0p0ZXJDQ1FoOVFqaVRqaVpyRycsIGdhcmJhZ2U6IEJ1ZmZlci5hbGxvYyhudW1CeXRlcykudG9TdHJpbmcoJ3V0ZjgnKSB9KTtcblxuICAgICAgcmVzLnNob3VsZC5oYXZlLnN0YXR1cygyMDApO1xuICAgICAgcmVzLmJvZHkuaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgZm9yIHJlcXVlc3QgYm9kaWVzID4yMG1iJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gYWN0dWFsIG51bWJlciBvZiBieXRlcyBzZW50IHdpbGwgYmUgcm91Z2hseSA2eCB0aGUgbnVtYmVyIG9mIGJ5dGVzIGluXG4gICAgICAvLyB0aGUgYnVmZmVyLiBUaGVyZWZvcmUsIHRvIGNyZWF0ZSBhIHJlcXVlc3QgYm9keSBiZXR3ZWVuIDIwbWIgYW5kIDI1bWIsXG4gICAgICAvLyB3ZSBzaG91bGQgY3JlYXRlIGEgYnVmZmVyIHdpdGggYmV0d2VlbiAzLjMzNGU2IGFuZCA0LjE2NmU2IGJ5dGVzLlxuICAgICAgLy8gd2UgdXNlIDMuNWU2IGluc3RlYWQgdG8gZ2l2ZSBhIGJpdCBvZiBidWZmZXIgc3BhY2UgKG5vIHB1biBpbnRlbmRlZClcbiAgICAgIGNvbnN0IG51bUJ5dGVzID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMC44MjZlNiArIDMuNWU2KTtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50XG4gICAgICAgIC5wb3N0KCcvYXBpL3YyL2J0Yy92ZXJpZnlhZGRyZXNzJylcbiAgICAgICAgLnNlbmQoeyBhZGRyZXNzOiAnM1AxNDE1OWY3M0U0Z0ZyN0p0ZXJDQ1FoOVFqaVRqaVpyRycsIGdhcmJhZ2U6IEJ1ZmZlci5hbGxvYyhudW1CeXRlcykudG9TdHJpbmcoJ3V0ZjgnKSB9KTtcblxuICAgICAgcmVzLnNob3VsZC5oYXZlLnN0YXR1cyg0MTMpO1xuICAgIH0pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIG5vdCBwcm94eSBhIG5vbi1hcGkgcm91dGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgYWdlbnQuZ2V0KCcvaW5mby9zb2x1dGlvbnMnKS5zZW5kKCk7XG4gICAgcmVzLnNob3VsZC5oYXZlLnN0YXR1cyg0MDQpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHByb3h5IHRoZSBvYXV0aC90b2tlbiByb3V0ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudC5wb3N0KCcvb2F1dGgvdG9rZW4nKS5zZW5kKCk7XG4gICAgcmVzLnNob3VsZC5ub3QuaGF2ZS5zdGF0dXMoNDA0KTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBoYW5kbGUgY29pbmxlc3Mgcm91dGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHJvdXRlcyA9IFtcbiAgICAgIGFnZW50LmdldCgnL2FwaS92Mi9yZXBvcnRzLycpLFxuICAgICAgYWdlbnQuZ2V0KCcvYXBpL3YyL3dhbGxldC9iYWxhbmNlcy9tZXJnZWQvJyksXG4gICAgICBhZ2VudC5nZXQoJy9hcGkvdjIvZW50ZXJwcmlzZS8xMjM0LycpLFxuICAgICAgYWdlbnQucG9zdCgnL2FwaS92Mi9zZW5kbGFiZWxzLycpLFxuICAgICAgYWdlbnQucHV0KCcvYXBpL3YyL3NlbmRsYWJlbHMvMTIzJyksXG4gICAgICBhZ2VudC5kZWxldGUoJy9hcGkvdjIvc2VuZGxhYmVscy8zMjMnKSxcbiAgICBdO1xuXG4gICAgZm9yIChjb25zdCByZXMgb2YgYXdhaXQgUHJvbWlzZS5hbGwocm91dGVzKSkge1xuICAgICAgcmVzLnNob3VsZC5oYXZlLnN0YXR1cyg0MDEpO1xuICAgIH1cbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBoYW5kbGUgY29pbmxlc3Mgcm91dGVzIHdpdGggbXVsdGlwbGUgcXVlcnkgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFnZW50LmdldCgnL2FwaS92Mi9tYXJrZXQvbGF0ZXN0P2NvaW49dGJ0YyZjb2luPXRsdGMnKTtcbiAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgc2hvdWxkLmV4aXN0KHJlcy5ib2R5Lm1hcmtldERhdGEpO1xuICAgIHJlcy5ib2R5Lm1hcmtldERhdGEuc2hvdWxkLmhhdmUubGVuZ3RoKDIpO1xuICAgIHJlcy5ib2R5Lm1hcmtldERhdGFbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW4nLCAndGJ0YycpO1xuICAgIHJlcy5ib2R5Lm1hcmtldERhdGFbMV0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW4nLCAndGx0YycpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGhhbmRsZSBjb2lubGVzcyByb3V0ZXMgd2l0aCBhIHNpbmdsZSBxdWVyeSBwYXJhbScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBhZ2VudC5nZXQoJy9hcGkvdjIvbWFya2V0L2xhdGVzdD9jb2luPXRidGMnKTtcbiAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgc2hvdWxkLmV4aXN0KHJlcy5ib2R5Lm1hcmtldERhdGEpO1xuICAgIHJlcy5ib2R5Lm1hcmtldERhdGEuc2hvdWxkLmhhdmUubGVuZ3RoKDEpO1xuICAgIHJlcy5ib2R5Lm1hcmtldERhdGFbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW4nLCAndGJ0YycpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHBhc3MgUE9TVCBib2R5IGRhdGEgdG8gdGhlIHByb3h5IHRhcmdldCB1cmwnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcGF0aCA9ICcvYXBpL3YyL3Bvc3QnO1xuICAgIGNvbnN0IGJvZHkgPSB7IHNvbWU6ICdkYXRhJyB9O1xuICAgIGNvbnN0IHNlcnZlclJlc3BvbnNlID0geyB0ZXN0UmVzcG9uc2U6ICdzZXJ2ZXIgcmVzcG9uc2UnIH07XG5cbiAgICAvLyBjbGllbnQgY29uc3RhbnRzIGFyZSByZXRyaWV2ZWQgdXBvbiBCaXRHb1xuICAgIC8vIG9iamVjdCBjcmVhdGlvbiBzbyB0aGV5IG5lZWQgdG8gYmUgbm9ja2VkXG4gICAgY29uc3Qgc2NvcGVzID0gW1xuICAgICAgbm9jayhFbnZpcm9ubWVudHMudGVzdC51cmkpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykucmVwbHkoMjAwLCB7fSksXG4gICAgICBub2NrKEVudmlyb25tZW50cy50ZXN0LnVyaSkucG9zdChwYXRoLCBib2R5KS5yZXBseSgyMDAsIHNlcnZlclJlc3BvbnNlKSxcbiAgICBdO1xuXG4gICAgY29uc3QgcG9zdFJlcyA9IGF3YWl0IGFnZW50LnBvc3QocGF0aCkuc2VuZChib2R5KTtcbiAgICBwb3N0UmVzLnNob3VsZC5oYXZlLnN0YXR1cygyMDApO1xuICAgIHBvc3RSZXMuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2JvZHknLCBzZXJ2ZXJSZXNwb25zZSk7XG4gICAgc2NvcGVzLmZvckVhY2goKHMpID0+IHMuZG9uZSgpKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Byb3h5IGVycm9yIGhhbmRsaW5nJywgKCkgPT4ge1xuICAgIGxldCBhZ2VudDtcbiAgICBiZWZvcmUoKCkgPT4ge1xuICAgICAgY29uc3QgYXJncyA9IHtcbiAgICAgICAgLi4uRGVmYXVsdENvbmZpZyxcbiAgICAgICAgZGVidWc6IHRydWUsXG4gICAgICAgIGVudjogJ3Rlc3QnIGFzIGNvbnN0LFxuICAgICAgICB0aW1lb3V0OiA1MDAsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBhcHAgPSBleHByZXNzQXBwKGFyZ3MpO1xuICAgICAgYWdlbnQgPSBzdXBlcnRlc3QoYXBwKTtcblxuICAgICAgaWYgKCFub2NrLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgbm9jay5hY3RpdmF0ZSgpO1xuICAgICAgfVxuICAgICAgbm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuICAgICAgbm9jay5lbmFibGVOZXRDb25uZWN0KCcxMjcuMC4wLjEnKTtcbiAgICB9KTtcblxuICAgIGFmdGVyKCgpID0+IHtcbiAgICAgIGlmIChub2NrLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgbm9jay5yZXN0b3JlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBFQ09OTlJFU0VUIGVycm9ycyBmcm9tIHRoZSBwcm94eSBzZXJ2ZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXRoID0gJy9hcGkvdjIvZmFrZXJvdXRlJztcblxuICAgICAgLy8gY2xpZW50IGNvbnN0YW50cyBhcmUgcmV0cmlldmVkIHVwb24gQml0R29cbiAgICAgIC8vIG9iamVjdCBjcmVhdGlvbiBzbyB0aGV5IG5lZWQgdG8gYmUgbm9ja2VkXG4gICAgICBub2NrKEVudmlyb25tZW50cy50ZXN0LnVyaSkuZ2V0KCcvYXBpL3YxL2NsaWVudC9jb25zdGFudHMnKS5yZXBseSgyMDAsIHt9KTtcblxuICAgICAgLy8gZmlyc3QgcmVxdWVzdCB0byBwaW5nIGVuZHBvaW50IHNob3VsZCB0aW1lIG91dFxuICAgICAgbm9jayhFbnZpcm9ubWVudHMudGVzdC51cmkpLmdldChwYXRoKS5kZWxheUNvbm5lY3Rpb24oMTAwMCkucmVwbHkoMjAwKTtcblxuICAgICAgLy8gd2Ugc2hvdWxkIHJldHVybiA1MDMgaW4gdGhlIGNhc2Ugb2YgYSB0aW1lb3V0XG4gICAgICBsZXQgcGluZ1JlcyA9IGF3YWl0IGFnZW50LmdldChwYXRoKS5zZW5kKHt9KTtcbiAgICAgIHBpbmdSZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDUwMyk7XG5cbiAgICAgIG5vY2soRW52aXJvbm1lbnRzLnRlc3QudXJpKS5nZXQocGF0aCkucmVwbHkoMjAwKTtcblxuICAgICAgcGluZ1JlcyA9IGF3YWl0IGFnZW50LmdldChwYXRoKS5zZW5kKHt9KTtcbiAgICAgIHBpbmdSZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDIwMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSBsb2c0aiBpbmplY3Rpb24gc3RyaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYWdlbnQuZ2V0KCcvJykucXVlcnkoJ2E9JHtqbmRpOmRuczovLzMuMTI3LjE0NS40MDo1My99Jykuc2VuZCh7fSk7XG4gICAgICByZXMuc2hvdWxkLmhhdmUuc3RhdHVzKDQwNCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!