Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1f08eaf
Added fixtures script to add users to DB
igznicolasjaremek Mar 17, 2015
49deffa
Merge branch 'cipher-users'
igznicolasjaremek Mar 17, 2015
e43a703
Merge branch 'master' of https://github.com/thegameofcode/cipherlayer
Mar 17, 2015
01f6def
Added env var for default password. Added default password for users.
igznicolasjaremek Mar 17, 2015
2fdd81e
added x-user-id header on directproxy request
Apr 8, 2015
9267a81
Merge remote-tracking branch 'upstream/master' into upstream-changes
Apr 21, 2015
50918ce
added verify old password functionality
Apr 21, 2015
1aca4bb
temporally skipped tests userAppVersion
Apr 21, 2015
9ca1c3e
Revert "Added middleware "userAppVersion" (update user info with his …
Apr 21, 2015
bbdcbf5
Merge branch 'master' of https://github.com/thegameofcode/cipherlayer
May 18, 2015
89a7a57
merged upstream master
Sep 9, 2015
fef9adf
fixed package and removed log
Sep 9, 2015
9fc9a9c
Added configuration parameter to define externalNotifications service…
igznicolasjaremek Sep 24, 2015
ca8d1ee
Updated tests for new configuration.
igznicolasjaremek Sep 24, 2015
ba61f47
Made JSON validator mandatory. Improved configuration file format.
igznicolasjaremek Sep 24, 2015
16cc102
Resetted hostnames for db and redis in config sample.
igznicolasjaremek Sep 30, 2015
7a3ad33
Merge pull request #1 from IGZgustavomarin/feature/improved-configura…
Sep 30, 2015
14cbf9f
add support to transfer a list of allowedHeaders in the configuration
Oct 13, 2015
f1e01d8
ADDED optional configuration to redirect to URL on email confirmation…
igznicolasjaremek Oct 14, 2015
ab4b620
Merge pull request #2 from IGZgustavomarin/feature/redirect-after-signup
Oct 14, 2015
971abde
Added from field to email endpoints.
igznicolasjaremek Oct 21, 2015
01bf244
Merge pull request #3 from IGZgustavomarin/feature/add-email-from-field
Oct 21, 2015
905fd4c
Fixed logout test.
igznicolasjaremek Oct 26, 2015
8f6061f
Readded an ignored Cucumber test with updated case.
igznicolasjaremek Oct 26, 2015
d8bb023
Readded passThrough Mocha tests.
igznicolasjaremek Oct 26, 2015
7a7d401
Added more cases to redis tests.
igznicolasjaremek Oct 27, 2015
1e1e2f0
Added test cases to Token manager.
igznicolasjaremek Oct 27, 2015
0a6722a
Added accessTokenParams middleware tests.
igznicolasjaremek Oct 27, 2015
a8d844e
Added authHeader middleware tests.
igznicolasjaremek Oct 27, 2015
35b6ffb
Added tests for decodeToken middleware.
igznicolasjaremek Oct 27, 2015
3c44b69
Added unit tests to permissions middleware.
igznicolasjaremek Oct 28, 2015
e5d9d54
Added unit tests to findUser middleware.
igznicolasjaremek Oct 28, 2015
9587e71
Added test cases to cover completely the pinValidation middleware.
igznicolasjaremek Oct 28, 2015
6ec86d9
Added unit tests for userAppVersion middleware.
igznicolasjaremek Oct 28, 2015
b6ae544
Added unit tests to prepareOptions middleware.
igznicolasjaremek Oct 28, 2015
8eb11f8
Added unit tests to platformsSetUp middleware.
igznicolasjaremek Oct 28, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions config_sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"accessToken" : {
"cipherKey" : "unsecureKey1",
"signKey" : "unsecureKey2",
"expiration" : 10
"expiration" : 1000
},
"refreshToken" : {
"cipherKey" : "unsecureKey3",
Expand Down Expand Up @@ -65,6 +65,12 @@
"avatars": "example-avatars"
}
},
"validators": {
"profile": {
"path": "",
"filename": "profile_create.json"
}
},
"phoneVerification": {
"pinSize": 4,
"attempts": 3,
Expand All @@ -83,43 +89,49 @@
}
]
},
"emailVerification":{
"emailVerification": {
"subject": "Example email verification",
"from": "hello@example.com",
"body": "<p>Thanks for register into Example, here is a link to activate your account click</p> <p><a href='{link}' >here</a></p> <p>If you have any problems on this process, please contact <a href='mailto:support@example.com'>support@example.com</a> and we will be pleased to help you.</p>",
"compatibleEmailDevices": [ "*iPhone*", "*iPad*", "*iPod*" , "*Android*"],
"nonCompatibleEmailMsg": "Your user has been created correctly, try to access to Example app in your device.",
"redis": {
"key":"user.{username}.transaction",
"expireInSec": 86400
},
"scheme":"mycomms"
"scheme":"mycomms",
"redirectUrl": "http://www.google.com"
},
"externalServices":{
"notifications": "http://localhost:3002"
"notifications": {
"base": "http://localhost:3002",
"pathEmail": "/api/notification/email"
}
},
"version" : {
"header" : "x-example-version",
"platforms" : {
"test" : {
"link" : "http://testLink",
"1" : true
}
},
},
"installPath" : "/install",
"db":"mongodb://localhost/versionControl?w=1"
}
},
"allowedDomains":[
"*@a.com"
],
"password":{
"validateOldPassword": false,
"regexValidation": "(?=.*\\d)(?=.*[A-Z])(?=.*[a-z]).{8}",
"message": "Your password must be at least 8 characters and must contain at least one capital, one lower and one number.",
"generatedRegex": "([a-z][\\d][A-Z]){3,4}",
"subject" :"Recover Example User Password",
"body" : "Here is your new password for accessing to your Example account, if you want, you can update it anytime from your edit profile screen. <p> __PASSWD__ <p> you can also click <a href='__LINK__' >here</a> from your mobile device to get in. If you receiver this email by error or you are sure you didn't requested it, please contact support@example.com"
},
"endpoints" : [
{
"endpoints" : [
{
"path" : "\/api\/profile",
"methods" : ["POST", "PUT"],
"roles" : ["admin"]
Expand All @@ -140,6 +152,9 @@
}
],
"directProxyUrls": [
"\/upload$"
"\/upload$"
],
"allowedHeaders": [
"x-custom-header"
]
}
3 changes: 1 addition & 2 deletions features/post_profile.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ Feature: client application POST a profile to create

#TODO: update to validate the domain with the first item of the allowedDomains in the config (if it exists)

@ignore
Scenario Outline: Client post data for a new profile
Given a protected service replies to a <METHOD> request with <PROTECTED_REQUEST_PAYLOAD> to <PATH> with status <STATUS> and a body <PROTECTED_PAYLOAD>
When the client makes a pass through <METHOD> with the following <PUBLIC_REQUEST_PAYLOAD> in the body
Expand All @@ -15,4 +14,4 @@ Feature: client application POST a profile to create

Examples:
| METHOD | PATH | STATUS | PROTECTED_REQUEST_PAYLOAD | PUBLIC_REQUEST_PAYLOAD | PROTECTED_PAYLOAD |
| POST | /api/profile | 201 | { "email" : "valid@vodafone.com" } | { "email":"valid@vodafone.com", "password":"i2E45678", "phone":"631014231", "country":"ES" } | { "id" : "a1b2c3d4" } |
| POST | /api/profile | 201 | { "email" : "valid@a.com" } | { "email":"valid@a.com", "password":"i2E45678", "phone":"631014231", "country":"ES" } | { "id" : "a1b2c3d4" } |
12 changes: 12 additions & 0 deletions features/proxy.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,15 @@ Feature: reverse proxy protects an applicacion behind cipherlayer
| PATH | METHOD | STATUS | REQUEST_PAYLOAD | RESPONSE_PAYLOAD |
| /test/get200 | GET | 200 | | {"m":"GET", "s":"200"} |
| /test/post200 | POST | 200 | {"key":"value"} | {"m":"POST", "s":"200"} |

@only
Scenario Outline: A protected service returns a response header
Given a user with role user and a valid access token
And a protected service replies to a <METHOD> request with <REQUEST_PAYLOAD> to <PATH> with status <STATUS> and a body <RESPONSE_PAYLOAD> and header <ALLOWED_HEADER> and value <HEADER_VALUE>
When the application makes a <METHOD> with <REQUEST_PAYLOAD> to a protected <PATH>
Then the response status code is <STATUS>
And the response body must be <RESPONSE_PAYLOAD>
And the response headers contains the <ALLOWED_HEADER> with <HEADER_VALUE>
Examples:
| PATH | METHOD | STATUS | REQUEST_PAYLOAD | RESPONSE_PAYLOAD | ALLOWED_HEADER | HEADER_VALUE |
| /test/get200 | GET | 200 | | {"m":"GET", "s":"200"} | x-custom-header | test |
2 changes: 1 addition & 1 deletion features/step_definitions/client_pass_through.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var config = require('../../config.json');
module.exports = function(){
this.When(/^the client makes a pass through (.*) with the following (.*) in the body$/, function (METHOD, PUBLIC_PAYLOAD, callback) {

var notifServiceURL = config.externalServices.notifications;
var notifServiceURL = config.externalServices.notifications.base;

var options = {
url: 'http://localhost:' + config.public_port + config.passThroughEndpoint.path,
Expand Down
4 changes: 3 additions & 1 deletion features/step_definitions/client_pass_through_pin.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ var myStepDefinitionsWrapper = function () {
.post(config.passThroughEndpoint.path)
.reply(201, {id: "a1b2c3d4e5f6"});

// This is required to skip the email verification step and avoid a hanging request targeted at the email verification endpoint
config.emailVerification = null;

request(options, function(err,res,body) {
assert.equal(err,null);
world.getResponse().statusCode = res.statusCode;
Expand All @@ -34,7 +37,6 @@ var myStepDefinitionsWrapper = function () {
});
});


});
};
module.exports = myStepDefinitionsWrapper;
9 changes: 6 additions & 3 deletions features/step_definitions/method_request_to_path.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ var nock = require('nock');
var request = require('request');
var assert = require('assert');

var NOTIFICATION_SERVICE_URL = config.externalServices.notifications.base;
var NOTIFICATION_EMAIL_SERVICE_PATH = config.externalServices.notifications.pathEmail;

var myStepDefinitionsWrapper = function () {
this.When(/^the client makes a (.*) request to (.*)$/, function (METHOD, PATH, callback) {

Expand All @@ -18,12 +21,12 @@ var myStepDefinitionsWrapper = function () {
};
options.headers[config.version.header] = "test/1";

nock(config.externalServices.notifications)
.post('/notification/email')
nock(NOTIFICATION_SERVICE_URL)
.post(NOTIFICATION_EMAIL_SERVICE_PATH)
.reply(204);

request(options, function(err,res) {
assert.equal(err,null);
assert.equal(err,null);
world.getResponse().statusCode = res.statusCode;
callback();
});
Expand Down
2 changes: 2 additions & 0 deletions features/step_definitions/protected_service_call.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ module.exports = function(){
} else {
world.getResponse().body = null;
}

world.getResponse().headers = res.headers;
callback();
});
});
Expand Down
15 changes: 14 additions & 1 deletion features/step_definitions/protected_service_definiton.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,24 @@ module.exports = function(){
callback();
});

