Socket
Socket
Sign inDemoInstall

purpleteam

Package Overview
Dependencies
185
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.1.0-alpha.3 to 4.0.0-alpha.3

bin/purpleteam.js

35

config/config.js

@@ -10,5 +10,6 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const convict = require('convict');
const convictFormatWithValidator = require('convict-format-with-validator');
const path = require('path');
import convict from 'convict';
import convictFormatWithValidator from 'convict-format-with-validator';
import { fileURLToPath } from 'url';
import path, { dirname } from 'path';

@@ -20,3 +21,3 @@ convict.addFormats(convictFormatWithValidator);

doc: 'The application environment.',
format: ['cloud', 'local', 'test'],
format: ['cloud', 'local', 'cloudtest', 'localtest'],
default: 'cloud',

@@ -197,3 +198,3 @@ env: 'NODE_ENV'

format: String,
default: `${process.cwd()}/outcomes/`
default: path.join(process.cwd(), '/outcomes/')
},

@@ -219,4 +220,4 @@ fileName: {

doc: 'The version of the Job accepted by the PurpleTeam API.',
format: ['0.1.0-alpha.1', '1.0.0-alpha.3', '2.0.0-alpha.3', '3.0.0-alpha.3'],
default: '3.0.0-alpha.3'
format: ['0.1.0-alpha.1', '1.0.0-alpha.3', '2.0.0-alpha.3', '3.0.0-alpha.3', '3.1.0-alpha.3', '4.0.0-alpha.3'],
default: '4.0.0-alpha.3'
}

@@ -232,6 +233,12 @@ },

uI: {
doc: 'The user interface used. cUi is usually the best option for running the purpleteam CLI standalone, noUi is usually the best option for running the purpleteam CLI from within another process',
format: ['cUi', 'noUi'],
default: 'cUi',
env: 'PURPLETEAM_UI'
type: {
doc: 'The user interface used. cUi is usually the best option for running the purpleteam CLI standalone, noUi is usually the best option for running the purpleteam CLI from within another process',
format: ['cUi', 'noUi'],
default: 'cUi',
env: 'PURPLETEAM_UI'
},
path: {
cUi: path.join(process.cwd(), '/src/view/cUi.js'),
noUi: path.join(process.cwd(), '/src/view/noUi.js')
}
}

@@ -245,3 +252,5 @@ };

// config.loadFile([path.join(__dirname, `config.${process.env.NODE_ENV}.json`), '/my/locked/down/purpleteam_secrets.json']);
config.loadFile(path.join(__dirname, `config.${process.env.NODE_ENV}.json`));
const filename = fileURLToPath(import.meta.url);
const currentDirName = dirname(filename);
config.loadFile(path.join(currentDirName, `config.${process.env.NODE_ENV}.json`));
config.validate();

@@ -253,2 +262,2 @@

