Socket
Socket
Sign inDemoInstall

dia

Package Overview
Dependencies
111
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.2 to 0.2.0

.travis.yml

44

lib/cli.js

@@ -7,12 +7,12 @@ //

var fs = require('fs')
, colors = require('colors')
, prompt = require('prompt')
, program = require('commander-plus')
, dia = require('./dia');
var program = require('commander-plus');
var colors = require('colors');
var prompt = require('prompt');
var dia = require('./dia');
var fs = require('fs');
colors.setTheme({
info: 'cyan'
, fail: 'red'
, pass: 'green'
info: 'cyan',
fail: 'red',
pass: 'green'
});

@@ -51,7 +51,7 @@

prompt.get([{
name: 'overwrite'
, pattern: /^[yn]/
, message: 'Response must be "y" or "n"'
, description: 'Manifest already exists. Replace it? (y/n)'
, required: true
name: 'overwrite',
pattern: /^[yn]/,
message: 'Response must be "y" or "n"',
description: 'Manifest already exists. Replace it? (y/n)',
required: true
}], function(err, result) {

@@ -112,12 +112,12 @@ if (typeof result !== 'undefined' && result.overwrite === 'y') {

var prompts = [{
name: 'username'
, description: 'Enter your username or email address (Modulus or GitHub)'
, required: true
name: 'username',
description: 'Enter your username or email address (Modulus or GitHub)',
required: true
},
{
name: 'password',
description: 'Enter your password (Modulus or GitHub)',
hidden: true,
required: true
}
, {
name: 'password'
, description: 'Enter your password (Modulus or GitHub)'
, hidden: true
, required: true
}
];

@@ -124,0 +124,0 @@

//
// Dia
// Copyright(c) 2013 Modulus <support@modulus.io>
// Copyright(c) 2014 Modulus <support@modulus.io>
// MIT Licensed
//
var librarian = require('./librarian')
, UserConfig = require('./user-config')
, randpass = require('randpass')
, request = require('request')
, path = require('path')
, util = require('util')
, url = require('url')
, crypto = require('crypto')
, fs = require('fs');
var UserConfig = require('./user-config');
var librarian = require('./librarian');
var randpass = require('randpass');
var request = require('request');
var path = require('path');
var util = require('util');
var url = require('url');
var fs = require('fs');
var dia = exports;
dia.manifest = {};

@@ -38,219 +38,50 @@ dia.plan = 'test';

//
// Helper functions for validating manifest properties.
// ===
//
var validators = require('./validators')(dia);
//
// Validate a string value - check that the value exists, is a string,
// and is not empty.
// Run the specified tests.
//
var validateString = function(value, name, pass) {
if (typeof value === 'undefined') {
pass = false;
console.log(' check if exists', '[FAIL]'.fail);
return console.log(util.format(' %s is required', name).fail);
} else {
console.log(' check if exists', '[PASS]'.pass);
if (typeof value === 'string' && value.length > 0) {
console.log(util.format(' check %s value', name), '[PASS]'.pass);
} else {
pass = false;
console.log(util.format(' check %s value', name), '[FAIL]'.fail);
console.log(util.format(' %s must be a string and not empty', name).fail);
}
}
};
dia.test = function () {
var type, filename, options;
var args = Array.prototype.slice.call(arguments);
//
// Validate each property of a manifest.
//
var validateManifestInternal = function(manifest, fn) {
var pass = true;
type = args.shift();
filename = args.shift();
console.log('\ntesting manifest id'.info);
validateString(manifest.id, 'id');
console.log();
console.log('testing manifest api'.info);
if (typeof manifest.api === 'undefined') {
console.log(' check if exists', '[FAIL]'.fail);
console.log(' api object is required'.fail);
return fn(false);
} else {
console.log(' check if exists', '[PASS]'.pass);
// Parse remaining arguments if present.
if (args.length > 0) {
options = args.shift();
}
console.log();
console.log('testing config_vars'.info);
if (typeof manifest.api.config_vars === 'undefined') {
pass = false;
console.log(' check that config_vars exists', '[FAIL]'.fail);
} else {
console.log(' check that config_vars exists', '[PASS]'.pass);
if (args.length > 0) {
dia.plan = args.shift();
}
if (!(manifest.api.config_vars instanceof Array)) {
pass = false;
console.log(' check that config_vars is an array', '[FAIL]'.fail);
} else {
if (manifest.api.config_vars.length === 0) {
console.log(' check that config_vars contains at lease one config var', '[FAIL]'.fail);
} else {
console.log(' check that config_vars contains at lease one config var', '[PASS]'.pass);
validators.manifest(filename, function (result) {
if (type === 'manifest' || !result || typeof dia.manifest.api.test === 'undefined') {
return;
}
console.log(' check that config_vars is an array', '[PASS]'.pass);
for (var i = 0; i < manifest.api.config_vars.length; i++) {
if (!manifest.id || manifest.api.config_vars[i].indexOf(manifest.id.toUpperCase()) !== 0) {
pass = false;
console.log(' check that config_vars match manifest id', '[FAIL]'.fail);
if (manifest.id) {
// Only show error if the ID exists.
pass = false;
console.log(util.format(' config variables must be prefixed with %s_', manifest.id.toUpperCase()).fail);
}
} else {
console.log(' check that config_vars match manifest id', '[PASS]'.pass);
if (type === 'all') {
validators.provision(function () {
validators.planchange(function () {
validators.deprovision(function () {
validators.sso(options || dia.id);
});
});
});
} else {
if (type === 'provision') {
validators.provision();
}
}
}
console.log();
console.log('testing api authentication properties'.info);
validateString(manifest.api.password, 'api password', pass);
validateString(manifest.api.sso_salt, 'api sso salt', pass);
console.log();
console.log('testing production api properties'.info);
if (typeof manifest.api.production === 'undefined') {
console.log(' check for production api', '[FAIL]'.fail);
console.log();
return fn(false);
} else {
console.log(' check for production api', '[PASS]'.pass);
}
validateString(manifest.api.production.base_url, 'production base_url', pass);
validateString(manifest.api.production.sso_url, 'production sso_url', pass);
console.log();
console.log('testing test api properties'.info);
if (typeof manifest.api.test === 'undefined') {
console.log(' check for test api', '[FAIL]'.fail);
console.log();
return fn(false);
} else {
console.log(' check for test api', '[PASS]'.pass);
}
validateString(manifest.api.test.base_url, 'test base_url', pass);
validateString(manifest.api.test.sso_url, 'test sso_url', pass);
console.log();
fn(pass);
};
//
// POST invalid single sign on authentication data and check
// the result.
//
var sendInvalidSso = function(id, fn) {
var opts = {
uri: dia.manifest.api.test.sso_url
, method: 'POST'
, body: {
id: id
, timestamp: parseInt(Date.now() / 1000, 10)
, email: dia.manifest.id + '999' + '@example.com'
, token: 'invalid'
, 'nav-data': ''
}
, json: true
};
console.log('testing invalid single sign on authentication'.info);
request(opts, function(err, response) {
if (err) {
console.log(' check response code', '[FAIL]'.fail);
console.log(util.format(' error attempting to authenticate single sign on user: %s', err.message).fail);
console.log();
return fn ? fn() : void 0;
}
if (response.statusCode === 403) {
console.log(' check successful single sign on response', '[PASS]'.pass);
} else if (response.statusCode ) {
console.log(' check successful single sign on response', '[FAIL]'.fail);
console.log(util.format(' expected status code 403 but got %s', response.statusCode).fail);
console.log();
return fn ? fn() : void 0;
}
console.log();
fn();
});
};
//
// POST valid single sign on authentication data and check
// the result.
//
var sendValidSso = function(id) {
var timestamp = parseInt(Date.now() / 1000, 10)
, preToken = id + ':' + dia.manifest.api.sso_salt + ':' + timestamp
, token = crypto.createHash('sha1').update(preToken).digest('hex');
var opts = {
uri: dia.manifest.api.test.sso_url
, method: 'POST'
, body: {
id: id
, timestamp: timestamp
, email: dia.manifest.id + '999' + '@example.com'
, token: token
, 'nav-data': ''
}
, json: true
};
console.log('testing valid single sign on authentication'.info);
request(opts, function(err, response) {
if (err) {
console.log(' check response code', '[FAIL]'.fail);
console.log(util.format(' error attempting to authenticate single sign on user: %s', err.message).fail);
return console.log();
}
if (response.statusCode === 302) {
// Follow the redirect URL and verify that a 200 is returned.
var getUrl = response.headers.location;
if (getUrl.indexOf('http') < 0) {
getUrl = response.request.uri.protocol + '//' + response.request.uri.host + response.headers.location;
if (type === 'planchange') {
dia.id = options;
validators.planchange();
}
request.get(getUrl, function(err, response) {
if (err) {
console.log(' check successful single sign on response', '[FAIL]'.fail);
console.log(util.format(' unable to GET %s: %s', getUrl, err).fail);
return console.log();
}
if (response.statusCode !== 200) {
console.log(response.body);
console.log(' check successful single sign on response', '[FAIL]'.fail);
console.log(util.format(' expected status code 200 but got %s', response.statusCode).fail);
return console.log();
}
console.log(' check successful single sign on response', '[PASS]'.pass);
return console.log();
});
} else {
console.log(' check successful single sign on response', '[FAIL]'.fail);
console.log(util.format(' expected status code 302 but got %s', response.statusCode).fail);
return console.log();
if (type === 'deprovision') {
dia.id = options;
validators.deprovision();
}
if (type === 'sso') {
validators.sso(options);
}
}

@@ -261,10 +92,5 @@ });

//
// Configuration
// ===
//
//
// Set a configuration value
//
dia.setConfig = function(key, value) {
dia.setConfig = function (key, value) {
var data = userConfig.data || {};

@@ -289,3 +115,3 @@

//
dia.getConfig = function(key) {
dia.getConfig = function (key) {
if (userConfig.data && typeof userConfig.data[key] !== 'undefined') {

@@ -299,277 +125,5 @@ console.log('\n ', userConfig.data[key].info, '\n');

//
// Add-On test functions.
// ===
// Initialize a skeleton manifest to the specified filename/specifier.
//
//
// Begin an add-on test routine.
//
dia.test = function() {
var type, filename, options
, args = Array.prototype.slice.call(arguments);
type = args.shift();
filename = args.shift();
// Parse remaining arguments if present.
if (args.length > 0) {
options = args.shift();
}
if (args.length > 0) {
dia.plan = args.shift();
}
dia.validateManifest(filename, function(result) {
if (type === 'manifest' || !result || typeof dia.manifest.api.test === 'undefined') return;
if (type === 'all') {
dia.validatePost(function() {
dia.validatePut(function() {
dia.validateDelete(function() {
dia.validateSso(options || dia.id);
});
});
});
} else {
if (type === 'provision') {
dia.validatePost();
}
if (type === 'planchange') {
dia.id = options;
dia.validatePut();
}
if (type === 'deprovision') {
dia.id = options;
dia.validateDelete();
}
if (type === 'sso') {
dia.validateSso(options);
}
}
});
};
//
// Validates the manifest for this add-on.
//
dia.validateManifest = function(filename, fn) {
var manifest = filename || '';
if (manifest.length > 0) {
if (!fs.existsSync(manifest)) {
console.log(' specified manifest does not exist\n'.fail);
}
} else {
manifest = path.resolve('./', 'addon-manifest.json');
}
fs.readFile(manifest, { encoding: 'utf8' }, function(err, data) {
if (err || !data) {
console.log(util.format('\n failed to open the manifest at %s\n', manifest).fail);
return fn(false);
}
dia.manifest = JSON.parse(data);
validateManifestInternal(dia.manifest, fn);
});
};
//
// POST to the API endpoint specified in the manifest to simulate
// a provision call and validate the response.
//
dia.validatePost = function(fn) {
var opts, i;
console.log(util.format('testing POST to %s', dia.manifest.api.test.base_url).info);
opts = {
uri: dia.manifest.api.test.base_url
, method: 'POST'
, auth: {
user: dia.manifest.id
, pass: dia.manifest.api.password
}
, body: {
options: {}
, callback_url: 'http://localhost:8000/callback/999'
, modulus_id: dia.manifest.id + '999'
, email: dia.manifest.id + '999' + '@example.com'
, plan: dia.plan
, region: 'us-east-1'
}
, json: true
};
request(opts, function(err, response) {
if (err) {
console.log(' check response code', '[FAIL]'.fail);
console.log(util.format(' error attempting to provision: %s', err.message).fail);
console.log();
return fn ? fn() : void 0;
}
if (response.statusCode === 200) {
console.log(' check authentication', '[PASS]'.pass);
} else {
console.log(' check authentication', '[FAIL]'.fail);
console.log(util.format(' expected status code 200 but got %s', response.statusCode).fail);
console.log();
return fn ? fn() : void 0;
}
if (response.body) {
if (typeof response.body.id === 'undefined') {
console.log(' check response', '[FAIL]'.fail);
console.log(' id not found in response'.fail);
console.log();
return fn ? fn() : void 0;
}
dia.id = response.body.id;
if (!response.body.config) {
console.log(' check response', '[FAIL]'.fail);
console.log(' config vars not found in response'.fail);
console.log();
return fn ? fn() : void 0;
} else {
for (i = 0; i < dia.manifest.api.config_vars.length; i++) {
if (!response.body.config[dia.manifest.api.config_vars[i]]) {
console.log(' check response', '[FAIL]'.fail);
console.log(util.format(' config var %s not found in response', dia.manifest.api.config_vars[i]).fail);
console.log();
return fn ? fn() : void 0;
}
}
}
console.log(' check response', '[PASS]'.pass);
} else {
console.log(' check response', '[FAIL]'.fail);
console.log(' response body is empty'. fail);
}
console.log();
fn && fn();
});
};
//
// DELETE to the API endpoint to simulate a deprovision call
// and validate the response.
//
dia.validateDelete = function(fn) {
var opts = {
uri: dia.manifest.api.test.base_url + '/' + dia.id
, method: 'DELETE'
, auth: {
user: dia.manifest.id
, pass: dia.manifest.api.password
}
};
console.log(util.format('testing DELETE to %s/%s', dia.manifest.api.test.base_url, dia.id).info);
request(opts, function(err, response) {
if (err) {
console.log(' check response code', '[FAIL]'.fail);
console.log(util.format(' error attempting to deprovision: %s', err.message).fail);
console.log();
return fn ? fn() : void 0;
}
if (response.statusCode === 200) {
console.log(' check authentication', '[PASS]'.pass);
} else if (response.statusCode ) {
console.log(' check authentication', '[FAIL]'.fail);
console.log(util.format(' expected status code 200 but got %s', response.statusCode).fail);
console.log();
return fn ? fn() : void 0;
}
console.log(' check response', '[PASS]'.pass);
console.log();
fn && fn();
});
};
//
// PUT to the API endpoint to simulate a planchange call
// and validate the response.
//
dia.validatePut = function(fn) {
var opts = {
uri: dia.manifest.api.test.base_url + '/' + dia.id
, method: 'PUT'
, auth: {
user: dia.manifest.id
, pass: dia.manifest.api.password
}
, body: {
plan: dia.plan || 'foo'
, modulus_id: dia.manifest.id + '999'
}
, json: true
};
console.log(util.format('testing PUT to %s/%s', dia.manifest.api.test.base_url, dia.id).info);
request(opts, function(err, response) {
if (err) {
console.log(' check response code', '[FAIL]'.fail);
console.log(util.format(' error attempting to planchange: %s', err.message).fail);
console.log();
return fn ? fn() : void 0;
}
if (response.statusCode === 200) {
console.log(' check authentication', '[PASS]'.pass);
} else if (response.statusCode ) {
console.log(' check authentication', '[FAIL]'.fail);
console.log(util.format(' expected status code 200 but got %s', response.statusCode).fail);
console.log();
return fn ? fn() : void 0;
}
if (typeof response.body === 'undefined') {
console.log(' check response', '[FAIL]'.fail);
console.log(' config vars not found in response'.fail);
console.log();
return fn ? fn() : void 0;
} else {
if (typeof response.body.message === 'undefined') {
console.log(' check response', '[FAIL]'.fail);
console.log(' message not found in response'.fail);
console.log();
return fn ? fn() : void 0;
}
if (response.body.config) {
for (var i = 0; i < dia.manifest.api.config_vars.length; i++) {
if (!response.body.config[dia.manifest.api.config_vars[i]]) {
console.log(' check response', '[FAIL]'.fail);
console.log(util.format(' config var %s not found in response', dia.manifest.api.config_vars[i]).fail);
console.log();
return fn ? fn() : void 0;
}
}
}
}
console.log(' check response', '[PASS]'.pass);
console.log();
fn && fn();
});
};
//
// Simulate single sign on authentication and check the response.
//
dia.validateSso = function(id) {
sendInvalidSso(id, function() {
sendValidSso(id);
});
};
//
// Initialize a skeleton manifest to the specified filename.
//
dia.init = function(filename) {
dia.init = function (filename) {
var manifest = {

@@ -599,7 +153,7 @@ id: 'myaddon',

//
dia.authenticate = function(username, password, fn) {
librarian.user.authenticate(username, librarian.util.createHash(password), function(err, user) {
dia.authenticate = function (username, password, fn) {
librarian.user.authenticate(username, librarian.util.createHash(password), function (err, user) {
if (err) {
var token = null
, userData = new Buffer(util.format('%s:%s', username, password), 'ascii').toString('base64');
var token = null;
var userData = new Buffer(util.format('%s:%s', username, password), 'ascii').toString('base64');

@@ -615,3 +169,3 @@ var opts = {

request.get(opts, function(error, response, body) {
request.get(opts, function (error, response, body) {
if (!error && response.statusCode === 200) {

@@ -650,6 +204,12 @@ for (var i = 0; i < body.length; i++) {

//
dia.create = function(filename, user) {
if (!userConfig.data) return console.log('\n you must configured the API endpoint\n'.fail);
if (!user.flags.isProvider) return console.log('\n you must opt into the Modulus provider program\n'.fail);
if (!user.flags.isVerified) return console.log('\n you must be verified to create an add-on\n'.fail);
dia.create = function (filename, user) {
if (!userConfig.data) {
return console.log('\n you must configured the API endpoint\n'.fail);
}
if (!user.flags.isProvider) {
return console.log('\n you must opt into the Modulus provider program\n'.fail);
}
if (!user.flags.isVerified) {
return console.log('\n you must be verified to create an add-on\n'.fail);
}

@@ -664,3 +224,3 @@ if (filename.length > 0) {

fs.readFile(filename, { encoding: 'utf8' }, function(err, data) {
fs.readFile(filename, { encoding: 'utf8' }, function (err, data) {
if (err || !data) {

@@ -671,21 +231,19 @@ return console.log(util.format('\n failed to open the manifest at %s\n', filename).fail);

var manifest = JSON.parse(data);
validateManifestInternal(manifest, function(result) {
if (result) {
console.log('creating add-on'.info);
librarian.addOns.create(user.id, user.authToken, manifest, function(err, addon) {
if (err) return console.log('\n failed to create add-on'.fail);
if (addon.err) {
console.log('\n failed to create add-on'.fail);
if (addon.code === 11000) {
return console.log(util.format(' add-on \'%s\' already exists\n', manifest.id).fail);
}
return console.log(util.format(' error code: %s', addon.code).fail);
}
console.log('successfully created add-on.\n'.info);
});
} else {
console.log(' unable to create add-on because the specified manifest is invalid\n'.fail);
librarian.addOns.create(user.id, user.authToken, manifest, function (err, addon) {
if (err) {
return console.log('\n failed to create add-on'.fail);
}
if (addon.err) {
console.log('\n failed to create add-on'.fail);
if (addon.code === 11000) {
return console.log(util.format(' add-on \'%s\' already exists\n', manifest.id).fail);
}
return console.log(util.format(' error code: %s', addon.code).fail);
}
console.log('successfully created add-on.\n'.info);
});
});
};
{
"name": "dia",
"version": "0.1.2",
"version": "0.2.0",
"description": "Modulus add-on test utility.",

@@ -9,4 +9,4 @@ "scripts": {

"repository": {
"type": "GIT",
"url": "https://bitbucket.org/modulus/dia"
"type": "git",
"url": "https://github.com/onmodulus/dia.git"
},

@@ -13,0 +13,0 @@ "keywords": [

@@ -1,2 +0,2 @@

Dia
Dia [![Build Status](https://travis-ci.org/onmodulus/dia.svg?branch=master)](https://travis-ci.org/onmodulus/dia)
===

@@ -6,4 +6,2 @@

[![NPM](https://nodei.co/npm/dia.png?compact=true)](https://nodei.co/npm/dia/)
# Usage

@@ -10,0 +8,0 @@

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