this.Given(/^a protected service replies to a GET request with (.*) to (.*) with status (.*) and a body (.*) and header (.*) and value (.*)$/, function (REQUEST_PAYLOAD, PATH, STATUS, RESPONSE_PAYLOAD, ALLOWED_HEADER, HEADER_VALUE, callback){
var headers = {};
headers[ALLOWED_HEADER] = HEADER_VALUE;
nock('http://localhost:'+config.private_port, {
reqheaders: {
'Content-Type': 'application/json; charset=utf-8',
'x-user-id' : world.getUser().id
}
}).get(PATH).reply(Number(STATUS), JSON.parse(RESPONSE_PAYLOAD), headers);

callback();
});

this.Given(/^a protected service replies to a POST request with (.*) to (.*) with status (.*) and a body (.*)$/, function (REQUEST_PAYLOAD, PATH, STATUS, RESPONSE_PAYLOAD, callback){
nock('http://localhost:'+config.private_port)
.post(PATH, JSON.parse(REQUEST_PAYLOAD))
.reply(Number(STATUS), JSON.parse(RESPONSE_PAYLOAD));

callback();
});

Expand Down
9 changes: 9 additions & 0 deletions features/step_definitions/response_header_content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var world = require('../support/world');
var assert = require('assert');

module.exports = function(){
this.Given(/^the response headers contains the (.*) with (.*)$/, function (ALLOWEDHEADER, HEADERVALUE, callback) {
assert.equal(world.getResponse().headers[ALLOWEDHEADER], HEADERVALUE);
callback();
});
};
98 changes: 98 additions & 0 deletions scripts/add_users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
var async = require('async'),
fs = require('fs'),
nock = require('nock'),
userMng = require('../src/managers/user'),
config = require('../config.json'),
userDao = require('../src/managers/dao.js');
/*
* Objects for `async.eachSeries`
*/