module.exports = config;
export default config;
{
"ava": {
"files": [
"test/**/*"
],
"environmentVariables": {
"NODE_ENV": "localtest"
}
},
"name": "purpleteam",

@@ -6,5 +14,5 @@ "np": {

},
"version": "3.1.0-alpha.3",
"version": "4.0.0-alpha.3",
"description": "CLI for driving purpleteam -- security regression testing SaaS",
"main": "src/index.js",
"exports": "./src/index.js",
"scripts": {

@@ -14,9 +22,10 @@ "lint": "eslint .",

"update:deps": "npm-check -u",
"test": "lab --assert @hapi/code --coverage",
"test:coveralls": "lab --assert @hapi/code --reporter lcov -o ./coverage/lcov.info",
"test:nolint": "lab --assert @hapi/code --coverage",
"test:debug": "node --inspect-brk=localhost:9230 ./node_modules/.bin/lab --assert @hapi/code --timeout 0",
"test": "c8 --reporter=lcov --reporter=text-summary ava",
"test:nolint": "c8 --reporter=lcov --reporter=text-summary ava",
"test:coveralls": "c8 ava; c8 report --reporter=text-lcov | coveralls",
"test:debug": "ava debug --break ./test/presenter/apiDecoratingAdapter_sSeAndLp.js",
"test:nockDebug": "DEBUG=nock.* ava debug --break ./test/presenter/apiDecoratingAdapter.js",
"pretest": "npm run lint",
"debug": "node --inspect-brk=localhost:9230 ./bin/purpleteam",
"start": "node ./bin/purpleteam",
"debug": "node --inspect-brk=localhost:9230 ./bin/purpleteam.js",
"start": "node ./bin/purpleteam.js",
"prepare": "husky install"

@@ -73,33 +82,35 @@ },

"@hapi/bourne": "^2.0.0",
"ajv": "^8.5.0",
"ajv": "^8.10.0",
"ajv-errors": "^3.0.0",
"ajv-formats": "^2.1.0",
"ajv-formats": "^2.1.1",
"blessed": "^0.1.81",
"blessed-contrib": "^4.8.21",
"chalk": "^4.1.1",
"convict": "^6.1.0",
"convict-format-with-validator": "^6.0.1",
"blessed-contrib": "^4.10.1",
"chalk": "^5.0.0",
"convict": "^6.2.1",
"convict-format-with-validator": "^6.2.0",
"diff": "^5.0.0",
"eventsource": "^1.1.0",
"figlet": "^1.5.0",
"got": "^11.8.2",
"purpleteam-logger": "^1.1.2",
"sywac": "^1.3.0"
"figlet": "^1.5.2",
"got": "^12.0.1",
"purpleteam-logger": "^2.0.0",
"sywac": "git+https://git@github.com:binarymist/sywac.git#binarymist/esm"
},
"devDependencies": {
"@hapi/code": "^8.0.3",
"@hapi/lab": "^24.2.1",
"eslint": "^7.27.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.23.3",
"mocksse": "^1.0.3",
"nock": "^13.0.11",
"ava": "^4.0.1",
"c8": "^7.11.0",
"coveralls": "^3.1.1",
"eslint": "^8.9.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-ava": "^13.2.0",
"eslint-plugin-import": "^2.25.4",
"husky": "^7.0.4",
"mocksse": "^1.0.4",
"nock": "^13.2.4",
"npm-check": "^5.9.2",
"rewire": "^5.0.0",
"sinon": "^11.1.1",
"husky": "^6.0.0"
"sinon": "^13.0.1"
},
"bin": {
"purpleteam": "./bin/purpleteam"
"purpleteam": "./bin/purpleteam.js"
},
"type": "module",
"files": [

@@ -106,0 +117,0 @@ "bin",

@@ -514,3 +514,5 @@ <div align="center">

* `test`: Once testing is under way, you can:
* [right-arrow], [left-arrow] through the terminal screens to view the testing progress of each of the [_Testers_](https://purpleteam-labs.com/doc/definitions/) in real-time courtesy of the _PurpleTeam_ API
* [right-arrow], [left-arrow] through the terminal screens to view the testing progress of each of the [_Testers_](https://purpleteam-labs.com/doc/definitions/) in real-time courtesy of the _PurpleTeam_ API.
Another way to follow the log file in real-time for another _Tester_ (TLS for example) is to copy the name of the CLI log file being created and run the following command in another terminal:
`tail tls-NA_[date]T[time].log -f -n +1`
* [down-arrow], [up-arrow] to highlight the different Running Statistics of the _Testers_ as they are provided in real-time courtesy of the _PurpleTeam_ API

@@ -517,0 +519,0 @@ * `testplan`: Once the test plans have been retrieved, you can [right-arrow], [left-arrow] through the terminal screens to view the test plans of each specific [_Tester_](https://purpleteam-labs.com/doc/definitions/)

@@ -10,8 +10,14 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const sywac = require('sywac');
const chalk = require('chalk');
const figlet = require('figlet');
const cUiLogger = require('purpleteam-logger').get();
const pkg = require('../package.json');
import sywac from 'sywac';
import chalk from 'chalk';
import figlet from 'figlet';
import { get as getLogger } from 'purpleteam-logger';
import { fileURLToPath } from 'url';
import path, { dirname } from 'path';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const { name: pkgName, description: pkgDescription } = require('../package');
const epilogue = `For more information, find the manual at https://doc.purpleteam-labs.com

@@ -22,11 +28,12 @@ Copyright (C) 2017-2021 BinaryMist Limited. All rights reserved.

const processCommands = async (options) => { // eslint-disable-line no-unused-vars
const cUiLogger = getLogger();
cUiLogger.debug('Configuring sywac\n', { tags: ['cli'] });
const api = sywac // eslint-disable-line no-unused-vars
.usage('Usage: $0 [command] [option(s)]')
.commandDirectory('cmds')
// This overrides the --help and --version and adds their aliases
.showHelpByDefault()
const api = sywac; // eslint-disable-line no-unused-vars
api.usage('Usage: $0 [command] [option(s)]');
await api.commandDirectory(path.join(dirname(fileURLToPath(import.meta.url)), 'cmds'));
// This overrides the --help and --version and adds their aliases
api.showHelpByDefault()
.version('-v, --version', { desc: 'Show version number' })
.help('-h, --help')
.preface(figlet.textSync(pkg.name, 'Chunky'), chalk.bgHex('#9961ed')(pkg.description))
.preface(figlet.textSync(pkgName, 'Chunky'), chalk.bgHex('#9961ed')(pkgDescription))
.epilogue(epilogue)

@@ -37,3 +44,3 @@ .style({

group: (str) => chalk.hex('#9961ed').bold(str),
messages: (str) => chalk.keyword('orange').bold(str)
messages: (str) => chalk.hex('#FFA500').bold(str)
});

@@ -63,2 +70,2 @@

module.exports = { processCommands };
export default processCommands;

@@ -10,11 +10,15 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const cUiLogger = require('purpleteam-logger').get();
const pkg = require('../../package.json');
import { get as getLogger } from 'purpleteam-logger';
exports.flags = 'about';
exports.desc = 'About purpleteam';
exports.setup = {};
exports.run = (/* parsedArgv, context */) => {
const { name: projectName, version, description, homepage, author: { name, email } } = pkg;
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const { name: projectName, version, description, homepage, author: { name, email } } = require('../../package');
const cUiLogger = getLogger();
const flags = 'about';
const desc = 'About purpleteam';
const setup = {};
const run = (/* parsedArgv, context */) => {
cUiLogger.notice(`${projectName} ${version}`, { tags: ['screen'] });

@@ -34,3 +38,17 @@ cUiLogger.notice(description, { tags: ['screen'] });

const manPage = `Usage details for the CLI can be found on the README:
(https://github.com/purpleteam-labs/purpleteam#usage)
Installation, configuration and running details for the CLI can also be
found on the README:
(https://github.com/purpleteam-labs/purpleteam#contents).
Full documentation for the PurpleTeam SaaS can be found at:
(https://purpleteam-labs.com/doc/)`;
console.log(`${manPage}\n`); // eslint-disable-line no-console
process.exit(0);
};
export { flags, desc, setup, run };

@@ -10,8 +10,11 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const api = require('../presenter/apiDecoratingAdapter');
import api from '../presenter/apiDecoratingAdapter.js';
exports.flags = 'status';
exports.desc = 'Check the status of the PurpleTeam back-end.';
exports.run = async () => {
const flags = 'status';
const desc = 'Check the status of the PurpleTeam back-end.';
const run = async () => {
api.inject({});
await api.status();
};
export { flags, desc, run };

@@ -10,9 +10,9 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const config = require('../../config/config'); // eslint-disable-line no-unused-vars
const api = require('../presenter/apiDecoratingAdapter');
import { statSync } from 'fs';
import config from '../../config/config.js';
import api from '../presenter/apiDecoratingAdapter.js';
exports.flags = 'test';
exports.description = 'Launch purpleteam to attack your specified target.';
exports.setup = (sywac) => {
const flags = 'test';
const description = 'Launch purpleteam to attack your specified target.';
const setup = (sywac) => {
sywac

@@ -23,3 +23,7 @@ .option('-j, --job-file <job-file path>', {

mustExist: true,
defaultValue: config.get('job.fileUri')
defaultValue: (() => {
const jobFileUri = config.get('job.fileUri');
const isFile = statSync(jobFileUri, { throwIfNoEntry: false })?.isFile();
return isFile ? jobFileUri : ''; // Only an empty string will cause proper error handling.
})()
})

@@ -30,4 +34,5 @@ .check((argv, context) => {

};
exports.run = async (parsedArgv, context) => {
const run = async (parsedArgv, context) => {
if (parsedArgv.j) {
api.inject({});
const jobFileContents = await api.getJobFile(parsedArgv.j);

@@ -46,1 +51,3 @@ // Todo: KC: In the future we could deserialise configFileContents, and possibly validate before sending to the Orchestrator.

};
export { flags, description, setup, run };

@@ -10,9 +10,9 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const config = require('../../config/config'); // eslint-disable-line no-unused-vars
const api = require('../presenter/apiDecoratingAdapter');
import { statSync } from 'fs';
import config from '../../config/config.js';
import api from '../presenter/apiDecoratingAdapter.js';
exports.flags = 'testplan';
exports.desc = 'Retrieve the test plan that will be executed when you run test.';
exports.setup = (sywac) => {
const flags = 'testplan';
const desc = 'Retrieve the test plan that will be executed when you run test.';
const setup = (sywac) => {
// To override the help:

@@ -25,3 +25,7 @@ // sywac.usage({ optionsPlaceholder: '' });

mustExist: true,
defaultValue: config.get('job.fileUri')
defaultValue: (() => {
const jobFileUri = config.get('job.fileUri');
const isFile = statSync(jobFileUri, { throwIfNoEntry: false })?.isFile();
return isFile ? jobFileUri : ''; // Only an empty string will cause proper error handling.
})()
})

@@ -32,4 +36,5 @@ .check((argv, context) => {

};
exports.run = async (parsedArgv, context) => {
const run = async (parsedArgv, context) => {
if (parsedArgv.j) {
api.inject({});
const jobFileContents = await api.getJobFile(parsedArgv.j);

@@ -41,1 +46,3 @@ await api.testPlans(jobFileContents);

};
export { flags, desc, setup, run };

@@ -10,10 +10,13 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const config = require('../config/config');
const cUiLogger = require('purpleteam-logger').init(config.get('loggers.cUi')); // eslint-disable-line import/order
import { init as initLogger } from 'purpleteam-logger';
import config from '../config/config.js';
import processCommands from './cli.js';
const { processCommands } = require('./cli');
const cUiLogger = initLogger(config.get('loggers.cUi'));
exports.start = async (options) => {
const start = async (options) => {
cUiLogger.debug('Starting the CLI', { tags: ['index'] });
await processCommands({ argv: options.argv });
};
export default start;

@@ -10,5 +10,6 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const EventEmitter = require('events');
const Bourne = require('@hapi/bourne');
const config = require('../../config/config');
import EventEmitter from 'events';
import Bourne from '@hapi/bourne';
import config from '../../config/config.js';
import initJobSchema from '../schemas/job.js';

@@ -24,3 +25,3 @@ const sutConfig = config.getSchema()._cvtProperties.sut; // eslint-disable-line no-underscore-dangle

};
const { validateJob } = require('../schemas/job').init(jobSchemaOpts);
const { validateJob } = initJobSchema(jobSchemaOpts);

@@ -105,2 +106,2 @@ const events = { testerProgress: [], testerPctComplete: [], testerBugCount: [] };

module.exports = Model;
export default Model;

@@ -10,19 +10,29 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const config = require('../../config/config'); // eslint-disable-line import/order
const { promises: fsPromises } = require('fs');
const got = require('got');
const EventSource = require('eventsource');
const Bourne = require('@hapi/bourne');
import { promises as fsPromises } from 'fs';
import got from 'got';
import importedPtLogger, { init as importedInitPtLogger } from 'purpleteam-logger';
import importedEventSource from 'eventsource';
import Bourne from '@hapi/bourne';
import { createRequire } from 'module';
import ImportedModel from '../models/model.js';
import importedView from '../view/index.js';
import { TesterUnavailable, TesterFeedbackRoutePrefix, NowAsFileName } from '../strings/index.js';
import config from '../../config/config.js';
const ptLogger = require('purpleteam-logger');
const Model = require('../models/model');
const view = require('../view');
const pkg = require('../../package.json');
const { TesterUnavailable, TesterFeedbackRoutePrefix, NowAsFileName } = require('../strings');
const require = createRequire(import.meta.url);
const { name: pkgName, version: pkgVersion, description: pkgDescription, homepage: pkgHomepage } = require('../../package');
const cUiLogger = ptLogger.init(config.get('loggers.cUi'));
const apiUrl = config.get('purpleteamApi.url');
const env = config.get('env');
const env = ((e) => {
const supportedEnvs = ['cloud', 'local'];
return supportedEnvs.find((sE) => e.startsWith(sE));
})(config.get('env'));
const internals = {
Model: undefined,
view: undefined,
ptLogger: undefined,
cUiLogger: undefined,
EventSource: undefined,
longPoll: {

@@ -34,2 +44,16 @@ nullProgressCounter: 0,

const inject = ({
Model = ImportedModel,
view = importedView,
ptLogger = importedPtLogger,
cUiLogger = importedInitPtLogger(config.get('loggers.cUi')),
EventSource = importedEventSource
}) => {
internals.Model = Model;
internals.view = view;
internals.ptLogger = ptLogger;
internals.cUiLogger = cUiLogger;
internals.EventSource = EventSource;
};
const getJobFile = async (filePath) => {

@@ -40,3 +64,3 @@ try {

} catch (err) {
cUiLogger.error(`Could not read file: ${filePath}, the error was: ${err}.`, { tags: ['apiDecoratingAdapter'] });
internals.cUiLogger.error(`Could not read file: ${filePath}, the error was: ${err}.`, { tags: ['apiDecoratingAdapter'] });
throw err;

@@ -52,3 +76,3 @@ }

headers: {
'user-agent': `${pkg.name}/${pkg.version} ${pkg.description} ${pkg.homepage}`,
'user-agent': `${pkgName}/${pkgVersion} ${pkgDescription} ${pkgHomepage}`,
'Content-type': 'application/x-www-form-urlencoded',

@@ -71,3 +95,3 @@ Authorization: `Basic ${(() => Buffer.from(`${config.get('purpleteamAuth.appClientId')}:${config.get('purpleteamAuth.appClientSecret')}`).toString('base64'))()}`

?? { default: `An unknown error occurred while attempting to get the access token. Error follows: ${error}` };
cUiLogger.crit(Object.values(knownError)[0], { tags: ['apiDecoratingAdapter'] });
internals.cUiLogger.crit(Object.values(knownError)[0], { tags: ['apiDecoratingAdapter'] });
});

@@ -81,4 +105,4 @@ return accessToken;

headers: {
local: { 'user-agent': `${pkg.name}/${pkg.version} ${pkg.description} ${pkg.homepage}` },
cloud: { 'user-agent': `${pkg.name}/${pkg.version} ${pkg.description} ${pkg.homepage}`, 'x-api-key': config.get('purpleteamApi.apiKey') }
local: { 'user-agent': `${pkgName}/${pkgVersion} ${pkgDescription} ${pkgHomepage}` },
cloud: { 'user-agent': `${pkgName}/${pkgVersion} ${pkgDescription} ${pkgHomepage}`, 'x-api-key': config.get('purpleteamApi.apiKey') }
}[env],

@@ -113,3 +137,3 @@ retry: {

// Save for further requests.
gotPt.defaults.options = got.mergeOptions(gotPt.defaults.options, optionAugmentations);
gotPt.defaults.options.merge(optionAugmentations);
// Make a new retry

@@ -163,2 +187,3 @@ return retryWithMergedOptions(optionAugmentations);

const requestStatus = async () => {
const { view, cUiLogger } = internals;
await gotPt.get('status').then((response) => {

@@ -199,2 +224,3 @@ view.status(cUiLogger, response.body);

const requestTestOrTestPlan = async (jobFileContents, route) => {
const { cUiLogger } = internals;
let result;

@@ -247,3 +273,3 @@ const retrying = (() => ({

await gotPt.post(`${route}`, {
await gotPt.post(route, {
headers: { 'Content-Type': 'application/vnd.api+json' },

@@ -283,25 +309,18 @@ json: jobFileContents,

const handleServerSentTesterEvents = async (event, model, testerNameAndSession) => {
if (event.origin === apiUrl) {
const eventDataPropPascalCase = event.type.replace('tester', '');
const eventDataProp = `${eventDataPropPascalCase.charAt(0).toLowerCase()}${eventDataPropPascalCase.substring(1)}`;
let message = Bourne.parse(event.data)[eventDataProp];
if (message != null) {
if (event.type === 'testerProgress' && message.startsWith('All Test Sessions of all Testers are finished')) { // Message defined in Orchestrator.
message = message.concat(`\n${await requestOutcomes()}`);
}
model.propagateTesterMessage({
testerType: testerNameAndSession.testerType,
sessionId: testerNameAndSession.sessionId,
message,
event: event.type
});
} else {
cUiLogger.warning(`A falsy ${event.type} event message was received from the orchestrator`, { tags: ['apiDecoratingAdapter'] });
// If event.origin is incorrect, eventSource drops the message and this handler is not called.
const eventDataPropPascalCase = event.type.replace('tester', '');
const eventDataProp = `${eventDataPropPascalCase.charAt(0).toLowerCase()}${eventDataPropPascalCase.substring(1)}`;
let message = Bourne.parse(event.data)[eventDataProp];
if (message != null) {
if (event.type === 'testerProgress' && message.startsWith('All Test Sessions of all Testers are finished')) { // Message defined in Orchestrator.
message = message.concat(`\n${await requestOutcomes()}`);
}
} else {
model.propagateTesterMessage({
testerType: testerNameAndSession.testerType,
sessionId: testerNameAndSession.sessionId,
message: `Origin of event was incorrect. Actual: "${event.origin}", Expected: "${apiUrl}"`
message,
event: event.type
});
} else {
internals.cUiLogger.warning(`A falsy ${event.type} event message was received from the orchestrator`, { tags: ['apiDecoratingAdapter'] });
}

@@ -316,3 +335,3 @@ };

const { transports, dirname } = config.get('loggers.testerProgress');
ptLogger.add(loggerType, { transports, filename: `${dirname}${loggerType}_${NowAsFileName()}.log` });
internals.ptLogger.add(loggerType, { transports, filename: `${dirname}${loggerType}_${NowAsFileName()}.log` });

@@ -327,3 +346,3 @@ const testerRepresentative = testerStatuses.find((element) => element.name === testerNameAndSession.testerType);

if (subscribeToOngoingFeedback && testerRepresentative.message !== TesterUnavailable(testerNameAndSession.testerType)) {
const eventSource = new EventSource(`${apiUrl}/${TesterFeedbackRoutePrefix('sse')}/${testerNameAndSession.testerType}/${testerNameAndSession.sessionId}`); // sessionId is 'NA' for tls?
const eventSource = new internals.EventSource(`${apiUrl}/${TesterFeedbackRoutePrefix('sse')}/${testerNameAndSession.testerType}/${testerNameAndSession.sessionId}`); // sessionId is 'NA' for tls?
const handleServerSentTesterEventsClosure = (event) => {

@@ -401,3 +420,3 @@ handleServerSentTesterEvents(event, model, testerNameAndSession);

const { transports, dirname } = config.get('loggers.testerProgress');
ptLogger.add(loggerType, { transports, filename: `${dirname}${loggerType}_${NowAsFileName()}.log` });
internals.ptLogger.add(loggerType, { transports, filename: `${dirname}${loggerType}_${NowAsFileName()}.log` });

@@ -465,3 +484,3 @@ const testerRepresentative = testerStatuses.find((element) => element.name === testerNameAndSession.testerType);

try {
model = new Model(jobFileContents);
model = new internals.Model(jobFileContents);
} catch (error) {

@@ -474,3 +493,3 @@ const knownErrors = [

?? { default: `Unknown error. Error follows: ${error}` };
cUiLogger.crit(`Error occurred while instantiating the model. Details follow: ${Object.values(knownError)[0]}`, { tags: ['apiDecoratingAdapter'] });
internals.cUiLogger.crit(`Error occurred while instantiating the model. Details follow: ${Object.values(knownError)[0]}`, { tags: ['apiDecoratingAdapter'] });
return undefined;

@@ -484,8 +503,8 @@ }

if (!model) return;
const resultingTestPlans = await requestTestPlan(JSON.stringify(model.job, null, 2));
resultingTestPlans && view.testPlan({ testPlans: resultingTestPlans, ptLogger });
const resultingTestPlans = await requestTestPlan(model.job);
resultingTestPlans && internals.view.testPlan({ testPlans: resultingTestPlans, ptLogger: internals.ptLogger });
};
const handleModelTesterEvents = (eventName, testerType, sessionId, message) => {
view[`handle${eventName.charAt(0).toUpperCase()}${eventName.substring(1)}`]({ testerType, sessionId, message, ptLogger });
internals.view[`handle${eventName.charAt(0).toUpperCase()}${eventName.substring(1)}`]({ testerType, sessionId, message, ptLogger: internals.ptLogger });
};

@@ -497,3 +516,3 @@

const result = await requestTest(JSON.stringify(model.job, null, 2));
const result = await requestTest(model.job);
let testerStatuses;

@@ -504,3 +523,3 @@ let testerFeedbackCommsMedium;

({ testerStatuses, testerFeedbackCommsMedium } = result);
view.test(model.testerSessions());
internals.view.test(model.testerSessions());
model.eventNames.forEach((eN) => {

@@ -523,3 +542,4 @@ model.on(eN, (testerType, sessionId, message) => { handleModelTesterEvents(eN, testerType, sessionId, message); });

module.exports = {
export default {
inject,
getJobFile,

@@ -526,0 +546,0 @@ testPlans,

@@ -183,2 +183,34 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

reportingStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
reports: {
type: 'object',
additionalProperties: false,
properties: {
templateThemes: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
name: {
type: 'string',
enum: [
'traditionalHtml',
'traditionalHtmlPlusLight',
'traditionalHtmlPlusDark',
'traditionalJson',
'traditionalMd',
'traditionalXml',
'riskConfidenceHtmlDark',
'modernMarketing',
'highLevelReport'
]
}
},
required: ['name']
},
minItems: 1
}
},
required: ['templateThemes']
},
openApi: { $ref: '#/definitions/OpenApi' },

@@ -267,2 +299,2 @@ soap: { $ref: '#/definitions/Soap' },

module.exports = { init, schema };
export { init, schema };

@@ -207,2 +207,34 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

reportingStrategy: { type: 'string', enum: ['Standard'], default: 'Standard' },
reports: {
type: 'object',
additionalProperties: false,
properties: {
templateThemes: {
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
name: {
type: 'string',
enum: [
'traditionalHtml',
'traditionalHtmlPlusLight',
'traditionalHtmlPlusDark',
'traditionalJson',
'traditionalMd',
'traditionalXml',
'riskConfidenceHtmlDark',
'modernMarketing',
'highLevelReport'
]
}
},
required: ['name']
},
minItems: 1
}
},
required: ['templateThemes']
},
excludedRoutes: {

@@ -259,2 +291,2 @@ type: 'array',

module.exports = { init, schema };
export { init, schema };

@@ -10,17 +10,15 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const jsdiff = require('diff');
const Ajv = require('ajv');
const addFormats = require('ajv-formats');
const Bourne = require('@hapi/bourne');
import { diffJson } from 'diff';
import ajvErrors from 'ajv-errors';
import addFormats from 'ajv-formats';
import Ajv from 'ajv';
import Bourne from '@hapi/bourne';
import { init as initPtLogger } from 'purpleteam-logger';
import { init as initApiSchema, schema as aPiSchema } from './job.aPi.js';
import { init as initBrowserAppSchema, schema as browserAppSchema } from './job.browserApp.js';
const ajv = new Ajv({ allErrors: true, useDefaults: true, removeAdditional: true });
addFormats(ajv);
ajvErrors(ajv);
// Todo: KC: Make error messages more meaningful.
require('ajv-errors')(ajv);
const purpleteamLogger = require('purpleteam-logger');
const aPiSchema = require('./job.aPi');
const browserAppSchema = require('./job.browserApp');
const internals = {

@@ -39,3 +37,3 @@ recognisedJobTypes: ['Api', 'BrowserApp'],

const deltaLogs = (initialConfig, possiblyMutatedConfig) => {
const deltas = jsdiff.diffJson(convertJsonToObj(initialConfig), convertJsonToObj(possiblyMutatedConfig));
const deltas = diffJson(convertJsonToObj(initialConfig), convertJsonToObj(possiblyMutatedConfig));
const additionLogs = deltas.filter((d) => d.added).map((cV) => `Added -> ${cV.value}`);

@@ -73,9 +71,9 @@ const subtractionsLogs = deltas.filter((d) => d.removed).map((cV) => `Removed -> ${cV.value}`);

internals.config.job = jobConfig;
internals.log = purpleteamLogger.init(loggerConfig);
internals.log = initPtLogger(loggerConfig);
aPiSchema.init(internals.config);
browserAppSchema.init(internals.config);
initApiSchema(internals.config);
initBrowserAppSchema(internals.config);
internals.validateApi = ajv.compile(aPiSchema.schema);
internals.validateBrowserApp = ajv.compile(browserAppSchema.schema);
internals.validateApi = ajv.compile(aPiSchema);
internals.validateBrowserApp = ajv.compile(browserAppSchema);

@@ -85,2 +83,2 @@ return { validateJob };

module.exports = { init };
export default init;

@@ -22,3 +22,3 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

module.exports = {
export {
TesterUnavailable,

@@ -25,0 +25,0 @@ TestPlanUnavailable,

@@ -10,4 +10,4 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const blessed = require('blessed');
const contrib = require('blessed-contrib');
import blessed from 'blessed';
import contrib from 'blessed-contrib';

@@ -31,3 +31,2 @@ const testOpts = {

const testPlanOpts = {

@@ -56,3 +55,3 @@ gridCoords: {

export default { testOpts, testPlanOpts };
module.exports = { testOpts, testPlanOpts };

@@ -10,7 +10,7 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const contrib = require('blessed-contrib');
import contrib from 'blessed-contrib';
const app = require('./app');
const server = require('./server');
const tls = require('./tls');
import app from './app.js';
import server from './server.js';
import tls from './tls.js';

@@ -102,3 +102,3 @@ const testerViewTypes = [app, server, tls];

module.exports = {
export {
testerViewTypes, // [app, server, tls],

@@ -105,0 +105,0 @@ testerPctCompleteType,

@@ -10,4 +10,4 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const blessed = require('blessed');
const contrib = require('blessed-contrib');
import blessed from 'blessed';
import contrib from 'blessed-contrib';

@@ -31,3 +31,2 @@ const testOpts = {

const testPlanOpts = {

@@ -56,3 +55,3 @@ gridCoords: {

export default { testOpts, testPlanOpts };
module.exports = { testOpts, testPlanOpts };

@@ -10,4 +10,4 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const blessed = require('blessed');
const contrib = require('blessed-contrib');
import blessed from 'blessed';
import contrib from 'blessed-contrib';

@@ -31,3 +31,2 @@ const testOpts = {

const testPlanOpts = {

@@ -56,3 +55,3 @@ gridCoords: {

export default { testOpts, testPlanOpts };
module.exports = { testOpts, testPlanOpts };

@@ -10,8 +10,12 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const config = require('../../config/config');
import contrib from 'blessed-contrib';
import { createRequire } from 'module';
import config from '../../config/config.js';
import { testerViewTypes, testerPctCompleteType, statTableType, newBugsType, totalProgressType } from './blessedTypes/index.js';
const require = createRequire(import.meta.url);
const { name: projectName } = require('../../package');
// blessed breaks tests, so fake it.
const blessed = require(config.get('modulePaths.blessed')); // eslint-disable-line import/no-dynamic-require
const contrib = require('blessed-contrib'); // eslint-disable-line import/order
const { name: projectName } = require('../../package.json');
const { testerViewTypes, testerPctCompleteType, statTableType, newBugsType, totalProgressType } = require('./blessedTypes');
const { default: blessed } = await import(config.get('modulePaths.blessed'));

@@ -461,3 +465,3 @@ const testerNames = testerViewTypes.map((tv) => tv.testOpts.args.name);

module.exports = {
export default {
testPlan,

@@ -464,0 +468,0 @@ test,

@@ -10,7 +10,8 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

/* eslint-disable */
const viewFileName = `./${require('../../config/config').get('uI')}`;
const view = require(viewFileName);
module.exports = view;
/* eslint-enable */
import config from '../../config/config.js';
const viewFileName = config.get(`uI.path.${config.get('uI.type')}`);
const { default: view } = await import(viewFileName);
export default view;

@@ -10,4 +10,4 @@ // Copyright (C) 2017-2022 BinaryMist Limited. All rights reserved.

const config = require('../../config/config');
const { NowAsFileName } = require('../strings');
import config from '../../config/config.js';
import { NowAsFileName } from '../strings/index.js';

@@ -43,3 +43,3 @@ const handleTesterProgress = ({ testerType, sessionId, message, ptLogger }) => {

module.exports = {
export default {
testPlan,

@@ -46,0 +46,0 @@ test,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc