Move exceptions to typescript

This commit is contained in:
Clement Michaud 2017-05-20 22:55:37 +02:00
parent ba80bbd219
commit bada70cf64
27 changed files with 328 additions and 315 deletions

View File

@ -1,7 +1,6 @@
import * as Promise from "bluebird"; import * as Promise from "bluebird";
import exceptions = require("./Exceptions");
const exceptions = require("./exceptions");
const REGULATION_TRACE_TYPE = "regulation"; const REGULATION_TRACE_TYPE = "regulation";
const MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE = 3; const MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE = 3;

49
src/lib/Exceptions.ts Normal file
View File

@ -0,0 +1,49 @@
export class LdapSeachError extends Error {
constructor(message?: string) {
super(message);
this.name = "LdapSeachError";
Object.setPrototypeOf(this, LdapSeachError.prototype);
}
}
export class LdapBindError extends Error {
constructor(message?: string) {
super(message);
this.name = "LdapBindError";
Object.setPrototypeOf(this, LdapBindError.prototype);
}
}
export class IdentityError extends Error {
constructor(message?: string) {
super(message);
this.name = "IdentityError";
Object.setPrototypeOf(this, IdentityError.prototype);
}
}
export class AccessDeniedError extends Error {
constructor(message?: string) {
super(message);
this.name = "AccessDeniedError";
Object.setPrototypeOf(this, AccessDeniedError.prototype);
}
}
export class AuthenticationRegulationError extends Error {
constructor(message?: string) {
super(message);
this.name = "AuthenticationRegulationError";
Object.setPrototypeOf(this, AuthenticationRegulationError.prototype);
}
}
export class InvalidTOTPError extends Error {
constructor(message?: string) {
super(message);
this.name = "InvalidTOTPError";
Object.setPrototypeOf(this, InvalidTOTPError.prototype);
}
}

View File

@ -57,7 +57,7 @@ export default class Server {
const five_minutes = 5 * 60; const five_minutes = 5 * 60;
const data_store = new UserDataStore(datastore_options); const data_store = new UserDataStore(datastore_options);
const regulator = new AuthenticationRegulator(data_store, five_minutes); const regulator = new AuthenticationRegulator(data_store, five_minutes);
const notifier = NotifierFactory.build(config.notifier, deps); const notifier = NotifierFactory.build(config.notifier, deps.nodemailer);
const ldap = new Ldap(deps, config.ldap); const ldap = new Ldap(deps, config.ldap);
const accessController = new AccessController(config.access_control, deps.winston); const accessController = new AccessController(config.access_control, deps.winston);
const totpValidator = new TOTPValidator(deps.speakeasy); const totpValidator = new TOTPValidator(deps.speakeasy);

View File

@ -1,45 +0,0 @@
module.exports = {
LdapSearchError: LdapSearchError,
LdapBindError: LdapBindError,
IdentityError: IdentityError,
AccessDeniedError: AccessDeniedError,
AuthenticationRegulationError: AuthenticationRegulationError,
InvalidTOTPError: InvalidTOTPError,
}
function LdapSearchError(message) {
this.name = "LdapSearchError";
this.message = (message || "");
}
LdapSearchError.prototype = Object.create(Error.prototype);
function LdapBindError(message) {
this.name = "LdapBindError";
this.message = (message || "");
}
LdapBindError.prototype = Object.create(Error.prototype);
function IdentityError(message) {
this.name = "IdentityError";
this.message = (message || "");
}
IdentityError.prototype = Object.create(Error.prototype);
function AccessDeniedError(message) {
this.name = "AccessDeniedError";
this.message = (message || "");
}
AccessDeniedError.prototype = Object.create(Error.prototype);
function AuthenticationRegulationError(message) {
this.name = "AuthenticationRegulationError";
this.message = (message || "");
}
AuthenticationRegulationError.prototype = Object.create(Error.prototype);
function InvalidTOTPError(message) {
this.name = "InvalidTOTPError";
this.message = (message || "");
}
InvalidTOTPError.prototype = Object.create(Error.prototype);

View File

@ -3,7 +3,7 @@ var objectPath = require('object-path');
var randomstring = require('randomstring'); var randomstring = require('randomstring');
var Promise = require('bluebird'); var Promise = require('bluebird');
var util = require('util'); var util = require('util');
var exceptions = require('./exceptions'); var exceptions = require('./Exceptions');
var fs = require('fs'); var fs = require('fs');
var ejs = require('ejs'); var ejs = require('ejs');

View File

@ -3,7 +3,7 @@ module.exports = Ldap;
var util = require('util'); var util = require('util');
var Promise = require('bluebird'); var Promise = require('bluebird');
var exceptions = require('./exceptions'); var exceptions = require('./Exceptions');
var Dovehash = require('dovehash'); var Dovehash = require('dovehash');
function Ldap(deps, ldap_config) { function Ldap(deps, ldap_config) {
@ -70,7 +70,7 @@ Ldap.prototype._search_in_ldap = function(base, query) {
}); });
}) })
.catch(function(err) { .catch(function(err) {
reject(new exceptions.LdapSearchError(err)); reject(err);
}); });
}); });
} }