// Function to apply to each fixture
var addFixture = function(fixture, callback) {

var data = fixture;

// Define user object to be passed to userMng
var pin = null;
var profileBody = {
id: data._id.$oid || data._id,
email: data.email,
password: data.password || (process.env.DEFAULT_PASS ? process.env.DEFAULT_PASS : "qwerty")
};

if(!profileBody.id || !profileBody.email || !profileBody.password) {
console.log("Missing mandatory parameter(s)");
return callback();
}
// Nock the createUser URL
nock('http://' + config.private_host + ':' + config.private_port + config.passThroughEndpoint.path, { reqheaders: {
'Content-Type': 'application/json; charset=utf-8'
}})
.post(config.passThroughEndpoint.path)
.reply(201,profileBody);

// Save user data to database
userMng().createUser(profileBody, pin, function(err) {
if(err) {

if (err.err === 'auth_proxy_user_error') {
console.log(profileBody.email + " " + err.des);
return callback();
}
return callback(err);
}
console.log(profileBody.email + " added");
return callback();
});

};

/*
* Main part of the script:
* - Exports the function, or
* - Executes the function if running from CLI
*/
var runLoadFixtures = module.exports = function(fixtureFile, callback) {

console.log("running Load Fixtures");


async.eachSeries(fixtureFile, addFixture, callback);

};

