juice-shop-ctf-cli
Advanced tools
Comparing version 3.2.0 to 4.0.0
#!/usr/bin/env node | ||
'use strict' | ||
const juiceShopCtfCli = require('../index') | ||
var juiceShopCtfCli = require('../index') | ||
juiceShopCtfCli() |
@@ -6,3 +6,2 @@ # Contributing [](https://github.com/bkimminich/juice-shop-ctf/graphs/contributors) [](http://waffle.io/bkimminich/juice-shop) | ||
[](https://codeclimate.com/github/bkimminich/juice-shop-ctf) | ||
[](https://www.bithound.io/github/bkimminich/juice-shop-ctf) | ||
[](https://gemnasium.com/github.com/bkimminich/juice-shop-ctf) | ||
@@ -9,0 +8,0 @@ |
60
index.js
@@ -1,12 +0,11 @@ | ||
'use strict' | ||
var inquirer = require('inquirer') | ||
var colors = require('colors') // eslint-disable-line no-unused-vars | ||
var secretKey = require('./lib/secretKey') | ||
var fetchChallenges = require('./lib/fetchChallenges') | ||
var generateData = require('./lib/generateData') | ||
var writeToZipFile = require('./lib/writeToZipFile') | ||
var options = require('./lib/options') | ||
const inquirer = require('inquirer') | ||
const colors = require('colors') // eslint-disable-line no-unused-vars | ||
const fetchSecretKey = require('./lib/fetchSecretKey') | ||
const fetchChallenges = require('./lib/fetchChallenges') | ||
const generateData = require('./lib/generateData') | ||
const writeToZipFile = require('./lib/writeToZipFile') | ||
const options = require('./lib/options') | ||
var juiceShopCtfCli = function () { | ||
var questions = [ | ||
const juiceShopCtfCli = async () => { | ||
const questions = [ | ||
{ | ||
@@ -41,28 +40,23 @@ type: 'input', | ||
console.log() | ||
console.log('Generate ZIP-archive to import into ' + 'CTFd'.bold + ' (≥1.0.5) with the ' + 'OWASP Juice Shop'.bold + ' challenges') | ||
inquirer.prompt(questions).then(function (answers) { | ||
console.log('Generate ZIP-archive to import into ' + 'CTFd'.bold + ' (≥1.1.0) with the ' + 'OWASP Juice Shop'.bold + ' challenges') | ||
try { | ||
const {ctfKey, juiceShopUrl, insertHints, insertHintUrls} = await inquirer.prompt(questions) | ||
const [secretKey, challenges] = await Promise.all([ | ||
fetchSecretKey(ctfKey), | ||
fetchChallenges(juiceShopUrl) | ||
]) | ||
const data = await generateData(challenges, insertHints, insertHintUrls, secretKey) | ||
const file = await writeToZipFile(data) | ||
console.log() | ||
secretKey(answers.ctfKey).then(function (secretKey) { | ||
fetchChallenges(answers.juiceShopUrl).then(function (challenges) { | ||
generateData(challenges, answers.insertHints, answers.insertHintUrls, secretKey).then(function (data) { | ||
writeToZipFile(data).then(function (file) { | ||
console.log('ZIP-archive written to ' + file) | ||
console.log() | ||
console.log('For a step-by-step guide to import the ZIP-archive into ' + 'CTFd'.bold + ', please refer to') | ||
console.log('https://bkimminich.gitbooks.io/pwning-owasp-juice-shop/content/part1/ctf.html#running-ctfd'.bold) | ||
}, function (error) { | ||
console.log(error.message.red) | ||
}) | ||
}, function (error) { | ||
console.log(error.message.red) | ||
}) | ||
}, function (error) { | ||
console.log(error.message.red) | ||
}) | ||
}, function (error) { | ||
console.log(error.message.red) | ||
}) | ||
}) | ||
console.log('ZIP-archive written to ' + file) | ||
console.log() | ||
console.log('For a step-by-step guide to import the ZIP-archive into ' + 'CTFd'.bold + ', please refer to') | ||
console.log('https://bkimminich.gitbooks.io/pwning-owasp-juice-shop/content/part1/ctf.html#running-ctfd'.bold) | ||
} catch (error) { | ||
console.log(error.message.red) | ||
} | ||
} | ||
module.exports = juiceShopCtfCli |
@@ -1,4 +0,3 @@ | ||
'use strict' | ||
var calculateScore = require('./calculateScore') | ||
var options = require('./options') | ||
const calculateScore = require('./calculateScore') | ||
const options = require('./options') | ||
@@ -10,4 +9,4 @@ /* The hint costs depend on the kind of hint and the difficulty of the challenge they are for: | ||
*/ | ||
function calculateHintCost (challenge, hintOption) { | ||
var costMultiplier = 0 | ||
function calculateHintCost ({difficulty}, hintOption) { | ||
let costMultiplier = 0 | ||
if (hintOption === options.paidTextHints) { | ||
@@ -18,4 +17,4 @@ costMultiplier = 0.1 | ||
} | ||
return costMultiplier * calculateScore(challenge.difficulty) | ||
return costMultiplier * calculateScore(difficulty) | ||
} | ||
module.exports = calculateHintCost |
@@ -1,12 +0,11 @@ | ||
'use strict' | ||
/* This is a default multiplier whereby the score will be = (difficulty x multiplier) | ||
i.e. using these multipliers will create challenges with the following scores: | ||
* = 100 | ||
** = 250 | ||
*** = 450 | ||
**** = 700 | ||
***** = 1000 | ||
I think it is fair to assume that completing a 5* task will be 10 times harder than a 1* task. | ||
* = 100 | ||
** = 250 | ||
*** = 450 | ||
**** = 700 | ||
***** = 1000 | ||
****** = 1350 | ||
*/ | ||
var multiplier = [ 100, 125, 150, 175, 200 ] | ||
const multiplier = [ 100, 125, 150, 175, 200, 225 ] | ||
function calculateScore (difficulty) { | ||
@@ -13,0 +12,0 @@ return difficulty * multiplier[ difficulty - 1 ] |
@@ -1,11 +0,10 @@ | ||
'use strict' | ||
var Promise = require('bluebird') | ||
var request = require('request-promise') | ||
const Promise = require('bluebird') | ||
const request = require('request-promise') | ||
function fetchChallenges (juiceShopUrl) { | ||
return new Promise(function (resolve, reject) { | ||
request({ url: juiceShopUrl + '/api/Challenges', json: true }).then(function (body) { | ||
resolve(body.data) | ||
}).catch(function (error) { | ||
reject(new Error('Failed to fetch challenges from API! ' + error.message)) | ||
return new Promise((resolve, reject) => { | ||
request({ url: juiceShopUrl + '/api/Challenges', json: true }).then(({data}) => { | ||
resolve(data) | ||
}).catch(({message}) => { | ||
reject(new Error('Failed to fetch challenges from API! ' + message)) | ||
}) | ||
@@ -12,0 +11,0 @@ }) |
@@ -1,11 +0,10 @@ | ||
'use strict' | ||
var Promise = require('bluebird') | ||
var calculateScore = require('./calculateScore') | ||
var calculateHintCost = require('./calculateHintCost') | ||
var hmacSha1 = require('./hmac') | ||
var options = require('./options') | ||
const Promise = require('bluebird') | ||
const calculateScore = require('./calculateScore') | ||
const calculateHintCost = require('./calculateHintCost') | ||
const hmacSha1 = require('./hmac') | ||
const options = require('./options') | ||
function generateData (challenges, insertHints, insertHintUrls, ctfKey) { | ||
function insertChallenge (data, challenge) { | ||
var score = calculateScore(challenge.difficulty) | ||
const score = calculateScore(challenge.difficulty) | ||
data.challenges['results'].push( | ||
@@ -25,10 +24,9 @@ { | ||
function insertKey (data, challenge) { | ||
data.flagKeys['results'].push( | ||
function insertKey ({flagKeys}, {id, name}) { | ||
flagKeys['results'].push( | ||
{ | ||
'id': challenge.id, | ||
'chal': challenge.id, | ||
'key_type': 'static', // TODO Remove deprecated predecessor (from CTFd 1.0.5) of `type` with v4.0.0 release | ||
'id': id, | ||
'chal': id, | ||
'type': 'static', | ||
'flag': hmacSha1(ctfKey, challenge.name), | ||
'flag': hmacSha1(ctfKey, name), | ||
'data': null | ||
@@ -39,4 +37,4 @@ } | ||
function insertTextHint (data, challenge) { | ||
data.hints['results'].push( | ||
function insertTextHint ({hints}, challenge) { | ||
hints['results'].push( | ||
{ | ||
@@ -52,4 +50,4 @@ 'id': challenge.id, | ||
function insertHintUrl (data, challenge) { | ||
data.hints['results'].push( | ||
function insertHintUrl ({hints}, challenge) { | ||
hints['results'].push( | ||
{ | ||
@@ -65,5 +63,5 @@ 'id': 10000 + challenge.id, | ||
return new Promise(function (resolve, reject) { | ||
return new Promise((resolve, reject) => { | ||
try { | ||
var data = { | ||
const data = { | ||
challenges: {'results': []}, | ||
@@ -73,5 +71,5 @@ hints: {'results': []}, | ||
} | ||
for (var key in challenges) { | ||
for (const key in challenges) { | ||
if (challenges.hasOwnProperty(key)) { | ||
var challenge = challenges[key] | ||
const challenge = challenges[key] | ||
insertChallenge(data, challenge) | ||
@@ -78,0 +76,0 @@ insertKey(data, challenge) |
@@ -1,6 +0,5 @@ | ||
'use strict' | ||
var jsSHA = require('jssha') | ||
const jsSHA = require('jssha') | ||
function hmacSha1 (secretKey, text) { | ||
var shaObj = new jsSHA('SHA-1', 'TEXT') // eslint-disable-line new-cap | ||
const shaObj = new jsSHA('SHA-1', 'TEXT') // eslint-disable-line new-cap | ||
shaObj.setHMACKey(secretKey, 'TEXT') | ||
@@ -7,0 +6,0 @@ shaObj.update(text) |
@@ -1,2 +0,1 @@ | ||
'use strict' | ||
module.exports = { | ||
@@ -3,0 +2,0 @@ noTextHints: 'No text hints', |
@@ -1,3 +0,1 @@ | ||
'use strict' | ||
function isUrl (text) { | ||
@@ -4,0 +2,0 @@ return text.match(/^(http|localhost|[0-9][0-9]?[0-9]?\.)/) !== null |
@@ -1,22 +0,21 @@ | ||
'use strict' | ||
var Promise = require('bluebird') | ||
var fs = require('fs') | ||
const Promise = require('bluebird') | ||
const fs = require('fs') | ||
Promise.promisifyAll(fs) | ||
var path = require('path') | ||
var dateFormat = require('dateformat') | ||
var Zip = require('node-zip') | ||
var zip = new Zip() | ||
const path = require('path') | ||
const dateFormat = require('dateformat') | ||
const Zip = require('node-zip') | ||
const zip = new Zip() | ||
function writeToZipFile (data) { | ||
return new Promise(function (resolve, reject) { | ||
var fileName = 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.zip' | ||
zip.file('db/challenges.json', JSON.stringify(data.challenges)) | ||
zip.file('db/hints.json', JSON.stringify(data.hints)) | ||
zip.file('db/keys.json', JSON.stringify(data.flagKeys)) | ||
function writeToZipFile ({challenges, hints, flagKeys}) { | ||
return new Promise((resolve, reject) => { | ||
const fileName = 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.zip' | ||
zip.file('db/challenges.json', JSON.stringify(challenges)) | ||
zip.file('db/hints.json', JSON.stringify(hints)) | ||
zip.file('db/keys.json', JSON.stringify(flagKeys)) | ||
zip.file('db/files.json', '') | ||
zip.file('db/tags.json', '') | ||
fs.writeFileAsync(fileName, zip.generate({base64: false, compression: 'DEFLATE'}), 'binary').then(function () { | ||
fs.writeFileAsync(fileName, zip.generate({base64: false, compression: 'DEFLATE'}), 'binary').then(() => { | ||
resolve(path.resolve(fileName).green) | ||
}).catch(function (error) { | ||
reject(new Error('Failed to write output to file! ' + error.message)) | ||
}).catch(({message}) => { | ||
reject(new Error('Failed to write output to file! ' + message)) | ||
}) | ||
@@ -23,0 +22,0 @@ }) |
{ | ||
"name": "juice-shop-ctf-cli", | ||
"version": "3.2.0", | ||
"version": "4.0.0", | ||
"description": "Command line client to generate INSERT statements for CTFd with the OWASP Juice Shop challenges", | ||
@@ -47,3 +47,3 @@ "author": "Bjoern Kimminich <bjoern.kimminich@owasp.org> (https://www.owasp.org/index.php/User:Bjoern_Kimminich)", | ||
"engines": { | ||
"node": ">=6 <=9" | ||
"node": ">=8 <=9" | ||
}, | ||
@@ -54,3 +54,3 @@ "dependencies": { | ||
"dateformat": "~3.0", | ||
"inquirer": "~5.0", | ||
"inquirer": "~5.1.0", | ||
"jssha": "~2.3", | ||
@@ -75,3 +75,3 @@ "node-zip": "~1.1", | ||
"rewire": "~3", | ||
"standard": "~10", | ||
"standard": "~11.0.0", | ||
"stryker": "~0", | ||
@@ -78,0 +78,0 @@ "stryker-api": "~0", |
@@ -6,3 +6,2 @@ #  OWASP Juice Shop CTF [](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Labs_Projects) [](https://github.com/bkimminich/juice-shop-ctf/releases/latest) [](https://twitter.com/owasp_juiceshop) | ||
[](https://codeclimate.com/github/bkimminich/juice-shop-ctf) | ||
[](https://www.bithound.io/github/bkimminich/juice-shop-ctf) | ||
[](https://gemnasium.com/github.com/bkimminich/juice-shop-ctf) | ||
@@ -21,5 +20,5 @@ [](https://greenkeeper.io/) | ||
> :information_source: The data format generated by `v3.x` of this utility | ||
> :information_source: The data format generated by `v4.x` of this utility | ||
> has been tested for schema-compatibility with | ||
> [CTFd `≥v1.0.5`](https://github.com/CTFd/CTFd/releases/tag/1.0.5). | ||
> [CTFd `≥v1.1.0`](https://github.com/CTFd/CTFd/releases/tag/1.1.0). | ||
@@ -109,3 +108,3 @@ ## Setup [](https://www.npmjs.com/package/juice-shop-ctf-cli) [](https://www.npmjs.com/package/juice-shop-ctf-cli) | ||
## Licensing [](LICENSE) [](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fbkimminich%2Fjuice-shop-ctf?ref=badge_shield) | ||
## Licensing [](LICENSE) | ||
@@ -112,0 +111,0 @@ This program is free software: you can redistribute it and/or modify it |
@@ -1,6 +0,4 @@ | ||
// stryker.conf.js | ||
module.exports = function (config) { | ||
config.set({ | ||
files: [ | ||
// Add your files here, this is just an example: | ||
{ pattern: 'index.js', mutated: false, included: false }, | ||
@@ -7,0 +5,0 @@ { pattern: 'lib/**/*.js', mutated: true, included: false }, |
@@ -1,17 +0,17 @@ | ||
var chai = require('chai') | ||
const chai = require('chai') | ||
chai.use(require('chai-as-promised')) | ||
var expect = chai.expect | ||
var inquirer = require('inquirer-test') | ||
var run = inquirer | ||
var ENTER = inquirer.ENTER | ||
var DOWN = inquirer.DOWN | ||
var fs = require('fs') | ||
var path = require('path') | ||
var dateFormat = require('dateformat') | ||
var outputFile = 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.zip' | ||
const expect = chai.expect | ||
const inquirer = require('inquirer-test') | ||
const run = inquirer | ||
const ENTER = inquirer.ENTER | ||
const DOWN = inquirer.DOWN | ||
const fs = require('fs') | ||
const path = require('path') | ||
const dateFormat = require('dateformat') | ||
const outputFile = 'OWASP_Juice_Shop.' + dateFormat(new Date(), 'yyyy-mm-dd') + '.zip' | ||
const juiceShopCtfCli = [path.join(__dirname, '../../bin/juice-shop-ctf.js')] | ||
describe('juice-shop-ctf', function () { | ||
beforeEach(function () { | ||
describe('juice-shop-ctf', () => { | ||
beforeEach(() => { | ||
if (fs.existsSync(outputFile)) { | ||
@@ -18,0 +18,0 @@ fs.unlinkSync(outputFile) |
@@ -1,8 +0,8 @@ | ||
var chai = require('chai') | ||
var expect = chai.expect | ||
var calculateHintCost = require('../../lib/calculateHintCost') | ||
var options = require('../../lib/options') | ||
const chai = require('chai') | ||
const expect = chai.expect | ||
const calculateHintCost = require('../../lib/calculateHintCost') | ||
const options = require('../../lib/options') | ||
describe('Hints', function () { | ||
it('should cost 10% of their point value for text hints when payment is required', function () { | ||
describe('Hints', () => { | ||
it('should cost 10% of their point value for text hints when payment is required', () => { | ||
expect(calculateHintCost({difficulty: 1}, options.paidTextHints)).to.equal(10) | ||
@@ -13,5 +13,6 @@ expect(calculateHintCost({difficulty: 2}, options.paidTextHints)).to.equal(25) | ||
expect(calculateHintCost({difficulty: 5}, options.paidTextHints)).to.equal(100) | ||
expect(calculateHintCost({difficulty: 6}, options.paidTextHints)).to.equal(135) | ||
}) | ||
it('should cost 20% of their point value for hint URLs when payment is required', function () { | ||
it('should cost 20% of their point value for hint URLs when payment is required', () => { | ||
expect(calculateHintCost({difficulty: 1}, options.paidHintUrls)).to.equal(20) | ||
@@ -22,5 +23,6 @@ expect(calculateHintCost({difficulty: 2}, options.paidHintUrls)).to.equal(50) | ||
expect(calculateHintCost({difficulty: 5}, options.paidHintUrls)).to.equal(200) | ||
expect(calculateHintCost({difficulty: 6}, options.paidHintUrls)).to.equal(270) | ||
}) | ||
it('should cost no points for text hints for all challenge difficulties when free', function () { | ||
it('should cost no points for text hints for all challenge difficulties when free', () => { | ||
expect(calculateHintCost({difficulty: 1}, options.freeTextHints)).to.equal(0) | ||
@@ -31,5 +33,6 @@ expect(calculateHintCost({difficulty: 2}, options.freeTextHints)).to.equal(0) | ||
expect(calculateHintCost({difficulty: 5}, options.freeTextHints)).to.equal(0) | ||
expect(calculateHintCost({difficulty: 6}, options.freeTextHints)).to.equal(0) | ||
}) | ||
it('should cost no points for hint URLs for all challenge difficulties when free', function () { | ||
it('should cost no points for hint URLs for all challenge difficulties when free', () => { | ||
expect(calculateHintCost({difficulty: 1}, options.freeHintUrls)).to.equal(0) | ||
@@ -40,3 +43,4 @@ expect(calculateHintCost({difficulty: 2}, options.freeHintUrls)).to.equal(0) | ||
expect(calculateHintCost({difficulty: 5}, options.freeHintUrls)).to.equal(0) | ||
expect(calculateHintCost({difficulty: 6}, options.freeHintUrls)).to.equal(0) | ||
}) | ||
}) |
@@ -1,25 +0,29 @@ | ||
var chai = require('chai') | ||
var expect = chai.expect | ||
var calculateScore = require('../../lib/calculateScore') | ||
const chai = require('chai') | ||
const expect = chai.expect | ||
const calculateScore = require('../../lib/calculateScore') | ||
describe('Score', function () { | ||
it('should be 100 points for a * challenge', function () { | ||
describe('Score', () => { | ||
it('should be 100 points for a * challenge', () => { | ||
expect(calculateScore(1)).to.equal(100) | ||
}) | ||
it('should be 250 points for a ** challenge', function () { | ||
it('should be 250 points for a ** challenge', () => { | ||
expect(calculateScore(2)).to.equal(250) | ||
}) | ||
it('should be 450 points for a *** challenge', function () { | ||
it('should be 450 points for a *** challenge', () => { | ||
expect(calculateScore(3)).to.equal(450) | ||
}) | ||
it('should be 700 points for a **** challenge', function () { | ||
it('should be 700 points for a **** challenge', () => { | ||
expect(calculateScore(4)).to.equal(700) | ||
}) | ||
it('should be 1000 points for a ***** challenge', function () { | ||
it('should be 1000 points for a ***** challenge', () => { | ||
expect(calculateScore(5)).to.equal(1000) | ||
}) | ||
it('should be 1350 points for a ****** challenge', () => { | ||
expect(calculateScore(6)).to.equal(1350) | ||
}) | ||
}) |
@@ -1,14 +0,14 @@ | ||
var Promise = require('bluebird') | ||
var chai = require('chai') | ||
const Promise = require('bluebird') | ||
const chai = require('chai') | ||
chai.use(require('chai-as-promised')) | ||
var expect = chai.expect | ||
var rewire = require('rewire') | ||
var fetchChallenges = rewire('../../lib/fetchChallenges') | ||
const expect = chai.expect | ||
const rewire = require('rewire') | ||
const fetchChallenges = rewire('../../lib/fetchChallenges') | ||
describe('Challenges', function () { | ||
it('should be fetched from the given URL', function () { | ||
describe('Challenges', () => { | ||
it('should be fetched from the given URL', () => { | ||
fetchChallenges.__set__({ | ||
request: function (options) { | ||
request (options) { | ||
expect(options).to.deep.equal({ url: 'http://localhost:3000/api/Challenges', json: true }) | ||
return new Promise(function (resolve) { resolve({ data: { c1: { }, c2: { } } }) }) | ||
return new Promise(resolve => { resolve({ data: { c1: { }, c2: { } } }) }) | ||
} | ||
@@ -19,6 +19,6 @@ }) | ||
it('should log retrieval error to console', function () { | ||
it('should log retrieval error to console', () => { | ||
fetchChallenges.__set__({ | ||
request: function () { | ||
return new Promise(function (resolve, reject) { reject(new Error('Argh!')) }) | ||
request () { | ||
return new Promise((resolve, reject) => { reject(new Error('Argh!')) }) | ||
} | ||
@@ -25,0 +25,0 @@ }) |
@@ -1,13 +0,13 @@ | ||
var Promise = require('bluebird') | ||
var chai = require('chai') | ||
const Promise = require('bluebird') | ||
const chai = require('chai') | ||
chai.use(require('chai-things')) | ||
chai.use(require('chai-subset')) | ||
chai.use(require('chai-as-promised')) | ||
var expect = chai.expect | ||
var generateData = require('../../lib/generateData') | ||
var options = require('../../lib/options') | ||
const expect = chai.expect | ||
const generateData = require('../../lib/generateData') | ||
const options = require('../../lib/options') | ||
describe('Generated data', function () { | ||
var challenges | ||
beforeEach(function () { | ||
describe('Generated data', () => { | ||
let challenges | ||
beforeEach(() => { | ||
challenges = { | ||
@@ -22,69 +22,48 @@ c1: {id: 1, name: 'c1', description: 'C1', difficulty: 1, category: '1'}, | ||
it('should consist of one object pushed into challenges.results per challenge', function () { | ||
return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include( | ||
{ | ||
challenges: { | ||
results: [ | ||
{ id: 1, name: 'c1', description: 'C1 (Difficulty Level: 1)', value: 100, category: '1', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 2, name: 'c2', description: 'C2 (Difficulty Level: 2)', value: 250, category: '2', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 3, name: 'c3', description: 'C3 (Difficulty Level: 3)', value: 450, category: '2', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 4, name: 'c4', description: 'C4 (Difficulty Level: 4)', value: 700, category: '3', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 5, name: 'c5', description: 'C5 (Difficulty Level: 5)', value: 1000, category: '1', hidden: false, max_attempts: 0, type: 'standard' } | ||
] | ||
} | ||
}) | ||
}) | ||
it('should consist of one object pushed into challenges.results per challenge', () => expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include( | ||
{ | ||
challenges: { | ||
results: [ | ||
{ id: 1, name: 'c1', description: 'C1 (Difficulty Level: 1)', value: 100, category: '1', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 2, name: 'c2', description: 'C2 (Difficulty Level: 2)', value: 250, category: '2', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 3, name: 'c3', description: 'C3 (Difficulty Level: 3)', value: 450, category: '2', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 4, name: 'c4', description: 'C4 (Difficulty Level: 4)', value: 700, category: '3', hidden: false, max_attempts: 0, type: 'standard' }, | ||
{ id: 5, name: 'c5', description: 'C5 (Difficulty Level: 5)', value: 1000, category: '1', hidden: false, max_attempts: 0, type: 'standard' } | ||
] | ||
} | ||
})) | ||
it('should consist of one object pushed into flagKeys.results per challenge', function () { | ||
return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include( | ||
{ | ||
flagKeys: { | ||
results: [ | ||
{ id: 1, chal: 1, flag: '958c64658383140e7d08d5dee091009cc0eafc1f', type: 'static', key_type: 'static', data: null }, | ||
{ id: 2, chal: 2, flag: '49294e8b829f5b053f748facad22825ccb4bf420', type: 'static', key_type: 'static', data: null }, | ||
{ id: 3, chal: 3, flag: 'aae3acb6eff2000c0e12af0d0d875d0bdbf4ca81', type: 'static', key_type: 'static', data: null }, | ||
{ id: 4, chal: 4, flag: '4e2b98db86cc32c56cba287db411198534af4ab6', type: 'static', key_type: 'static', data: null }, | ||
{ id: 5, chal: 5, flag: '554df67c6c0b6a99efecaec4fe2ced73b7b5be60', type: 'static', key_type: 'static', data: null } | ||
] | ||
} | ||
}) | ||
}) | ||
it('should consist of one object pushed into flagKeys.results per challenge', () => expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include( | ||
{ | ||
flagKeys: { | ||
results: [ | ||
{ id: 1, chal: 1, flag: '958c64658383140e7d08d5dee091009cc0eafc1f', type: 'static', data: null }, | ||
{ id: 2, chal: 2, flag: '49294e8b829f5b053f748facad22825ccb4bf420', type: 'static', data: null }, | ||
{ id: 3, chal: 3, flag: 'aae3acb6eff2000c0e12af0d0d875d0bdbf4ca81', type: 'static', data: null }, | ||
{ id: 4, chal: 4, flag: '4e2b98db86cc32c56cba287db411198534af4ab6', type: 'static', data: null }, | ||
{ id: 5, chal: 5, flag: '554df67c6c0b6a99efecaec4fe2ced73b7b5be60', type: 'static', data: null } | ||
] | ||
} | ||
})) | ||
xit('should consist of one object pushed into flagKeys.results per challenge', function () { | ||
return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.containSubset( | ||
{ | ||
flagKeys: { | ||
results: [ | ||
{ id: 1, chal: 1, flag: '958c64658383140e7d08d5dee091009cc0eafc1f', type: 'static', data: null }, | ||
{ id: 2, chal: 2, flag: '49294e8b829f5b053f748facad22825ccb4bf420', type: 'static', data: null }, | ||
{ id: 3, chal: 3, flag: 'aae3acb6eff2000c0e12af0d0d875d0bdbf4ca81', type: 'static', data: null }, | ||
{ id: 4, chal: 4, flag: '4e2b98db86cc32c56cba287db411198534af4ab6', type: 'static', data: null }, | ||
{ id: 5, chal: 5, flag: '554df67c6c0b6a99efecaec4fe2ced73b7b5be60', type: 'static', data: null } | ||
] | ||
} | ||
}) | ||
}) | ||
xit('should consist of one object pushed into flagKeys.results per challenge', () => expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.containSubset( | ||
{ | ||
flagKeys: { | ||
results: [ | ||
{ id: 1, chal: 1, flag: '958c64658383140e7d08d5dee091009cc0eafc1f', type: 'static', data: null }, | ||
{ id: 2, chal: 2, flag: '49294e8b829f5b053f748facad22825ccb4bf420', type: 'static', data: null }, | ||
{ id: 3, chal: 3, flag: 'aae3acb6eff2000c0e12af0d0d875d0bdbf4ca81', type: 'static', data: null }, | ||
{ id: 4, chal: 4, flag: '4e2b98db86cc32c56cba287db411198534af4ab6', type: 'static', data: null }, | ||
{ id: 5, chal: 5, flag: '554df67c6c0b6a99efecaec4fe2ced73b7b5be60', type: 'static', data: null } | ||
] | ||
} | ||
})) | ||
xit('should contain the "key_type" property for backward compatibility with CTFd <1.1.0', function () { | ||
return expect(generateData(challenges, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.containSubset( | ||
{ | ||
flagKeys: { | ||
results: [ | ||
{ key_type: 'static' } | ||
] | ||
} | ||
}) | ||
}) | ||
it('should be empty when given no challenges', () => expect(generateData({}, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include( | ||
{ challenges: { results: [] } } | ||
)) | ||
it('should be empty when given no challenges', function () { | ||
return expect(generateData({}, options.noTextHints, options.noHintUrls, '')).to.eventually.deep.include( | ||
{ challenges: { results: [] } } | ||
) | ||
}) | ||
it('should log generator error to console', () => expect(generateData({c1: undefined}, options.noTextHints, options.noHintUrls, '')).to.be.rejectedWith('Failed to generate challenge data! Cannot read property \'difficulty\' of undefined')) | ||
it('should log generator error to console', function () { | ||
return expect(generateData({c1: undefined}, options.noTextHints, options.noHintUrls, '')).to.be.rejectedWith('Failed to generate challenge data! Cannot read property \'difficulty\' of undefined') | ||
}) | ||
it('should push an object into hints.results for a text hint defined on a challenge', function () { | ||
it('should push an object into hints.results for a text hint defined on a challenge', () => { | ||
challenges.c3.hint = 'hint' | ||
@@ -111,3 +90,3 @@ return Promise.all([ | ||
it('should push an object into hints.results for a text hint URL defined on a challenge', function () { | ||
it('should push an object into hints.results for a text hint URL defined on a challenge', () => { | ||
challenges.c3.hintUrl = 'hintUrl' | ||
@@ -134,3 +113,3 @@ return Promise.all([ | ||
it('should push an object each into hints.results for a challenge with text hint and hint URL defined', function () { | ||
it('should push an object each into hints.results for a challenge with text hint and hint URL defined', () => { | ||
challenges.c3.hint = 'hint' | ||
@@ -178,3 +157,3 @@ challenges.c3.hintUrl = 'hintUrl' | ||
it('should not insert a text hint when corresponding hint option is not chosen', function () { | ||
it('should not insert a text hint when corresponding hint option is not chosen', () => { | ||
challenges.c1.hint = 'hint' | ||
@@ -187,3 +166,3 @@ challenges.c2.hint = 'hint' | ||
it('should not insert a hint URL when corresponding hint option is not chosen', function () { | ||
it('should not insert a hint URL when corresponding hint option is not chosen', () => { | ||
challenges.c1.hintUrl = 'hintUrl' | ||
@@ -196,3 +175,3 @@ challenges.c2.hintUrl = 'hintUrl' | ||
it('should not insert a text hint for challenges that do not have a hint defined', function () { | ||
it('should not insert a text hint for challenges that do not have a hint defined', () => { | ||
challenges.c1.hint = 'hint' | ||
@@ -223,3 +202,3 @@ challenges.c2.hint = 'hint' | ||
it('should not insert a hint URL for challenges that do not have a hint defined', function () { | ||
it('should not insert a hint URL for challenges that do not have a hint defined', () => { | ||
challenges.c1.hintUrl = 'hintUrl' | ||
@@ -226,0 +205,0 @@ challenges.c2.hintUrl = 'hintUrl' |
@@ -1,17 +0,17 @@ | ||
var chai = require('chai') | ||
var expect = chai.expect | ||
var hmacSha1 = require('../../lib/hmac') | ||
const chai = require('chai') | ||
const expect = chai.expect | ||
const hmacSha1 = require('../../lib/hmac') | ||
describe('Flag', function () { | ||
it('should be a SHA256 HMAC from plain text and given secret key', function () { | ||
describe('Flag', () => { | ||
it('should be a SHA256 HMAC from plain text and given secret key', () => { | ||
expect(hmacSha1('ZJnHOTckstBeJP!QC2T', 'text')).to.equal('5188938396d17832dd26fbabd5ac4d79518a87da') | ||
}) | ||
it('should be a SHA256 HMAC from plain text and empty secret key', function () { | ||
it('should be a SHA256 HMAC from plain text and empty secret key', () => { | ||
expect(hmacSha1('', 'text')).to.equal('f3f276f5001644013dbd202f1854bd61f9123d0f') | ||
}) | ||
it('should be different for different plain texts with same secret key', function () { | ||
it('should be different for different plain texts with same secret key', () => { | ||
expect(hmacSha1('key', 'text1')).to.not.equal(hmacSha1('key', 'text2')) | ||
}) | ||
}) |
@@ -1,21 +0,21 @@ | ||
var chai = require('chai') | ||
var expect = chai.expect | ||
var url = require('../../lib/url') | ||
const chai = require('chai') | ||
const expect = chai.expect | ||
const url = require('../../lib/url') | ||
describe('URL', function () { | ||
it('should be recognized on given valid HTTP URL', function () { | ||
describe('URL', () => { | ||
it('should be recognized on given valid HTTP URL', () => { | ||
expect(url('http://domain')).to.equal(true) | ||
}) | ||
it('should be recognized on given valid HTTPS URL', function () { | ||
it('should be recognized on given valid HTTPS URL', () => { | ||
expect(url('https://domain')).to.equal(true) | ||
}) | ||
it('should be recognized on given valid IP address', function () { | ||
it('should be recognized on given valid IP address', () => { | ||
expect(url('127.0.0.1')).to.equal(true) | ||
}) | ||
it('should not be recognized on given HMAC key', function () { | ||
it('should not be recognized on given HMAC key', () => { | ||
expect(url('ZRwakRJnHOTckstBeyJbyswgP!QC2T')).to.equal(false) | ||
}) | ||
}) |
@@ -1,16 +0,16 @@ | ||
var Promise = require('bluebird') | ||
var chai = require('chai') | ||
const Promise = require('bluebird') | ||
const chai = require('chai') | ||
chai.use(require('chai-as-promised')) | ||
var expect = chai.expect | ||
var rewire = require('rewire') | ||
var writeToZipFile = rewire('../../lib/writeToZipFile') | ||
const expect = chai.expect | ||
const rewire = require('rewire') | ||
const writeToZipFile = rewire('../../lib/writeToZipFile') | ||
describe('Output to file', function () { | ||
it('should be written to ZIP file', function () { | ||
describe('Output to file', () => { | ||
it('should be written to ZIP file', () => { | ||
writeToZipFile.__set__({ | ||
console: { | ||
log: function () {} | ||
log () {} | ||
}, | ||
fs: { | ||
writeFileAsync: function (path, data) { | ||
writeFileAsync (path, data) { | ||
expect(data).to.match(/challenges.json/) | ||
@@ -22,3 +22,3 @@ expect(data).to.match(/hints.json/) | ||
expect(path).to.match(/OWASP_Juice_Shop\.[0-9]{4}-[0-9]{2}-[0-9]{2}\.zip/) | ||
return new Promise(function (resolve) { resolve() }) | ||
return new Promise(resolve => { resolve() }) | ||
}} | ||
@@ -30,7 +30,7 @@ }) | ||
it('should log file system error to console', function () { | ||
it('should log file system error to console', () => { | ||
writeToZipFile.__set__({ | ||
fs: { | ||
writeFileAsync: function (path, data) { | ||
return new Promise(function () { throw new Error('Argh!') }) | ||
writeFileAsync (path, data) { | ||
return new Promise(() => { throw new Error('Argh!') }) | ||
}} | ||
@@ -37,0 +37,0 @@ }) |
Sorry, the diff of this file is not supported yet
766773
706
113
+ Addedinquirer@5.1.0(transitive)
- Removedinquirer@5.0.1(transitive)
Updatedinquirer@~5.1.0