View File

@ -3,7 +3,7 @@ import * as BluebirdPromise from "bluebird";
import * as util from "util"; import * as util from "util";
import * as fs from "fs"; import * as fs from "fs";
import { INotifier } from "./INotifier"; import { INotifier } from "./INotifier";
import { Identity } from "../Identity"; import { Identity } from "../../types/Identity";
import { FileSystemNotifierConfiguration } from "../Configuration"; import { FileSystemNotifierConfiguration } from "../Configuration";

View File

@ -4,8 +4,8 @@ import * as fs from "fs";
import * as ejs from "ejs"; import * as ejs from "ejs";
import nodemailer = require("nodemailer"); import nodemailer = require("nodemailer");
import { NodemailerDependencies } from "../../types/Dependencies"; import { Nodemailer } from "../../types/Dependencies";
import { Identity } from "../Identity"; import { Identity } from "../../types/Identity";
import { INotifier } from "../notifiers/INotifier"; import { INotifier } from "../notifiers/INotifier";
import { GmailNotifierConfiguration } from "../Configuration"; import { GmailNotifierConfiguration } from "../Configuration";
@ -14,9 +14,9 @@ const email_template = fs.readFileSync(__dirname + "/../../resources/email-templ
export class GMailNotifier extends INotifier { export class GMailNotifier extends INotifier {
private transporter: any; private transporter: any;
constructor(options: GmailNotifierConfiguration, deps: NodemailerDependencies) { constructor(options: GmailNotifierConfiguration, nodemailer: Nodemailer) {
super(); super();
const transporter = deps.createTransport({ const transporter = nodemailer.createTransport({
service: "gmail", service: "gmail",
auth: { auth: {
user: options.username, user: options.username,

View File

@ -1,6 +1,6 @@
import * as BluebirdPromise from "bluebird"; import * as BluebirdPromise from "bluebird";
import { Identity } from "../Identity"; import { Identity } from "../../types/Identity";
export abstract class INotifier { export abstract class INotifier {
abstract notify(identity: Identity, subject: string, link: string): BluebirdPromise<void>; abstract notify(identity: Identity, subject: string, link: string): BluebirdPromise<void>;

View File

@ -1,15 +1,15 @@
import { NotifierConfiguration } from "..//Configuration"; import { NotifierConfiguration } from "..//Configuration";
import { NotifierDependencies } from "../../types/Dependencies"; import { Nodemailer } from "../../types/Dependencies";
import { INotifier } from "./INotifier"; import { INotifier } from "./INotifier";
import { GMailNotifier } from "./GMailNotifier"; import { GMailNotifier } from "./GMailNotifier";
import { FileSystemNotifier } from "./FileSystemNotifier"; import { FileSystemNotifier } from "./FileSystemNotifier";
export class NotifierFactory { export class NotifierFactory {
static build(options: NotifierConfiguration, deps: NotifierDependencies): INotifier { static build(options: NotifierConfiguration, nodemailer: Nodemailer): INotifier {
if ("gmail" in options) { if ("gmail" in options) {
return new GMailNotifier(options.gmail, deps.nodemailer); return new GMailNotifier(options.gmail, nodemailer);
} }
else if ("filesystem" in options) { else if ("filesystem" in options) {
return new FileSystemNotifier(options.filesystem); return new FileSystemNotifier(options.filesystem);

View File

@ -1,5 +1,5 @@
var first_factor = require('./routes/first_factor'); var first_factor = require('./routes/FirstFactor');
var second_factor = require('./routes/second_factor'); var second_factor = require('./routes/second_factor');
var reset_password = require('./routes/reset_password'); var reset_password = require('./routes/reset_password');
var verify = require('./routes/verify'); var verify = require('./routes/verify');

View File

@ -0,0 +1,76 @@
import exceptions = require("../Exceptions");
import objectPath = require("object-path");
import Promise = require("bluebird");
import express = require("express");
export = function(req: express.Request, res: express.Response) {
const username = req.body.username;
const password = req.body.password;
if (!username || !password) {
res.status(401);
res.send();
return;
}
const logger = req.app.get("logger");
const ldap = req.app.get("ldap");
const config = req.app.get("config");
const regulator = req.app.get("authentication regulator");
const accessController = req.app.get("access controller");
logger.info("1st factor: Starting authentication of user \"%s\"", username);
logger.debug("1st factor: Start bind operation against LDAP");
logger.debug("1st factor: username=%s", username);
regulator.regulate(username)
.then(function() {
return ldap.bind(username, password);
})
.then(function() {
objectPath.set(req, "session.auth_session.userid", username);
objectPath.set(req, "session.auth_session.first_factor", true);
logger.info("1st factor: LDAP binding successful");
logger.debug("1st factor: Retrieve email from LDAP");
return Promise.join(ldap.get_emails(username), ldap.get_groups(username));
})
.then(function(data: string[2]) {
const emails = data[0];
const groups = data[1];
if (!emails && emails.length <= 0) throw new Error("No email found");
logger.debug("1st factor: Retrieved email are %s", emails);
objectPath.set(req, "session.auth_session.email", emails[0]);
const isAllowed = accessController.isDomainAllowedForUser(username, groups);
if (!isAllowed) throw new Error("User not allowed to visit this domain");
regulator.mark(username, true);
res.status(204);
res.send();
})
.catch(exceptions.LdapSeachError, function(err: Error) {
logger.error("1st factor: Unable to retrieve email from LDAP", err);
res.status(500);
res.send();
})
.catch(exceptions.LdapBindError, function(err: Error) {
logger.error("1st factor: LDAP binding failed");
logger.debug("1st factor: LDAP binding failed due to ", err);
regulator.mark(username, false);
res.status(401);
res.send("Bad credentials");
})
.catch(exceptions.AuthenticationRegulationError, function(err: Error) {
logger.error("1st factor: the regulator rejected the authentication of user %s", username);
logger.debug("1st factor: authentication rejected due to %s", err);
res.status(403);
res.send("Access has been restricted for a few minutes...");
})
.catch(function(err: Error) {
console.log(err.stack);
logger.error("1st factor: Unhandled error %s", err);
res.status(500);
res.send("Internal error");
});
};

View File

@ -1,95 +0,0 @@
module.exports = first_factor;
var exceptions = require('../exceptions');
var objectPath = require('object-path');
var Promise = require('bluebird');
function get_allowed_domains(access_control, username, groups) {
var allowed_domains = [];
for(var i = 0; i<access_control.length; ++i) {
var rule = access_control[i];
if('allowed_domains' in rule) {
if('group' in rule && groups.indexOf(rule['group']) >= 0) {
var domains = rule.allowed_domains;
allowed_domains = allowed_domains.concat(domains);
}
else if('user' in rule && username == rule['user']) {
var domains = rule.allowed_domains;
allowed_domains = allowed_domains.concat(domains);
}
}
}
return allowed_domains;
}
function first_factor(req, res) {
var username = req.body.username;
var password = req.body.password;
if(!username || !password) {
res.status(401);
res.send();
return;
}
var logger = req.app.get('logger');
var ldap = req.app.get('ldap');
var config = req.app.get('config');
var regulator = req.app.get('authentication regulator');
var accessController = req.app.get('access controller');
logger.info('1st factor: Starting authentication of user "%s"', username);
logger.debug('1st factor: Start bind operation against LDAP');
logger.debug('1st factor: username=%s', username);
regulator.regulate(username)
.then(function() {
return ldap.bind(username, password);
})
.then(function() {
objectPath.set(req, 'session.auth_session.userid', username);
objectPath.set(req, 'session.auth_session.first_factor', true);
logger.info('1st factor: LDAP binding successful');
logger.debug('1st factor: Retrieve email from LDAP');
return Promise.join(ldap.get_emails(username), ldap.get_groups(username));
})
.then(function(data) {
var emails = data[0];
var groups = data[1];
var allowed_domains;
if(!emails && emails.length <= 0) throw new Error('No email found');
logger.debug('1st factor: Retrieved email are %s', emails);
objectPath.set(req, 'session.auth_session.email', emails[0]);
allowed_domains = accessController.isDomainAllowedForUser(username, groups);
regulator.mark(username, true);
res.status(204);
res.send();
})
.catch(exceptions.LdapSearchError, function(err) {
logger.error('1st factor: Unable to retrieve email from LDAP', err);
res.status(500);
res.send();
})
.catch(exceptions.LdapBindError, function(err) {
logger.error('1st factor: LDAP binding failed');
logger.debug('1st factor: LDAP binding failed due to ', err);
regulator.mark(username, false);
res.status(401);
res.send('Bad credentials');
})
.catch(exceptions.AuthenticationRegulationError, function(err) {
logger.error('1st factor: the regulator rejected the authentication of user %s', username);
logger.debug('1st factor: authentication rejected due to %s', err);
res.status(403);
res.send('Access has been restricted for a few minutes...');
})
.catch(function(err) {
logger.error('1st factor: Unhandled error %s', err);
res.status(500);
res.send('Internal error');
});
}

View File

@ -1,7 +1,7 @@
var Promise = require('bluebird'); var Promise = require('bluebird');
var objectPath = require('object-path'); var objectPath = require('object-path');
var exceptions = require('../exceptions'); var exceptions = require('../Exceptions');
var CHALLENGE = 'reset-password'; var CHALLENGE = 'reset-password';
var icheck_interface = { var icheck_interface = {

View File

@ -2,7 +2,7 @@
module.exports = totp_fn; module.exports = totp_fn;
var objectPath = require('object-path'); var objectPath = require('object-path');
var exceptions = require('../../../src/lib/exceptions'); var exceptions = require('../../../src/lib/Exceptions');
var UNAUTHORIZED_MESSAGE = 'Unauthorized access'; var UNAUTHORIZED_MESSAGE = 'Unauthorized access';

View File

@ -1,8 +1,9 @@
import * as winston from "winston"; import winston = require("winston");
import * as speakeasy from "speakeasy"; import speakeasy = require("speakeasy");
import nodemailer = require("nodemailer"); import nodemailer = require("nodemailer");
import session = require("express-session"); import session = require("express-session");
import nedb = require("nedb"); import nedb = require("nedb");
import ldapjs = require("ldapjs");
export type Nodemailer = typeof nodemailer; export type Nodemailer = typeof nodemailer;
export type Speakeasy = typeof speakeasy; export type Speakeasy = typeof speakeasy;
@ -18,10 +19,4 @@ export interface GlobalDependencies {
winston: Winston; winston: Winston;
speakeasy: Speakeasy; speakeasy: Speakeasy;
nedb: Nedb; nedb: Nedb;
}
export type NodemailerDependencies = Nodemailer;
export interface NotifierDependencies {
nodemailer: Nodemailer;
} }

View File

@ -1,9 +1,8 @@
import AuthenticationRegulator from "../../src/lib/AuthenticationRegulator"; import AuthenticationRegulator from "../../src/lib/AuthenticationRegulator";
import UserDataStore from "../../src/lib/UserDataStore"; import UserDataStore from "../../src/lib/UserDataStore";
import * as MockDate from "mockdate"; import MockDate = require("mockdate");
import exceptions = require("../../src/lib/Exceptions");
const exceptions = require("../../src/lib/exceptions");
describe("test authentication regulator", function() { describe("test authentication regulator", function() {
it("should mark 2 authentication and regulate (resolve)", function() { it("should mark 2 authentication and regulate (resolve)", function() {

View File

@ -0,0 +1,8 @@
import sinon = require("sinon");
export = function () {
return {
isDomainAllowedForUser: sinon.stub()
};
};

View File

@ -0,0 +1,9 @@
import sinon = require("sinon");
export = function () {
return {
mark: sinon.stub(),
regulate: sinon.stub()
};
};

View File

@ -0,0 +1,10 @@
import sinon = require("sinon");
export = function () {
return {
bind: sinon.stub(),
get_emails: sinon.stub(),
get_groups: sinon.stub()
};
};

View File

@ -0,0 +1,11 @@
import sinon = require("sinon");
export = {
Response: function () {
return {
send: sinon.stub(),
status: sinon.stub()
};
}
};

View File

@ -9,14 +9,10 @@ import { NotifierFactory } from "../../../src/lib/notifiers/NotifierFactory";
import { GMailNotifier } from "../../../src/lib/notifiers/GMailNotifier"; import { GMailNotifier } from "../../../src/lib/notifiers/GMailNotifier";
import { FileSystemNotifier } from "../../../src/lib/notifiers/FileSystemNotifier"; import { FileSystemNotifier } from "../../../src/lib/notifiers/FileSystemNotifier";
import { NotifierDependencies } from "../../../src/types/Dependencies"; import nodemailerMock = require("../mocks/nodemailer");
describe("test notifier", function() { describe("test notifier factory", function() {
const deps: NotifierDependencies = {
nodemailer: NodemailerMock
};
it("should build a Gmail Notifier", function() { it("should build a Gmail Notifier", function() {
const options = { const options = {
gmail: { gmail: {
@ -24,7 +20,8 @@ describe("test notifier", function() {
password: "password" password: "password"
} }
}; };
assert(NotifierFactory.build(options, deps) instanceof GMailNotifier); nodemailerMock.createTransport.returns(sinon.spy());
assert(NotifierFactory.build(options, nodemailerMock) instanceof GMailNotifier);
}); });
it("should build a FS Notifier", function() { it("should build a FS Notifier", function() {
@ -34,6 +31,6 @@ describe("test notifier", function() {
} }
}; };
assert(NotifierFactory.build(options, deps) instanceof FileSystemNotifier); assert(NotifierFactory.build(options, nodemailerMock) instanceof FileSystemNotifier);
}); });
}); });

View File

@ -0,0 +1,136 @@
import sinon = require("sinon");
import BluebirdPromise = require("bluebird");
import assert = require("assert");
import winston = require("winston");
import FirstFactor = require("../../../src/lib/routes/FirstFactor");
import exceptions = require("../../../src/lib/Exceptions");
import AuthenticationRegulatorMock = require("../mocks/AuthenticationRegulator");
import AccessControllerMock = require("../mocks/AccessController");
import LdapMock = require("../mocks/Ldap");
import ExpressMock = require("../mocks/express");
describe("test the first factor validation route", function() {
let req: any;
let res: any;
let emails: string[];
let groups: string[];
let configuration;
let ldapMock: any;
let regulator: any;
let accessController: any;
beforeEach(function() {
configuration = {
ldap: {
base_dn: "ou=users,dc=example,dc=com",
user_name_attribute: "uid"
}
};
emails = [ "test_ok@example.com" ];
groups = [ "group1", "group2" ];
ldapMock = LdapMock();
accessController = AccessControllerMock();
accessController.isDomainAllowedForUser.returns(true);
regulator = AuthenticationRegulatorMock();
regulator.regulate.returns(BluebirdPromise.resolve());
regulator.mark.returns(BluebirdPromise.resolve());
const app_get = sinon.stub();
app_get.withArgs("ldap").returns(ldapMock);
app_get.withArgs("configuration").returns(configuration);
app_get.withArgs("logger").returns(winston);
app_get.withArgs("authentication regulator").returns(regulator);
app_get.withArgs("access controller").returns(accessController);
req = {
app: {
get: app_get
},
body: {
username: "username",
password: "password"
},
session: {
auth_session: {
FirstFactor: false,
second_factor: false
}
}
};
res = ExpressMock.Response();
});
it("should return status code 204 when LDAP binding succeeds", function() {
return new Promise(function(resolve, reject) {
res.send = sinon.spy(function() {
assert.equal("username", req.session.auth_session.userid);
assert.equal(204, res.status.getCall(0).args[0]);
resolve();
});
ldapMock.bind.withArgs("username").returns(BluebirdPromise.resolve());
ldapMock.get_emails.returns(BluebirdPromise.resolve(emails));
FirstFactor(req, res);
});
});
it("should retrieve email from LDAP", function(done) {
res.send = sinon.spy(function() { done(); });
ldapMock.bind.returns(BluebirdPromise.resolve());
ldapMock.get_emails = sinon.stub().withArgs("usernam").returns(BluebirdPromise.resolve([{mail: ["test@example.com"] }]));
FirstFactor(req, res);
});
it("should set email as session variables", function() {
return new Promise(function(resolve, reject) {
res.send = sinon.spy(function() {
assert.equal("test_ok@example.com", req.session.auth_session.email);
resolve();
});
const emails = [ "test_ok@example.com" ];
ldapMock.bind.returns(BluebirdPromise.resolve());
ldapMock.get_emails.returns(BluebirdPromise.resolve(emails));
FirstFactor(req, res);
});
});
it("should return status code 401 when LDAP binding throws", function(done) {
res.send = sinon.spy(function() {
assert.equal(401, res.status.getCall(0).args[0]);
assert.equal(regulator.mark.getCall(0).args[0], "username");
done();
});
ldapMock.bind.throws(new exceptions.LdapBindError("Bad credentials"));
FirstFactor(req, res);
});
it("should return status code 500 when LDAP search throws", function(done) {
res.send = sinon.spy(function() {
assert.equal(500, res.status.getCall(0).args[0]);
done();
});
ldapMock.bind.returns(BluebirdPromise.resolve());
ldapMock.get_emails.throws(new exceptions.LdapSeachError("error while retrieving emails"));
FirstFactor(req, res);
});
it("should return status code 403 when regulator rejects authentication", function(done) {
const err = new exceptions.AuthenticationRegulationError("Authentication regulation...");
regulator.regulate.returns(BluebirdPromise.reject(err));
res.send = sinon.spy(function() {
assert.equal(403, res.status.getCall(0).args[0]);
done();
});
ldapMock.bind.returns(BluebirdPromise.resolve());
ldapMock.get_emails.returns(BluebirdPromise.resolve());
FirstFactor(req, res);
});
});

View File

@ -1,136 +0,0 @@
var sinon = require('sinon');
var Promise = require('bluebird');
var assert = require('assert');
var winston = require('winston');
var first_factor = require('../../../src/lib/routes/first_factor');
var exceptions = require('../../../src/lib/exceptions');
var Ldap = require('../../../src/lib/ldap');
describe('test the first factor validation route', function() {
var req, res;
var ldap_interface_mock;
var emails;
var search_res_ok;
var regulator;
var access_controller;
var config;
beforeEach(function() {
ldap_interface_mock = sinon.createStubInstance(Ldap);
config = {
ldap: {
base_dn: 'ou=users,dc=example,dc=com',
user_name_attribute: 'uid'
}
}
emails = [ 'test_ok@example.com' ];
groups = [ 'group1', 'group2' ];
regulator = {};
regulator.mark = sinon.stub();
regulator.regulate = sinon.stub();
regulator.mark.returns(Promise.resolve());
regulator.regulate.returns(Promise.resolve());
access_controller = {
isDomainAllowedForUser: sinon.stub().returns(true)
};
var app_get = sinon.stub();
app_get.withArgs('ldap').returns(ldap_interface_mock);
app_get.withArgs('config').returns(config);
app_get.withArgs('logger').returns(winston);
app_get.withArgs('authentication regulator').returns(regulator);
app_get.withArgs('access controller').returns(access_controller);
req = {
app: {
get: app_get
},
body: {
username: 'username',
password: 'password'
},
session: {
auth_session: {
first_factor: false,
second_factor: false
}
}
}
res = {
send: sinon.spy(),
status: sinon.spy()
}
});
it('should return status code 204 when LDAP binding succeeds', function() {
return new Promise(function(resolve, reject) {
res.send = sinon.spy(function(data) {
assert.equal('username', req.session.auth_session.userid);
assert.equal(204, res.status.getCall(0).args[0]);
resolve();
});
ldap_interface_mock.bind.withArgs('username').returns(Promise.resolve());
ldap_interface_mock.get_emails.returns(Promise.resolve(emails));
first_factor(req, res);
});
});
it('should retrieve email from LDAP', function(done) {
res.send = sinon.spy(function(data) { done(); });
ldap_interface_mock.bind.returns(Promise.resolve());
ldap_interface_mock.get_emails = sinon.stub().withArgs('usernam').returns(Promise.resolve([{mail: ['test@example.com'] }]));
first_factor(req, res);
});
it('should set email as session variables', function() {
return new Promise(function(resolve, reject) {
res.send = sinon.spy(function(data) {
assert.equal('test_ok@example.com', req.session.auth_session.email);
resolve();
});
var emails = [ 'test_ok@example.com' ];
ldap_interface_mock.bind.returns(Promise.resolve());
ldap_interface_mock.get_emails.returns(Promise.resolve(emails));
first_factor(req, res);
});
});
it('should return status code 401 when LDAP binding throws', function(done) {
res.send = sinon.spy(function(data) {
assert.equal(401, res.status.getCall(0).args[0]);
assert.equal(regulator.mark.getCall(0).args[0], 'username');
done();
});
ldap_interface_mock.bind.throws(new exceptions.LdapBindError('Bad credentials'));
first_factor(req, res);
});
it('should return status code 500 when LDAP search throws', function(done) {
res.send = sinon.spy(function(data) {
assert.equal(500, res.status.getCall(0).args[0]);
done();
});
ldap_interface_mock.bind.returns(Promise.resolve());
ldap_interface_mock.get_emails.throws(new exceptions.LdapSearchError('err'));
first_factor(req, res);
});
it('should return status code 403 when regulator rejects authentication', function(done) {
var err = new exceptions.AuthenticationRegulationError();
regulator.regulate.returns(Promise.reject(err));
res.send = sinon.spy(function(data) {
assert.equal(403, res.status.getCall(0).args[0]);
done();
});
ldap_interface_mock.bind.returns(Promise.resolve());
ldap_interface_mock.get_emails.returns(Promise.resolve());
first_factor(req, res);
});
});

View File

@ -1,7 +1,7 @@
var sinon = require('sinon'); var sinon = require('sinon');
var identity_check = require('../../src/lib/identity_check'); var identity_check = require('../../src/lib/identity_check');
var exceptions = require('../../src/lib/exceptions'); var exceptions = require('../../src/lib/Exceptions');
var assert = require('assert'); var assert = require('assert');
var winston = require('winston'); var winston = require('winston');
var Promise = require('bluebird'); var Promise = require('bluebird');

View File

@ -122,7 +122,7 @@ describe('test ldap validation', function() {
var expected_doc = {}; var expected_doc = {};
expected_doc.mail = []; expected_doc.mail = [];
expected_doc.mail.push('user@example.com'); expected_doc.mail.push('user@example.com');
ldap_client.search.yields('error'); ldap_client.search.yields('Error while searching mails');
return ldap.get_emails('user') return ldap.get_emails('user')
.catch(function() { .catch(function() {