if (!module.parent) { // Run as CLI command exec
async.series([

// Start cipherLayer components (mongodb, redis...)
function connect(done) {
userDao.connect(done);
},

function drop(done) {
if(!process.env.DROP_DB) return done();
console.log("Dropping database");
userDao.deleteAllUsers(done);
},

function load(done) {
fixtureFile = require(__dirname + '/' + '../tests/fixtures/' + 'User.json');
runLoadFixtures(fixtureFile,done);
},

function disconnect(done) {
userDao.disconnect(done);
}

], function(err) {
if (err) {
console.error(err);
process.exit(1);
}

console.info('Fixtures loaded');
process.exit();
});

}
10 changes: 5 additions & 5 deletions src/managers/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ var redisMng = require('./redis');
var _settings = {};

function sendEmailVerification(email, subject, emailBody, cbk){
var notifServiceURL = _settings.externalServices.notifications;
var notifServiceURL = _settings.externalServices.notifications.base;
var emailOptions = {
to: email,
subject: subject,
html: emailBody
html: emailBody,
from: _settings.emailVerification.from
};

var options = {
url: notifServiceURL + '/notification/email',
url: notifServiceURL + _settings.externalServices.notifications.pathEmail,
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
Expand Down Expand Up @@ -72,7 +73,6 @@ function emailVerification(email, bodyData, cbk){
var emailText = (_settings.emailVerification.body).replace('{link}', link);

var subject = _settings.emailVerification.subject;

//Send verify email
sendEmailVerification(email, subject, emailText, function(err){
if (err) {
Expand All @@ -96,7 +96,7 @@ function sendEmailForgotPassword(email, passwd, link, cbk){
};

var options = {
url: _settings.externalServices.notifications + '/notification/email',
url: _settings.externalServices.notifications.base + _settings.externalServices.notifications.pathEmail ,
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
Expand Down
20 changes: 20 additions & 0 deletions src/managers/json_formats/profile_downloader.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"id": "/Profile",
"type": "object",
"properties": {
"password": {
"type": "string",
"required": true
},
"email": {
"type": "string",
"format": "email",
"required": true
},
"name": {
"type": "string",
"required": true
}
},
"additionalProperties": true
}
8 changes: 5 additions & 3 deletions src/managers/json_validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ module.exports = {
if( !json || Object.keys(json).length === 0) {
return false;
}
if(schema) {

if (!schema) {
return true;
}
var result = (new Validator()).validate(json, schema);
if (result.errors.length > 0) {
return false;
}
}
return true;
return true;
}
};
Loading