diff --git a/.travis.yml b/.travis.yml index 27105ca44..077e57022 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ -dist: trusty language: node_js -sudo: required node_js: - "8" services: diff --git a/Gruntfile.js b/Gruntfile.js index b25a01433..068897681 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -19,7 +19,7 @@ module.exports = function (grunt) { "generate-config-schema": { cmd: "./node_modules/.bin/typescript-json-schema", args: ["-o", schemaDir, "--strictNullChecks", - "--required", "server/tsconfig.json", "UserConfiguration"] + "--required", "server/tsconfig.json", "Configuration"] }, "compile-client": { cmd: "./node_modules/.bin/tsc", @@ -35,11 +35,11 @@ module.exports = function (grunt) { }, "test-server-unit": { cmd: "./node_modules/.bin/mocha", - args: ['--colors', '--compilers', 'ts:ts-node/register', '--recursive', 'server/test'] + args: ['--colors', '--require', 'ts-node/register', 'server/src/**/*.spec.ts'] }, "test-client-unit": { cmd: "./node_modules/.bin/mocha", - args: ['--colors', '--compilers', 'ts:ts-node/register', '--recursive', 'client/test'] + args: ['--colors', '--require', 'ts-node/register', 'client/test/**/*.test.ts'] }, "test-int": { cmd: "./scripts/run-cucumber.sh", diff --git a/config.minimal.yml b/config.minimal.yml new file mode 100644 index 000000000..0a910b1be --- /dev/null +++ b/config.minimal.yml @@ -0,0 +1,24 @@ +############################################################### +# Authelia minimal configuration # +############################################################### + +ldap: + url: ldap://openldap + base_dn: dc=example,dc=com + + additional_users_dn: ou=users + additional_groups_dn: ou=groups + + groups_filter: (&(member={dn})(objectclass=groupOfNames)) + + user: cn=admin,dc=example,dc=com + password: password + +session: + # The secret to encrypt the session cookies. + secret: unsecure_session_secret + + # The domain to protect. + # Note: the authenticator must also be in that domain. If empty, the cookie + # is restricted to the subdomain of the issuer. + domain: example.com diff --git a/config.template.yml b/config.template.yml index 5022d6e35..c127f1c2d 100644 --- a/config.template.yml +++ b/config.template.yml @@ -191,10 +191,11 @@ session: # time. regulation: # The number of failed login attempts before user is banned. - # Set it to 0 for disabling regulation. + # Set it to 0 to disable regulation. max_retries: 3 - # The length of time between login attempts before user is banned. + # The time range during which the user can attempt login before being banned. + # The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window. find_time: 120 # The length of time before a banned user can login again. diff --git a/server/src/lib/AuthenticationSessionHandler.ts b/server/src/lib/AuthenticationSessionHandler.ts index 2349490b8..ae2ff7c53 100644 --- a/server/src/lib/AuthenticationSessionHandler.ts +++ b/server/src/lib/AuthenticationSessionHandler.ts @@ -29,7 +29,7 @@ export class AuthenticationSessionHandler { static get(req: express.Request, logger: IRequestLogger): AuthenticationSession { if (!req.session) { - const errorMsg = "Something is wrong with session cookies. Please check Redis is running and Authelia can contact it."; + const errorMsg = "Something is wrong with session cookies. Please check Redis is running and Authelia can connect to it."; logger.error(req, errorMsg); throw new Error(errorMsg); } diff --git a/server/test/IdentityCheckMiddleware.test.ts b/server/src/lib/IdentityCheckMiddleware.spec.ts similarity index 73% rename from server/test/IdentityCheckMiddleware.test.ts rename to server/src/lib/IdentityCheckMiddleware.spec.ts index f59832d67..5f2b23a4b 100644 --- a/server/test/IdentityCheckMiddleware.test.ts +++ b/server/src/lib/IdentityCheckMiddleware.spec.ts @@ -1,32 +1,32 @@ import sinon = require("sinon"); -import IdentityValidator = require("../src/lib/IdentityCheckMiddleware"); +import IdentityValidator = require("./IdentityCheckMiddleware"); import { AuthenticationSessionHandler } - from "../src/lib/AuthenticationSessionHandler"; -import { AuthenticationSession } from "../types/AuthenticationSession"; -import { UserDataStore } from "../src/lib/storage/UserDataStore"; -import exceptions = require("../src/lib/Exceptions"); -import { ServerVariables } from "../src/lib/ServerVariables"; + from "./AuthenticationSessionHandler"; +import { AuthenticationSession } from "../../types/AuthenticationSession"; +import { UserDataStore } from "./storage/UserDataStore"; +import exceptions = require("./Exceptions"); +import { ServerVariables } from "./ServerVariables"; import Assert = require("assert"); import express = require("express"); import BluebirdPromise = require("bluebird"); -import ExpressMock = require("./mocks/express"); -import NotifierMock = require("./mocks/Notifier"); -import IdentityValidatorMock = require("./mocks/IdentityValidator"); -import { RequestLoggerStub } from "./mocks/RequestLoggerStub"; +import ExpressMock = require("./stubs/express.spec"); +import NotifierMock = require("./notifiers/NotifierStub.spec"); +import { IdentityValidableStub } from "./IdentityValidableStub.spec"; +import { RequestLoggerStub } from "./logging/RequestLoggerStub.spec"; import { ServerVariablesMock, ServerVariablesMockBuilder } - from "./mocks/ServerVariablesMockBuilder"; + from "./ServerVariablesMockBuilder.spec"; import { PRE_VALIDATION_TEMPLATE } - from "../src/lib/IdentityCheckPreValidationTemplate"; + from "./IdentityCheckPreValidationTemplate"; -describe("test identity check process", function () { +describe("IdentityCheckMiddleware", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let app: express.Application; let app_get: sinon.SinonStub; let app_post: sinon.SinonStub; - let identityValidable: IdentityValidatorMock.IdentityValidableMock; + let identityValidable: IdentityValidableStub; let mocks: ServerVariablesMock; let vars: ServerVariables; @@ -38,8 +38,6 @@ describe("test identity check process", function () { req = ExpressMock.RequestMock(); res = ExpressMock.ResponseMock(); - identityValidable = IdentityValidatorMock.IdentityValidableMock(); - req.headers = {}; req.originalUrl = "/non-api/xxx"; req.session = {}; @@ -47,6 +45,8 @@ describe("test identity check process", function () { req.query = {}; req.app = {}; + identityValidable = new IdentityValidableStub(); + mocks.notifier.notifyStub.returns(BluebirdPromise.resolve()); mocks.userDataStore.produceIdentityValidationTokenStub .returns(BluebirdPromise.resolve()); @@ -66,7 +66,7 @@ describe("test identity check process", function () { describe("test start GET", function () { it("should redirect to error 401 if pre validation initialization \ throws a first factor error", function () { - identityValidable.preValidationInit.returns(BluebirdPromise.reject( + identityValidable.preValidationInitStub.returns(BluebirdPromise.reject( new exceptions.FirstFactorValidationError( "Error during prevalidation"))); const callback = IdentityValidator.get_start_validation( @@ -83,14 +83,14 @@ throws a first factor error", function () { it("should send 200 if email is missing in provided identity", function () { const identity = { userid: "abc" }; - identityValidable.preValidationInit + identityValidable.preValidationInitStub .returns(BluebirdPromise.resolve(identity)); const callback = IdentityValidator .get_start_validation(identityValidable, "/endpoint", vars); return callback(req as any, res as any, undefined) .then(function () { - Assert(identityValidable.preValidationResponse.called); + Assert(identityValidable.preValidationResponseStub.called); }); }); @@ -100,14 +100,14 @@ throws a first factor error", function () { const endpoint = "/protected"; const identity = { email: "abc@example.com" }; - identityValidable.preValidationInit + identityValidable.preValidationInitStub .returns(BluebirdPromise.resolve(identity)); const callback = IdentityValidator .get_start_validation(identityValidable, "/endpoint", vars); return callback(req as any, res as any, undefined) .then(function () { - Assert(identityValidable.preValidationResponse.called); + Assert(identityValidable.preValidationResponseStub.called); }); }); @@ -116,7 +116,7 @@ throws a first factor error", function () { const identity = { userid: "user", email: "abc@example.com" }; req.get = sinon.stub().withArgs("Host").returns("localhost"); - identityValidable.preValidationInit + identityValidable.preValidationInitStub .returns(BluebirdPromise.resolve(identity)); const callback = IdentityValidator .get_start_validation(identityValidable, "/finish_endpoint", vars); @@ -177,24 +177,5 @@ valid", function () { Assert(res.redirect.calledWith("/error/401")); }); }); - - it("should set the identity_check session object even if session does \ -not exist yet", function () { - req.query.identity_token = "token"; - - req.session = {}; - const authSession = - AuthenticationSessionHandler.get(req as any, vars.logger); - const callback = IdentityValidator - .get_finish_validation(identityValidable, vars); - - return callback(req as any, res as any, undefined) - .then(function () { - return BluebirdPromise.reject("Should fail"); - }) - .catch(function () { - Assert.equal(authSession.identity_check.userid, "user"); - }); - }); }); }); diff --git a/server/src/lib/IdentityCheckMiddleware.ts b/server/src/lib/IdentityCheckMiddleware.ts index 4a6486595..1163aea68 100644 --- a/server/src/lib/IdentityCheckMiddleware.ts +++ b/server/src/lib/IdentityCheckMiddleware.ts @@ -1,4 +1,3 @@ - import objectPath = require("object-path"); import randomstring = require("randomstring"); import BluebirdPromise = require("bluebird"); @@ -12,6 +11,7 @@ import ErrorReplies = require("./ErrorReplies"); import { AuthenticationSessionHandler } from "./AuthenticationSessionHandler"; import { AuthenticationSession } from "../../types/AuthenticationSession"; import { ServerVariables } from "./ServerVariables"; +import { IdentityValidable } from "./IdentityValidable"; import Identity = require("../../types/Identity"); import { IdentityValidationDocument } @@ -20,26 +20,9 @@ import { IdentityValidationDocument } const filePath = __dirname + "/../resources/email-template.ejs"; const email_template = fs.readFileSync(filePath, "utf8"); -// IdentityValidator allows user to go through a identity validation process -// in two steps: -// - Request an operation to be performed (password reset, registration). -// - Confirm operation with email. - -export interface IdentityValidable { - challenge(): string; - preValidationInit(req: Express.Request): BluebirdPromise; - postValidationInit(req: Express.Request): BluebirdPromise; - - // Serves a page after identity check request - preValidationResponse(req: Express.Request, res: Express.Response): void; - // Serves the page if identity validated - postValidationResponse(req: Express.Request, res: Express.Response): void; - mailSubject(): string; -} - function createAndSaveToken(userid: string, challenge: string, - userDataStore: IUserDataStore) - : BluebirdPromise { + userDataStore: IUserDataStore): BluebirdPromise { + const five_minutes = 4 * 60 * 1000; const token = randomstring.generate({ length: 64 }); const that = this; @@ -80,8 +63,10 @@ function checkIdentityToken(req: Express.Request, identityToken: string) export function get_finish_validation(handler: IdentityValidable, vars: ServerVariables) : Express.RequestHandler { + return function (req: Express.Request, res: Express.Response) : BluebirdPromise { + let authSession: AuthenticationSession; const identityToken = objectPath.get( req, "query.identity_token"); diff --git a/server/src/lib/IdentityValidable.ts b/server/src/lib/IdentityValidable.ts new file mode 100644 index 000000000..075580c9e --- /dev/null +++ b/server/src/lib/IdentityValidable.ts @@ -0,0 +1,19 @@ +import Bluebird = require("bluebird"); +import Identity = require("../../types/Identity"); + +// IdentityValidator allows user to go through a identity validation process +// in two steps: +// - Request an operation to be performed (password reset, registration). +// - Confirm operation with email. + +export interface IdentityValidable { + challenge(): string; + preValidationInit(req: Express.Request): Bluebird; + postValidationInit(req: Express.Request): Bluebird; + + // Serves a page after identity check request + preValidationResponse(req: Express.Request, res: Express.Response): void; + // Serves the page if identity validated + postValidationResponse(req: Express.Request, res: Express.Response): void; + mailSubject(): string; +} \ No newline at end of file diff --git a/server/src/lib/IdentityValidableStub.spec.ts b/server/src/lib/IdentityValidableStub.spec.ts new file mode 100644 index 000000000..f8722a63f --- /dev/null +++ b/server/src/lib/IdentityValidableStub.spec.ts @@ -0,0 +1,52 @@ + +import Sinon = require("sinon"); +import { IdentityValidable } from "./IdentityValidable"; +import express = require("express"); +import Bluebird = require("bluebird"); +import { Identity } from "../../types/Identity"; + + +export class IdentityValidableStub implements IdentityValidable { + challengeStub: Sinon.SinonStub; + preValidationInitStub: Sinon.SinonStub; + postValidationInitStub: Sinon.SinonStub; + preValidationResponseStub: Sinon.SinonStub; + postValidationResponseStub: Sinon.SinonStub; + mailSubjectStub: Sinon.SinonStub; + + constructor() { + this.challengeStub = Sinon.stub(); + + this.preValidationInitStub = Sinon.stub(); + this.postValidationResponseStub = Sinon.stub(); + + this.preValidationResponseStub = Sinon.stub(); + this.postValidationResponseStub = Sinon.stub(); + + this.mailSubjectStub = Sinon.stub(); + } + + challenge(): string { + return this.challengeStub(); + } + + preValidationInit(req: Express.Request): Bluebird { + return this.preValidationInitStub(req); + } + + postValidationInit(req: Express.Request): Bluebird { + return this.postValidationInitStub(req); + } + + preValidationResponse(req: Express.Request, res: Express.Response): void { + return this.preValidationResponseStub(req, res); + } + + postValidationResponse(req: Express.Request, res: Express.Response): void { + return this.postValidationResponseStub(req, res); + } + + mailSubject(): string { + return this.mailSubjectStub(); + } +} \ No newline at end of file diff --git a/server/test/ServerConfiguration.test.ts b/server/src/lib/Server.spec.ts similarity index 82% rename from server/test/ServerConfiguration.test.ts rename to server/src/lib/Server.spec.ts index bc6c1ba82..e3a00e1fe 100644 --- a/server/test/ServerConfiguration.test.ts +++ b/server/src/lib/Server.spec.ts @@ -7,13 +7,13 @@ import winston = require("winston"); import speakeasy = require("speakeasy"); import u2f = require("u2f"); import session = require("express-session"); -import { AppConfiguration, UserConfiguration } from "../src/lib/configuration/Configuration"; -import { GlobalDependencies } from "../types/Dependencies"; -import Server from "../src/lib/Server"; -import { LdapjsMock, LdapjsClientMock } from "./mocks/ldapjs"; +import { Configuration } from "./configuration/schema/Configuration"; +import { GlobalDependencies } from "../../types/Dependencies"; +import Server from "./Server"; +import { LdapjsMock, LdapjsClientMock } from "./stubs/ldapjs.spec"; -describe("test server configuration", function () { +describe("Server", function () { let deps: GlobalDependencies; let sessionMock: Sinon.SinonSpy; let ldapjsMock: LdapjsMock; @@ -36,7 +36,7 @@ describe("test server configuration", function () { it("should set cookie scope to domain set in the config", function () { - const config: UserConfiguration = { + const config: Configuration = { port: 8081, session: { domain: "example.com", diff --git a/server/src/lib/Server.ts b/server/src/lib/Server.ts index ad8ebd2be..c8e969e7a 100644 --- a/server/src/lib/Server.ts +++ b/server/src/lib/Server.ts @@ -2,7 +2,7 @@ import BluebirdPromise = require("bluebird"); import ObjectPath = require("object-path"); import { AccessController } from "./access_control/AccessController"; -import { AppConfiguration, UserConfiguration } from "./configuration/Configuration"; +import { Configuration } from "./configuration/schema/Configuration"; import { GlobalDependencies } from "../../types/Dependencies"; import { UserDataStore } from "./storage/UserDataStore"; import { ConfigurationParser } from "./configuration/ConfigurationParser"; @@ -31,33 +31,22 @@ export default class Server { this.requestLogger = new RequestLogger(deps.winston); } - private displayConfigurations(userConfiguration: UserConfiguration, - appConfiguration: AppConfiguration) { - const displayableUserConfiguration = clone(userConfiguration); - const displayableAppConfiguration = clone(appConfiguration); + private displayConfigurations(configuration: Configuration) { + const displayableConfiguration: Configuration = clone(configuration); const STARS = "*****"; - displayableUserConfiguration.ldap.password = STARS; - displayableUserConfiguration.session.secret = STARS; - if (displayableUserConfiguration.notifier && displayableUserConfiguration.notifier.email) - displayableUserConfiguration.notifier.email.password = STARS; - if (displayableUserConfiguration.notifier && displayableUserConfiguration.notifier.smtp) - displayableUserConfiguration.notifier.smtp.password = STARS; - - displayableAppConfiguration.ldap.password = STARS; - displayableAppConfiguration.session.secret = STARS; - if (displayableAppConfiguration.notifier && displayableAppConfiguration.notifier.email) - displayableAppConfiguration.notifier.email.password = STARS; - if (displayableAppConfiguration.notifier && displayableAppConfiguration.notifier.smtp) - displayableAppConfiguration.notifier.smtp.password = STARS; + displayableConfiguration.ldap.password = STARS; + displayableConfiguration.session.secret = STARS; + if (displayableConfiguration.notifier && displayableConfiguration.notifier.email) + displayableConfiguration.notifier.email.password = STARS; + if (displayableConfiguration.notifier && displayableConfiguration.notifier.smtp) + displayableConfiguration.notifier.smtp.password = STARS; this.globalLogger.debug("User configuration is %s", - JSON.stringify(displayableUserConfiguration, undefined, 2)); - this.globalLogger.debug("Adapted configuration is %s", - JSON.stringify(displayableAppConfiguration, undefined, 2)); + JSON.stringify(displayableConfiguration, undefined, 2)); } - private setup(config: AppConfiguration, app: Express.Application, deps: GlobalDependencies): BluebirdPromise { + private setup(config: Configuration, app: Express.Application, deps: GlobalDependencies): BluebirdPromise { const that = this; return ServerVariablesInitializer.initialize(config, this.requestLogger, deps) .then(function (vars: ServerVariables) { @@ -76,16 +65,16 @@ export default class Server { }); } - start(userConfiguration: UserConfiguration, deps: GlobalDependencies) + start(configuration: Configuration, deps: GlobalDependencies) : BluebirdPromise { const that = this; const app = Express(); - const appConfiguration = ConfigurationParser.parse(userConfiguration); + const appConfiguration = ConfigurationParser.parse(configuration); // by default the level of logs is info - deps.winston.level = userConfiguration.logs_level; - this.displayConfigurations(userConfiguration, appConfiguration); + deps.winston.level = configuration.logs_level; + this.displayConfigurations(configuration); return this.setup(appConfiguration, app, deps) .then(function () { diff --git a/server/src/lib/ServerVariables.ts b/server/src/lib/ServerVariables.ts index a7b1e2e5e..cdd5285e2 100644 --- a/server/src/lib/ServerVariables.ts +++ b/server/src/lib/ServerVariables.ts @@ -7,7 +7,7 @@ import { IU2fHandler } from "./authentication/u2f/IU2fHandler"; import { IUserDataStore } from "./storage/IUserDataStore"; import { INotifier } from "./notifiers/INotifier"; import { IRegulator } from "./regulation/IRegulator"; -import { AppConfiguration } from "./configuration/Configuration"; +import { Configuration } from "./configuration/schema/Configuration"; import { IAccessController } from "./access_control/IAccessController"; export interface ServerVariables { @@ -20,6 +20,6 @@ export interface ServerVariables { userDataStore: IUserDataStore; notifier: INotifier; regulator: IRegulator; - config: AppConfiguration; + config: Configuration; accessController: IAccessController; } \ No newline at end of file diff --git a/server/src/lib/ServerVariablesInitializer.ts b/server/src/lib/ServerVariablesInitializer.ts index 9eed50f12..2a9f40977 100644 --- a/server/src/lib/ServerVariablesInitializer.ts +++ b/server/src/lib/ServerVariablesInitializer.ts @@ -26,7 +26,7 @@ import { UserDataStore } from "./storage/UserDataStore"; import { INotifier } from "./notifiers/INotifier"; import { Regulator } from "./regulation/Regulator"; import { IRegulator } from "./regulation/IRegulator"; -import Configuration = require("./configuration/Configuration"); +import Configuration = require("./configuration/schema/Configuration"); import { AccessController } from "./access_control/AccessController"; import { IAccessController } from "./access_control/IAccessController"; import { CollectionFactoryFactory } from "./storage/CollectionFactoryFactory"; @@ -40,7 +40,7 @@ import { ServerVariables } from "./ServerVariables"; import { MethodCalculator } from "./authentication/MethodCalculator"; class UserDataStoreFactory { - static create(config: Configuration.AppConfiguration): BluebirdPromise { + static create(config: Configuration.Configuration): BluebirdPromise { if (config.storage.local) { const nedbOptions: Nedb.DataStoreOptions = { filename: config.storage.local.path, @@ -64,7 +64,7 @@ class UserDataStoreFactory { } export class ServerVariablesInitializer { - static initialize(config: Configuration.AppConfiguration, requestLogger: IRequestLogger, + static initialize(config: Configuration.Configuration, requestLogger: IRequestLogger, deps: GlobalDependencies): BluebirdPromise { const mailSenderBuilder = new MailSenderBuilder(Nodemailer); const notifier = NotifierFactory.build(config.notifier, mailSenderBuilder); diff --git a/server/test/mocks/ServerVariablesMockBuilder.ts b/server/src/lib/ServerVariablesMockBuilder.spec.ts similarity index 70% rename from server/test/mocks/ServerVariablesMockBuilder.ts rename to server/src/lib/ServerVariablesMockBuilder.spec.ts index 7a4ef5ca9..a26218e1a 100644 --- a/server/test/mocks/ServerVariablesMockBuilder.ts +++ b/server/src/lib/ServerVariablesMockBuilder.spec.ts @@ -1,20 +1,20 @@ -import { ServerVariables } from "../../src/lib/ServerVariables"; +import { ServerVariables } from "./ServerVariables"; -import { AppConfiguration } from "../../src/lib/configuration/Configuration"; -import { AuthenticatorStub } from "./ldap/AuthenticatorStub"; -import { EmailsRetrieverStub } from "./ldap/EmailsRetrieverStub"; -import { PasswordUpdaterStub } from "./ldap/PasswordUpdaterStub"; -import { AccessControllerStub } from "./AccessControllerStub"; -import { RequestLoggerStub } from "./RequestLoggerStub"; -import { NotifierStub } from "./NotifierStub"; -import { RegulatorStub } from "./RegulatorStub"; -import { TotpHandlerStub } from "./TotpHandlerStub"; -import { UserDataStoreStub } from "./storage/UserDataStoreStub"; -import { U2fHandlerStub } from "./U2fHandlerStub"; +import { Configuration } from "./configuration/schema/Configuration"; +import { AuthenticatorStub } from "./ldap/AuthenticatorStub.spec"; +import { EmailsRetrieverStub } from "./ldap/EmailsRetrieverStub.spec"; +import { PasswordUpdaterStub } from "./ldap/PasswordUpdaterStub.spec"; +import { AccessControllerStub } from "./access_control/AccessControllerStub.spec"; +import { RequestLoggerStub } from "./logging/RequestLoggerStub.spec"; +import { NotifierStub } from "./notifiers/NotifierStub.spec"; +import { RegulatorStub } from "./regulation/RegulatorStub.spec"; +import { TotpHandlerStub } from "./authentication/totp/TotpHandlerStub.spec"; +import { UserDataStoreStub } from "./storage/UserDataStoreStub.spec"; +import { U2fHandlerStub } from "./authentication/u2f/U2fHandlerStub.spec"; export interface ServerVariablesMock { accessController: AccessControllerStub; - config: AppConfiguration; + config: Configuration; ldapAuthenticator: AuthenticatorStub; ldapEmailsRetriever: EmailsRetrieverStub; ldapPasswordUpdater: PasswordUpdaterStub; @@ -40,11 +40,12 @@ export class ServerVariablesMockBuilder { }, ldap: { url: "ldap://ldap", + base_dn: "dc=example,dc=com", user: "user", password: "password", mail_attribute: "mail", - users_dn: "ou=users,dc=example,dc=com", - groups_dn: "ou=groups,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", users_filter: "cn={0}", groups_filter: "member={dn}", group_name_attribute: "cn" diff --git a/server/test/access_control/AccessController.test.ts b/server/src/lib/access_control/AccessController.spec.ts similarity index 98% rename from server/test/access_control/AccessController.test.ts rename to server/src/lib/access_control/AccessController.spec.ts index 322c3540a..057e23d8e 100644 --- a/server/test/access_control/AccessController.test.ts +++ b/server/src/lib/access_control/AccessController.spec.ts @@ -1,10 +1,10 @@ import Assert = require("assert"); import winston = require("winston"); -import { AccessController } from "../../src/lib/access_control/AccessController"; -import { ACLConfiguration, ACLRule } from "../../src/lib/configuration/Configuration"; +import { AccessController } from "./AccessController"; +import { ACLConfiguration, ACLRule } from "../configuration/schema/AclConfiguration"; -describe("test access control manager", function () { +describe("access_control/AccessController", function () { let accessController: AccessController; let configuration: ACLConfiguration; diff --git a/server/src/lib/access_control/AccessController.ts b/server/src/lib/access_control/AccessController.ts index a7a572080..dd7328fdd 100644 --- a/server/src/lib/access_control/AccessController.ts +++ b/server/src/lib/access_control/AccessController.ts @@ -1,5 +1,5 @@ -import { ACLConfiguration, ACLPolicy, ACLRule } from "../configuration/Configuration"; +import { ACLConfiguration, ACLPolicy, ACLRule } from "../configuration/schema/AclConfiguration"; import { IAccessController } from "./IAccessController"; import { Winston } from "../../../types/Dependencies"; import { MultipleDomainMatcher } from "./MultipleDomainMatcher"; diff --git a/server/test/mocks/AccessControllerStub.ts b/server/src/lib/access_control/AccessControllerStub.spec.ts similarity index 81% rename from server/test/mocks/AccessControllerStub.ts rename to server/src/lib/access_control/AccessControllerStub.spec.ts index e295cdab9..607454690 100644 --- a/server/test/mocks/AccessControllerStub.ts +++ b/server/src/lib/access_control/AccessControllerStub.spec.ts @@ -1,6 +1,5 @@ - import Sinon = require("sinon"); -import { IAccessController } from "../../src/lib/access_control/IAccessController"; +import { IAccessController } from "./IAccessController"; export class AccessControllerStub implements IAccessController { isAccessAllowedMock: Sinon.SinonStub; diff --git a/server/test/authentication/MethodCalculator.test.ts b/server/src/lib/authentication/MethodCalculator.spec.ts similarity index 93% rename from server/test/authentication/MethodCalculator.test.ts rename to server/src/lib/authentication/MethodCalculator.spec.ts index 45b3ee2f8..6c6c916a0 100644 --- a/server/test/authentication/MethodCalculator.test.ts +++ b/server/src/lib/authentication/MethodCalculator.spec.ts @@ -1,10 +1,9 @@ -import { MethodCalculator } - from "../../src/lib/authentication/MethodCalculator"; +import { MethodCalculator } from "./MethodCalculator"; import { AuthenticationMethodsConfiguration } - from "../../src/lib/configuration/Configuration"; + from "../configuration/schema/AuthenticationMethodsConfiguration"; import Assert = require("assert"); -describe("test MethodCalculator", function () { +describe("authentication/MethodCalculator", function () { describe("test compute method", function () { it("should return default method when sub domain not overriden", function () { diff --git a/server/src/lib/authentication/MethodCalculator.ts b/server/src/lib/authentication/MethodCalculator.ts index d18a83f38..961a8402d 100644 --- a/server/src/lib/authentication/MethodCalculator.ts +++ b/server/src/lib/authentication/MethodCalculator.ts @@ -1,7 +1,7 @@ import { AuthenticationMethod, AuthenticationMethodsConfiguration -} from "../configuration/Configuration"; +} from "../configuration/schema/AuthenticationMethodsConfiguration"; function computeIsSingleFactorOnlyMode( configuration: AuthenticationMethodsConfiguration): boolean { diff --git a/server/test/authentication/totp/Validator.test.ts b/server/src/lib/authentication/totp/TotpHandler.spec.ts similarity index 88% rename from server/test/authentication/totp/Validator.test.ts rename to server/src/lib/authentication/totp/TotpHandler.spec.ts index 3d0518440..67cffa638 100644 --- a/server/test/authentication/totp/Validator.test.ts +++ b/server/src/lib/authentication/totp/TotpHandler.spec.ts @@ -1,10 +1,10 @@ -import { TotpHandler } from "../../../src/lib/authentication/totp/TotpHandler"; +import { TotpHandler } from "./TotpHandler"; import Sinon = require("sinon"); import Speakeasy = require("speakeasy"); import Assert = require("assert"); -describe("test TOTP validation", function() { +describe("authentication/totp/TotpHandler", function() { let totpValidator: TotpHandler; let validateStub: Sinon.SinonStub; diff --git a/server/test/mocks/TotpHandlerStub.ts b/server/src/lib/authentication/totp/TotpHandlerStub.spec.ts similarity index 79% rename from server/test/mocks/TotpHandlerStub.ts rename to server/src/lib/authentication/totp/TotpHandlerStub.spec.ts index 8b261effe..ea93330d9 100644 --- a/server/test/mocks/TotpHandlerStub.ts +++ b/server/src/lib/authentication/totp/TotpHandlerStub.spec.ts @@ -1,7 +1,7 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); -import { ITotpHandler } from "../../src/lib/authentication/totp/ITotpHandler"; -import { TOTPSecret } from "../../types/TOTPSecret"; +import { ITotpHandler } from "./ITotpHandler"; +import { TOTPSecret } from "../../../../types/TOTPSecret"; export class TotpHandlerStub implements ITotpHandler { generateStub: Sinon.SinonStub; diff --git a/server/test/mocks/U2fHandlerStub.ts b/server/src/lib/authentication/u2f/U2fHandlerStub.spec.ts similarity index 92% rename from server/test/mocks/U2fHandlerStub.ts rename to server/src/lib/authentication/u2f/U2fHandlerStub.spec.ts index 95256641f..135d7eb06 100644 --- a/server/test/mocks/U2fHandlerStub.ts +++ b/server/src/lib/authentication/u2f/U2fHandlerStub.spec.ts @@ -1,7 +1,7 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import U2f = require("u2f"); -import { IU2fHandler } from "../../src/lib/authentication/u2f/IU2fHandler"; +import { IU2fHandler } from "./IU2fHandler"; export class U2fHandlerStub implements IU2fHandler { diff --git a/server/src/lib/configuration/Configuration.d.ts b/server/src/lib/configuration/Configuration.d.ts deleted file mode 100644 index 20555b993..000000000 --- a/server/src/lib/configuration/Configuration.d.ts +++ /dev/null @@ -1,155 +0,0 @@ -export interface UserLdapConfiguration { - url: string; - base_dn: string; - - additional_users_dn?: string; - users_filter?: string; - - additional_groups_dn?: string; - groups_filter?: string; - - group_name_attribute?: string; - mail_attribute?: string; - - user: string; // admin username - password: string; // admin password -} - -export interface LdapConfiguration { - url: string; - - users_dn: string; - users_filter: string; - - groups_dn: string; - groups_filter: string; - - group_name_attribute: string; - mail_attribute: string; - - user: string; // admin username - password: string; // admin password -} - -type UserName = string; -type GroupName = string; -type DomainPattern = string; - -export type ACLPolicy = 'deny' | 'allow'; - -export type ACLRule = { - domain: string; - policy: ACLPolicy; - resources?: string[]; -} - -export type ACLDefaultRules = ACLRule[]; -export type ACLGroupsRules = { [group: string]: ACLRule[]; }; -export type ACLUsersRules = { [user: string]: ACLRule[]; }; - -export interface ACLConfiguration { - default_policy?: ACLPolicy; - any?: ACLDefaultRules; - groups?: ACLGroupsRules; - users?: ACLUsersRules; -} - -export interface SessionRedisOptions { - host: string; - port: number; -} - -interface SessionCookieConfiguration { - secret: string; - expiration?: number; - inactivity?: number; - domain: string; - redis?: SessionRedisOptions; -} - -export interface EmailNotifierConfiguration { - username: string; - password: string; - sender: string; - service: string; -} - -export interface SmtpNotifierConfiguration { - username?: string; - password?: string; - host: string; - port: number; - secure: boolean; - sender: string; -} - -export interface FileSystemNotifierConfiguration { - filename: string; -} - -export interface NotifierConfiguration { - email?: EmailNotifierConfiguration; - smtp?: SmtpNotifierConfiguration; - filesystem?: FileSystemNotifierConfiguration; -} - -export interface MongoStorageConfiguration { - url: string; - database: string; -} - -export interface LocalStorageConfiguration { - path?: string; - in_memory?: boolean; -} - -export interface StorageConfiguration { - local?: LocalStorageConfiguration; - mongo?: MongoStorageConfiguration; -} - -export interface RegulationConfiguration { - max_retries: number; - find_time: number; - ban_time: number; -} - -declare type AuthenticationMethod = 'two_factor' | 'single_factor'; -declare type AuthenticationMethodPerSubdomain = { [subdomain: string]: AuthenticationMethod } - -export interface AuthenticationMethodsConfiguration { - default_method: AuthenticationMethod; - per_subdomain_methods?: AuthenticationMethodPerSubdomain; -} - -export interface TOTPConfiguration { - issuer: string; -} - -export interface UserConfiguration { - port?: number; - logs_level?: string; - ldap: UserLdapConfiguration; - session: SessionCookieConfiguration; - storage: StorageConfiguration; - notifier: NotifierConfiguration; - authentication_methods?: AuthenticationMethodsConfiguration; - access_control?: ACLConfiguration; - regulation: RegulationConfiguration; - default_redirection_url?: string; - totp?: TOTPConfiguration; -} - -export interface AppConfiguration { - port: number; - logs_level: string; - ldap: LdapConfiguration; - session: SessionCookieConfiguration; - storage: StorageConfiguration; - notifier: NotifierConfiguration; - authentication_methods: AuthenticationMethodsConfiguration; - access_control?: ACLConfiguration; - regulation: RegulationConfiguration; - default_redirection_url?: string; - totp: TOTPConfiguration; -} diff --git a/server/test/configuration/ConfigurationParser.test.ts b/server/src/lib/configuration/ConfigurationParser.spec.ts similarity index 92% rename from server/test/configuration/ConfigurationParser.test.ts rename to server/src/lib/configuration/ConfigurationParser.spec.ts index 107a94ebe..bb304386d 100644 --- a/server/test/configuration/ConfigurationParser.test.ts +++ b/server/src/lib/configuration/ConfigurationParser.spec.ts @@ -1,13 +1,11 @@ import * as Assert from "assert"; -import { - UserConfiguration, - LdapConfiguration, ACLConfiguration -} from "../../src/lib/configuration/Configuration"; -import { ConfigurationParser } from "../../src/lib/configuration/ConfigurationParser"; +import { Configuration } from "./schema/Configuration"; +import { ACLConfiguration } from "./schema/AclConfiguration"; +import { ConfigurationParser } from "./ConfigurationParser"; -describe("test config parser", function () { - function buildYamlConfig(): UserConfiguration { - const yaml_config: UserConfiguration = { +describe("configuration/ConfigurationParser", function () { + function buildYamlConfig(): Configuration { + const yaml_config: Configuration = { port: 8080, ldap: { url: "http://ldap", @@ -160,11 +158,11 @@ describe("test config parser", function () { userConfig.access_control = {} as any; const config = ConfigurationParser.parse(userConfig); Assert.deepEqual(config.access_control, { - default_policy: "deny", + default_policy: "allow", any: [], users: {}, groups: {} - } as ACLConfiguration); + }); }); }); diff --git a/server/src/lib/configuration/ConfigurationParser.ts b/server/src/lib/configuration/ConfigurationParser.ts index 858936311..a67632c3b 100644 --- a/server/src/lib/configuration/ConfigurationParser.ts +++ b/server/src/lib/configuration/ConfigurationParser.ts @@ -1,109 +1,39 @@ import * as ObjectPath from "object-path"; -import { - AppConfiguration, UserConfiguration, NotifierConfiguration, - ACLConfiguration, LdapConfiguration, SessionRedisOptions, - MongoStorageConfiguration, LocalStorageConfiguration, - UserLdapConfiguration -} from "./Configuration"; +import { Configuration, complete } from "./schema/Configuration"; +import Ajv = require("ajv"); +import Path = require("path"); import Util = require("util"); -import { ACLAdapter } from "./adapters/ACLAdapter"; -import { TOTPAdapter } from "./adapters/TOTPAdapter"; -import { AuthenticationMethodsAdapter } from "./adapters/AuthenticationMethodsAdapter"; -import { Validator } from "./Validator"; - -const LDAP_URL_ENV_VARIABLE = "LDAP_URL"; - -function get_optional(config: object, path: string, default_value: T): T { - let entry = default_value; - if (ObjectPath.has(config, path)) { - entry = ObjectPath.get(config, path); - } - return entry; -} - -function ensure_key_existence(config: object, path: string): void { - if (!ObjectPath.has(config, path)) { - throw new Error(`Configuration error: key '${path}' is missing in configuration file`); - } -} - -function adaptLdapConfiguration(userConfig: UserLdapConfiguration): LdapConfiguration { - const DEFAULT_USERS_FILTER = "cn={0}"; - const DEFAULT_GROUPS_FILTER = "member={dn}"; - const DEFAULT_GROUP_NAME_ATTRIBUTE = "cn"; - const DEFAULT_MAIL_ATTRIBUTE = "mail"; - - let usersDN = userConfig.base_dn; - if (userConfig.additional_users_dn) - usersDN = userConfig.additional_users_dn + "," + usersDN; - - let groupsDN = userConfig.base_dn; - if (userConfig.additional_groups_dn) - groupsDN = userConfig.additional_groups_dn + "," + groupsDN; - - return { - url: userConfig.url, - users_dn: usersDN, - users_filter: userConfig.users_filter || DEFAULT_USERS_FILTER, - groups_dn: groupsDN, - groups_filter: userConfig.groups_filter || DEFAULT_GROUPS_FILTER, - group_name_attribute: userConfig.group_name_attribute || DEFAULT_GROUP_NAME_ATTRIBUTE, - mail_attribute: userConfig.mail_attribute || DEFAULT_MAIL_ATTRIBUTE, - password: userConfig.password, - user: userConfig.user - }; -} - -function adaptFromUserConfiguration(userConfiguration: UserConfiguration) - : AppConfiguration { - if (!Validator.isValid(userConfiguration)) - throw new Error("Configuration is malformed. Please double check your configuration file."); - - const port = userConfiguration.port || 8080; - const ldapConfiguration = adaptLdapConfiguration(userConfiguration.ldap); - const authenticationMethods = AuthenticationMethodsAdapter - .adapt(userConfiguration.authentication_methods); - const totpConfiguration = TOTPAdapter.adapt(userConfiguration.totp); - - return { - port: port, - ldap: ldapConfiguration, - session: { - domain: ObjectPath.get(userConfiguration, "session.domain"), - secret: ObjectPath.get(userConfiguration, "session.secret"), - expiration: get_optional(userConfiguration, "session.expiration", 3600000), // in ms - inactivity: get_optional(userConfiguration, "session.inactivity", undefined), - redis: ObjectPath.get(userConfiguration, "session.redis") - }, - storage: { - local: get_optional(userConfiguration, "storage.local", undefined), - mongo: get_optional(userConfiguration, "storage.mongo", undefined) - }, - logs_level: get_optional(userConfiguration, "logs_level", "info"), - notifier: ObjectPath.get(userConfiguration, "notifier"), - access_control: ACLAdapter.adapt(userConfiguration.access_control), - regulation: userConfiguration.regulation, - authentication_methods: authenticationMethods, - default_redirection_url: userConfiguration.default_redirection_url, - totp: totpConfiguration - }; -} export class ConfigurationParser { - static parse(userConfiguration: UserConfiguration): AppConfiguration { - const errors = Validator.isValid(userConfiguration); - if (errors.length > 0) { - errors.forEach((e: string) => { console.log(e); }); + private static parseTypes(configuration: Configuration): string[] { + const schema = require(Path.resolve(__dirname, "./Configuration.schema.json")); + const ajv = new Ajv({ + allErrors: true, + missingRefs: "fail" + }); + ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-06.json")); + const valid = ajv.validate(schema, configuration); + if (!valid) + return ajv.errors.map( + (e: Ajv.ErrorObject) => { return ajv.errorsText([e]); }); + return []; + } + + static parse(configuration: Configuration): Configuration { + const validationErrors = this.parseTypes(configuration); + if (validationErrors.length > 0) { + validationErrors.forEach((e: string) => { console.log(e); }); throw new Error("Malformed configuration. Please double-check your configuration file."); } - const appConfiguration = adaptFromUserConfiguration(userConfiguration); - const ldapUrl = process.env[LDAP_URL_ENV_VARIABLE]; - if (ldapUrl) - appConfiguration.ldap.url = ldapUrl; + const [newConfiguration, completionErrors] = complete(configuration); - return appConfiguration; + if (completionErrors.length > 0) { + completionErrors.forEach((e: string) => { console.log(e); }); + throw new Error("Malformed configuration. Please double-check your configuration file."); + } + return newConfiguration; } } diff --git a/server/test/SessionConfigurationBuilder.test.ts b/server/src/lib/configuration/SessionConfigurationBuilder.spec.ts similarity index 87% rename from server/test/SessionConfigurationBuilder.test.ts rename to server/src/lib/configuration/SessionConfigurationBuilder.spec.ts index 6fc1359ac..0d5cc11fe 100644 --- a/server/test/SessionConfigurationBuilder.test.ts +++ b/server/src/lib/configuration/SessionConfigurationBuilder.spec.ts @@ -1,15 +1,15 @@ -import { SessionConfigurationBuilder } from "../src/lib/configuration/SessionConfigurationBuilder"; -import { AppConfiguration } from "../src/lib/configuration/Configuration"; -import { GlobalDependencies } from "../types/Dependencies"; +import { SessionConfigurationBuilder } from "./SessionConfigurationBuilder"; +import { Configuration } from "./schema/Configuration"; +import { GlobalDependencies } from "../../../types/Dependencies"; import ExpressSession = require("express-session"); import ConnectRedis = require("connect-redis"); import Sinon = require("sinon"); import Assert = require("assert"); -describe("test session configuration builder", function () { +describe("configuration/SessionConfigurationBuilder", function () { it("should return session options without redis options", function () { - const configuration: AppConfiguration = { + const configuration: Configuration = { access_control: { default_policy: "deny", any: [], @@ -22,9 +22,10 @@ describe("test session configuration builder", function () { ldap: { url: "ldap://ldap", user: "user", + base_dn: "dc=example,dc=com", password: "password", - groups_dn: "ou=groups,dc=example,dc=com", - users_dn: "ou=users,dc=example,dc=com", + additional_groups_dn: "ou=groups", + additional_users_dn: "ou=users", group_name_attribute: "", groups_filter: "", mail_attribute: "", @@ -87,7 +88,7 @@ describe("test session configuration builder", function () { }); it("should return session options with redis options", function () { - const configuration: AppConfiguration = { + const configuration: Configuration = { access_control: { default_policy: "deny", any: [], @@ -101,8 +102,9 @@ describe("test session configuration builder", function () { url: "ldap://ldap", user: "user", password: "password", - groups_dn: "ou=groups,dc=example,dc=com", - users_dn: "ou=users,dc=example,dc=com", + base_dn: "dc=example,dc=com", + additional_groups_dn: "ou=groups", + additional_users_dn: "ou=users", group_name_attribute: "", groups_filter: "", mail_attribute: "", diff --git a/server/src/lib/configuration/SessionConfigurationBuilder.ts b/server/src/lib/configuration/SessionConfigurationBuilder.ts index fa5e4443c..427cec728 100644 --- a/server/src/lib/configuration/SessionConfigurationBuilder.ts +++ b/server/src/lib/configuration/SessionConfigurationBuilder.ts @@ -1,11 +1,11 @@ import ExpressSession = require("express-session"); -import { AppConfiguration } from "./Configuration"; +import { Configuration } from "./schema/Configuration"; import { GlobalDependencies } from "../../../types/Dependencies"; export class SessionConfigurationBuilder { - static build(configuration: AppConfiguration, deps: GlobalDependencies): ExpressSession.SessionOptions { + static build(configuration: Configuration, deps: GlobalDependencies): ExpressSession.SessionOptions { const sessionOptions: ExpressSession.SessionOptions = { secret: configuration.session.secret, resave: false, diff --git a/server/src/lib/configuration/Validator.ts b/server/src/lib/configuration/Validator.ts deleted file mode 100644 index 307ed2bb2..000000000 --- a/server/src/lib/configuration/Validator.ts +++ /dev/null @@ -1,94 +0,0 @@ -import Ajv = require("ajv"); -import Path = require("path"); -import Util = require("util"); -import { - UserConfiguration, StorageConfiguration, - NotifierConfiguration, AuthenticationMethodsConfiguration -} from "./Configuration"; -import { MethodCalculator } from "../authentication/MethodCalculator"; - -function validateSchema(configuration: UserConfiguration): string[] { - const schema = require(Path.resolve(__dirname, "./Configuration.schema.json")); - const ajv = new Ajv({ - allErrors: true, - missingRefs: "fail" - }); - ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-06.json")); - const valid = ajv.validate(schema, configuration); - if (!valid) - return ajv.errors.map( - (e: Ajv.ErrorObject) => { return ajv.errorsText([e]); }); - return []; -} - -function diff(a: string[], b: string[]) { - return a.filter(function(i) {return b.indexOf(i) < 0; }); -} - -function validateUnknownKeys(path: string, obj: any, knownKeys: string[]) { - const keysSet = Object.keys(obj); - - const unknownKeysSet = diff(keysSet, knownKeys); - if (unknownKeysSet.length > 0) { - const unknownKeys = Array.from(unknownKeysSet); - return unknownKeys.map((k: string) => { return Util.format("data.%s has unknown key '%s'", path, k); }); - } - return []; -} - -function validateStorage(storage: any): string[] { - const ERROR = "Storage must be either 'local' or 'mongo'"; - - if (!storage) - return []; - - const errors = validateUnknownKeys("storage", storage, ["local", "mongo"]); - if (errors.length > 0) - return errors; - - if (storage.local && storage.mongo) - return [ERROR]; - - if (!storage.local && !storage.mongo) - return [ERROR]; - - return []; -} - -function validateNotifier(notifier: NotifierConfiguration, - authenticationMethods: AuthenticationMethodsConfiguration): string[] { - const ERROR = "Notifier must be either 'filesystem', 'email' or 'smtp'"; - - if (!notifier) - return []; - - if (!MethodCalculator.isSingleFactorOnlyMode(authenticationMethods)) { - if (Object.keys(notifier).length != 1) - return ["A notifier needs to be declared when server is used with two-factor"]; - - if (notifier && notifier.filesystem && notifier.email && notifier.smtp) - return [ERROR]; - - if (notifier && !notifier.filesystem && !notifier.email && !notifier.smtp) - return [ERROR]; - } - - const errors = validateUnknownKeys("notifier", notifier, ["filesystem", "email", "smtp"]); - if (errors.length > 0) - return errors; - - return []; -} - -export class Validator { - static isValid(configuration: any): string[] { - const schemaErrors = validateSchema(configuration); - const storageErrors = validateStorage(configuration.storage); - const notifierErrors = validateNotifier(configuration.notifier, - configuration.authentication_methods); - - return schemaErrors - .concat(storageErrors) - .concat(notifierErrors); - } -} \ No newline at end of file diff --git a/server/src/lib/configuration/adapters/ACLAdapter.ts b/server/src/lib/configuration/adapters/ACLAdapter.ts deleted file mode 100644 index d9fca60b8..000000000 --- a/server/src/lib/configuration/adapters/ACLAdapter.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { ACLConfiguration } from "../Configuration"; -import { ObjectCloner } from "../../utils/ObjectCloner"; - -const DEFAULT_POLICY = "deny"; - -function adaptDefaultPolicy(configuration: ACLConfiguration) { - if (!configuration.default_policy) - configuration.default_policy = DEFAULT_POLICY; - if (configuration.default_policy != "deny" && configuration.default_policy != "allow") - configuration.default_policy = DEFAULT_POLICY; -} - -function adaptAny(configuration: ACLConfiguration) { - if (!configuration.any || !(configuration.any.constructor === Array)) - configuration.any = []; -} - -function adaptGroups(configuration: ACLConfiguration) { - if (!configuration.groups || !(configuration.groups.constructor === Object)) - configuration.groups = {}; -} - -function adaptUsers(configuration: ACLConfiguration) { - if (!configuration.users || !(configuration.users.constructor === Object)) - configuration.users = {}; -} - -export class ACLAdapter { - static adapt(configuration: ACLConfiguration): ACLConfiguration { - if (!configuration) return; - - const newConfiguration: ACLConfiguration = ObjectCloner.clone(configuration); - adaptDefaultPolicy(newConfiguration); - adaptAny(newConfiguration); - adaptGroups(newConfiguration); - adaptUsers(newConfiguration); - return newConfiguration; - } -} \ No newline at end of file diff --git a/server/src/lib/configuration/adapters/AuthenticationMethodsAdapter.ts b/server/src/lib/configuration/adapters/AuthenticationMethodsAdapter.ts deleted file mode 100644 index 462d6bc65..000000000 --- a/server/src/lib/configuration/adapters/AuthenticationMethodsAdapter.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { AuthenticationMethodsConfiguration } from "../Configuration"; -import { ObjectCloner } from "../../utils/ObjectCloner"; - -function clone(obj: any): any { - return JSON.parse(JSON.stringify(obj)); -} - -export class AuthenticationMethodsAdapter { - static adapt(authentication_methods: AuthenticationMethodsConfiguration) - : AuthenticationMethodsConfiguration { - if (!authentication_methods) { - return { - default_method: "two_factor", - per_subdomain_methods: {} - }; - } - - const newAuthMethods: AuthenticationMethodsConfiguration - = ObjectCloner.clone(authentication_methods); - - if (!newAuthMethods.default_method) - newAuthMethods.default_method = "two_factor"; - - if (!newAuthMethods.per_subdomain_methods || - newAuthMethods.per_subdomain_methods.constructor !== Object) - newAuthMethods.per_subdomain_methods = {}; - - return newAuthMethods; - } -} diff --git a/server/src/lib/configuration/adapters/TOTPAdapter.ts b/server/src/lib/configuration/adapters/TOTPAdapter.ts deleted file mode 100644 index 198c6ddb2..000000000 --- a/server/src/lib/configuration/adapters/TOTPAdapter.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { TOTPConfiguration } from "../Configuration"; -import { ObjectCloner } from "../../utils/ObjectCloner"; - -const DEFAULT_ISSUER = "authelia.com"; - -export class TOTPAdapter { - static adapt(configuration: TOTPConfiguration): TOTPConfiguration { - const newConfiguration = { - issuer: DEFAULT_ISSUER - }; - - if (!configuration) - return newConfiguration; - - if (configuration && configuration.issuer) - newConfiguration.issuer = configuration.issuer; - - return newConfiguration; - } -} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/AclConfiguration.spec.ts b/server/src/lib/configuration/schema/AclConfiguration.spec.ts new file mode 100644 index 000000000..8c5ef3444 --- /dev/null +++ b/server/src/lib/configuration/schema/AclConfiguration.spec.ts @@ -0,0 +1,14 @@ +import { ACLConfiguration, complete } from "./AclConfiguration"; +import Assert = require("assert"); + +describe("configuration/schema/AclConfiguration", function() { + it("should complete ACLConfiguration", function() { + const configuration: ACLConfiguration = {}; + const newConfiguration = complete(configuration); + + Assert.deepEqual(newConfiguration.default_policy, "allow"); + Assert.deepEqual(newConfiguration.any, []); + Assert.deepEqual(newConfiguration.groups, {}); + Assert.deepEqual(newConfiguration.users, {}); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/AclConfiguration.ts b/server/src/lib/configuration/schema/AclConfiguration.ts new file mode 100644 index 000000000..bba3c4dca --- /dev/null +++ b/server/src/lib/configuration/schema/AclConfiguration.ts @@ -0,0 +1,42 @@ + +export type ACLPolicy = "deny" | "allow"; + +export type ACLRule = { + domain: string; + policy: ACLPolicy; + resources?: string[]; +}; + +export type ACLDefaultRules = ACLRule[]; +export type ACLGroupsRules = { [group: string]: ACLRule[]; }; +export type ACLUsersRules = { [user: string]: ACLRule[]; }; + +export interface ACLConfiguration { + default_policy?: ACLPolicy; + any?: ACLDefaultRules; + groups?: ACLGroupsRules; + users?: ACLUsersRules; +} + +export function complete(configuration: ACLConfiguration): ACLConfiguration { + const newConfiguration: ACLConfiguration = (configuration) + ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.default_policy) { + newConfiguration.default_policy = "allow"; + } + + if (!newConfiguration.any) { + newConfiguration.any = []; + } + + if (!newConfiguration.groups) { + newConfiguration.groups = {}; + } + + if (!newConfiguration.users) { + newConfiguration.users = {}; + } + + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/AuthenticationMethodsConfiguration.spec.ts b/server/src/lib/configuration/schema/AuthenticationMethodsConfiguration.spec.ts new file mode 100644 index 000000000..f39ae671b --- /dev/null +++ b/server/src/lib/configuration/schema/AuthenticationMethodsConfiguration.spec.ts @@ -0,0 +1,12 @@ +import Assert = require("assert"); +import { AuthenticationMethodsConfiguration, complete } from "./AuthenticationMethodsConfiguration"; + +describe("configuration/schema/AuthenticationMethodsConfiguration", function() { + it("should ensure at least one key is provided", function() { + const configuration: AuthenticationMethodsConfiguration = {}; + const newConfiguration = complete(configuration); + + Assert.deepEqual(newConfiguration.default_method, "two_factor"); + Assert.deepEqual(newConfiguration.per_subdomain_methods, []); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/AuthenticationMethodsConfiguration.ts b/server/src/lib/configuration/schema/AuthenticationMethodsConfiguration.ts new file mode 100644 index 000000000..1b454d078 --- /dev/null +++ b/server/src/lib/configuration/schema/AuthenticationMethodsConfiguration.ts @@ -0,0 +1,21 @@ +export type AuthenticationMethod = "two_factor" | "single_factor"; +export type AuthenticationMethodPerSubdomain = { [subdomain: string]: AuthenticationMethod }; + +export interface AuthenticationMethodsConfiguration { + default_method?: AuthenticationMethod; + per_subdomain_methods?: AuthenticationMethodPerSubdomain; +} + +export function complete(configuration: AuthenticationMethodsConfiguration): AuthenticationMethodsConfiguration { + const newConfiguration: AuthenticationMethodsConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.default_method) { + newConfiguration.default_method = "two_factor"; + } + + if (!newConfiguration.per_subdomain_methods) { + newConfiguration.per_subdomain_methods = {}; + } + + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/Configuration.ts b/server/src/lib/configuration/schema/Configuration.ts new file mode 100644 index 000000000..117367f16 --- /dev/null +++ b/server/src/lib/configuration/schema/Configuration.ts @@ -0,0 +1,55 @@ +import { ACLConfiguration, complete as AclConfigurationComplete } from "./AclConfiguration"; +import { AuthenticationMethodsConfiguration, complete as AuthenticationMethodsConfigurationComplete } from "./AuthenticationMethodsConfiguration"; +import { LdapConfiguration, complete as LdapConfigurationComplete } from "./LdapConfiguration"; +import { NotifierConfiguration, complete as NotifierConfigurationComplete } from "./NotifierConfiguration"; +import { RegulationConfiguration, complete as RegulationConfigurationComplete } from "./RegulationConfiguration"; +import { SessionConfiguration, complete as SessionConfigurationComplete } from "./SessionConfiguration"; +import { StorageConfiguration, complete as StorageConfigurationComplete } from "./StorageConfiguration"; +import { TotpConfiguration, complete as TotpConfigurationComplete } from "./TotpConfiguration"; +import { MethodCalculator } from "../../authentication/MethodCalculator"; + +export interface Configuration { + access_control?: ACLConfiguration; + ldap: LdapConfiguration; + authentication_methods?: AuthenticationMethodsConfiguration; + default_redirection_url?: string; + logs_level?: string; + notifier?: NotifierConfiguration; + port?: number; + regulation?: RegulationConfiguration; + session?: SessionConfiguration; + storage?: StorageConfiguration; + totp?: TotpConfiguration; +} + +export function complete(configuration: Configuration): [Configuration, string[]] { + const newConfiguration: Configuration = JSON.parse(JSON.stringify(configuration)); + const errors: string[] = []; + + newConfiguration.access_control = AclConfigurationComplete(newConfiguration.access_control); + newConfiguration.ldap = LdapConfigurationComplete(newConfiguration.ldap); + + newConfiguration.authentication_methods = AuthenticationMethodsConfigurationComplete(newConfiguration.authentication_methods); + + if (!newConfiguration.logs_level) { + newConfiguration.logs_level = "info"; + } + + // In single factor mode, notifier section is optional. + if (!MethodCalculator.isSingleFactorOnlyMode(newConfiguration.authentication_methods)) { + const [notifier, error] = NotifierConfigurationComplete(newConfiguration.notifier); + newConfiguration.notifier = notifier; + if (error) errors.push(error); + } + + if (!newConfiguration.port) { + newConfiguration.port = 8080; + } + + newConfiguration.regulation = RegulationConfigurationComplete(newConfiguration.regulation); + newConfiguration.session = SessionConfigurationComplete(newConfiguration.session); + newConfiguration.storage = StorageConfigurationComplete(newConfiguration.storage); + newConfiguration.totp = TotpConfigurationComplete(newConfiguration.totp); + + return [newConfiguration, errors]; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/LdapConfiguration.spec.ts b/server/src/lib/configuration/schema/LdapConfiguration.spec.ts new file mode 100644 index 000000000..cc73d1085 --- /dev/null +++ b/server/src/lib/configuration/schema/LdapConfiguration.spec.ts @@ -0,0 +1,25 @@ +import Assert = require("assert"); +import { LdapConfiguration, complete } from "./LdapConfiguration"; + +describe("configuration/schema/AuthenticationMethodsConfiguration", function() { + it("should ensure at least one key is provided", function() { + const configuration: LdapConfiguration = { + url: "ldap.example.com", + base_dn: "dc=example,dc=com", + user: "admin", + password: "password" + }; + const newConfiguration = complete(configuration); + + Assert.deepEqual(newConfiguration, { + url: "ldap.example.com", + base_dn: "dc=example,dc=com", + user: "admin", + password: "password", + users_filter: "cn={0}", + group_name_attribute: "cn", + groups_filter: "member={dn}", + mail_attribute: "mail" + }); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/LdapConfiguration.ts b/server/src/lib/configuration/schema/LdapConfiguration.ts new file mode 100644 index 000000000..5dacb9390 --- /dev/null +++ b/server/src/lib/configuration/schema/LdapConfiguration.ts @@ -0,0 +1,40 @@ +import Util = require("util"); + +export interface LdapConfiguration { + url: string; + base_dn: string; + + additional_users_dn?: string; + users_filter?: string; + + additional_groups_dn?: string; + groups_filter?: string; + + group_name_attribute?: string; + mail_attribute?: string; + + user: string; // admin username + password: string; // admin password +} + +export function complete(configuration: LdapConfiguration): LdapConfiguration { + const newConfiguration: LdapConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.users_filter) { + newConfiguration.users_filter = "cn={0}"; + } + + if (!newConfiguration.groups_filter) { + newConfiguration.groups_filter = "member={dn}"; + } + + if (!newConfiguration.group_name_attribute) { + newConfiguration.group_name_attribute = "cn"; + } + + if (!newConfiguration.mail_attribute) { + newConfiguration.mail_attribute = "mail"; + } + + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/NotifierConfiguration.spec.ts b/server/src/lib/configuration/schema/NotifierConfiguration.spec.ts new file mode 100644 index 000000000..3ffe940c6 --- /dev/null +++ b/server/src/lib/configuration/schema/NotifierConfiguration.spec.ts @@ -0,0 +1,31 @@ +import Assert = require("assert"); +import { NotifierConfiguration, complete } from "./NotifierConfiguration"; + +describe("configuration/schema/NotifierConfiguration", function() { + it("should ensure at least one key is provided", function() { + const configuration: NotifierConfiguration = {}; + const [newConfiguration, error] = complete(configuration); + + Assert.equal(error, "Notifier must have one of the following keys: 'filesystem', 'email' or 'smtp'"); + }); + + it("should ensure there is no more than one key", function() { + const configuration: NotifierConfiguration = { + smtp: { + host: "smtp.example.com", + port: 25, + secure: false, + sender: "test@example.com" + }, + email: { + username: "test", + password: "test", + sender: "test@example.com", + service: "gmail" + } + }; + const [newConfiguration, error] = complete(configuration); + + Assert.equal(error, "Notifier must have one of the following keys: 'filesystem', 'email' or 'smtp'"); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/NotifierConfiguration.ts b/server/src/lib/configuration/schema/NotifierConfiguration.ts new file mode 100644 index 000000000..497220ef5 --- /dev/null +++ b/server/src/lib/configuration/schema/NotifierConfiguration.ts @@ -0,0 +1,42 @@ + +export interface EmailNotifierConfiguration { + username: string; + password: string; + sender: string; + service: string; +} + +export interface SmtpNotifierConfiguration { + username?: string; + password?: string; + host: string; + port: number; + secure: boolean; + sender: string; +} + +export interface FileSystemNotifierConfiguration { + filename: string; +} + +export interface NotifierConfiguration { + email?: EmailNotifierConfiguration; + smtp?: SmtpNotifierConfiguration; + filesystem?: FileSystemNotifierConfiguration; +} + +export function complete(configuration: NotifierConfiguration): [NotifierConfiguration, string] { + const newConfiguration: NotifierConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + const ERROR = "Notifier must have one of the following keys: 'filesystem', 'email' or 'smtp'"; + + if (Object.keys(newConfiguration).length != 1) + return [newConfiguration, ERROR]; + + const key = Object.keys(newConfiguration)[0]; + + if (key != "filesystem" && key != "smtp" && key != "email") + return [newConfiguration, ERROR]; + + return [newConfiguration, undefined]; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/RegulationConfiguration.spec.ts b/server/src/lib/configuration/schema/RegulationConfiguration.spec.ts new file mode 100644 index 000000000..dce2caf4e --- /dev/null +++ b/server/src/lib/configuration/schema/RegulationConfiguration.spec.ts @@ -0,0 +1,13 @@ +import Assert = require("assert"); +import { RegulationConfiguration, complete } from "./RegulationConfiguration"; + +describe("configuration/schema/RegulationConfiguration", function() { + it("should return default regulation configuration", function() { + const configuration: RegulationConfiguration = {}; + const newConfiguration = complete(configuration); + + Assert.equal(newConfiguration.ban_time, 300); + Assert.equal(newConfiguration.find_time, 120); + Assert.equal(newConfiguration.max_retries, 3); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/RegulationConfiguration.ts b/server/src/lib/configuration/schema/RegulationConfiguration.ts new file mode 100644 index 000000000..117463f43 --- /dev/null +++ b/server/src/lib/configuration/schema/RegulationConfiguration.ts @@ -0,0 +1,23 @@ +export interface RegulationConfiguration { + max_retries?: number; + find_time?: number; + ban_time?: number; +} + +export function complete(configuration: RegulationConfiguration): RegulationConfiguration { + const newConfiguration: RegulationConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.max_retries) { + newConfiguration.max_retries = 3; + } + + if (!newConfiguration.find_time) { + newConfiguration.find_time = 120; // seconds + } + + if (!newConfiguration.ban_time) { + newConfiguration.ban_time = 300; // seconds + } + + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/SessionConfiguration.spec.ts b/server/src/lib/configuration/schema/SessionConfiguration.spec.ts new file mode 100644 index 000000000..b63e7eede --- /dev/null +++ b/server/src/lib/configuration/schema/SessionConfiguration.spec.ts @@ -0,0 +1,15 @@ +import Assert = require("assert"); +import { SessionConfiguration, complete } from "./SessionConfiguration"; + +describe("configuration/schema/SessionConfiguration", function() { + it("should return default regulation configuration", function() { + const configuration: SessionConfiguration = { + domain: "example.com", + secret: "unsecure_secret" + }; + const newConfiguration = complete(configuration); + + Assert.equal(newConfiguration.expiration, 3600000); + Assert.equal(newConfiguration.inactivity, undefined); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/SessionConfiguration.ts b/server/src/lib/configuration/schema/SessionConfiguration.ts new file mode 100644 index 000000000..e628cb0d1 --- /dev/null +++ b/server/src/lib/configuration/schema/SessionConfiguration.ts @@ -0,0 +1,26 @@ +export interface SessionRedisOptions { + host: string; + port: number; +} + +export interface SessionConfiguration { + domain: string; + secret: string; + expiration?: number; + inactivity?: number; + redis?: SessionRedisOptions; +} + +export function complete(configuration: SessionConfiguration): SessionConfiguration { + const newConfiguration: SessionConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.expiration) { + newConfiguration.expiration = 3600000; // 1 hour + } + + if (!newConfiguration.inactivity) { + newConfiguration.inactivity = undefined; // disabled + } + + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/StorageConfiguration.spec.ts b/server/src/lib/configuration/schema/StorageConfiguration.spec.ts new file mode 100644 index 000000000..9d02a11b6 --- /dev/null +++ b/server/src/lib/configuration/schema/StorageConfiguration.spec.ts @@ -0,0 +1,15 @@ +import Assert = require("assert"); +import { StorageConfiguration, complete } from "./StorageConfiguration"; + +describe("configuration/schema/StorageConfiguration", function() { + it("should return default regulation configuration", function() { + const configuration: StorageConfiguration = {}; + const newConfiguration = complete(configuration); + + Assert.deepEqual(newConfiguration, { + local: { + in_memory: true + } + }); + }); +}); \ No newline at end of file diff --git a/server/src/lib/configuration/schema/StorageConfiguration.ts b/server/src/lib/configuration/schema/StorageConfiguration.ts new file mode 100644 index 000000000..9cbc6d170 --- /dev/null +++ b/server/src/lib/configuration/schema/StorageConfiguration.ts @@ -0,0 +1,25 @@ +export interface MongoStorageConfiguration { + url: string; + database: string; +} + +export interface LocalStorageConfiguration { + path?: string; + in_memory?: boolean; +} + +export interface StorageConfiguration { + local?: LocalStorageConfiguration; + mongo?: MongoStorageConfiguration; +} + +export function complete(configuration: StorageConfiguration): StorageConfiguration { + const newConfiguration: StorageConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.local && !newConfiguration.mongo) { + newConfiguration.local = { + in_memory: true + }; + } + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/TotpConfiguration.ts b/server/src/lib/configuration/schema/TotpConfiguration.ts new file mode 100644 index 000000000..683135639 --- /dev/null +++ b/server/src/lib/configuration/schema/TotpConfiguration.ts @@ -0,0 +1,13 @@ +export interface TotpConfiguration { + issuer: string; +} + +export function complete(configuration: TotpConfiguration): TotpConfiguration { + const newConfiguration: TotpConfiguration = (configuration) ? JSON.parse(JSON.stringify(configuration)) : {}; + + if (!newConfiguration.issuer) { + newConfiguration.issuer = "authelia.com"; + } + + return newConfiguration; +} \ No newline at end of file diff --git a/server/src/lib/configuration/schema/UserDatabaseConfiguration.ts b/server/src/lib/configuration/schema/UserDatabaseConfiguration.ts new file mode 100644 index 000000000..8008b4833 --- /dev/null +++ b/server/src/lib/configuration/schema/UserDatabaseConfiguration.ts @@ -0,0 +1,9 @@ + +export interface UserInfo { + username: string; + password_hash: string; + email: string; + groups?: string[]; +} + +export type UserDatabaseConfiguration = UserInfo[]; \ No newline at end of file diff --git a/server/test/connectors/mongo/MongoClient.test.ts b/server/src/lib/connectors/mongo/MongoClient.spec.ts similarity index 89% rename from server/test/connectors/mongo/MongoClient.test.ts rename to server/src/lib/connectors/mongo/MongoClient.spec.ts index 37ad0c4d6..355e6f028 100644 --- a/server/test/connectors/mongo/MongoClient.test.ts +++ b/server/src/lib/connectors/mongo/MongoClient.spec.ts @@ -1,9 +1,9 @@ import Assert = require("assert"); import Sinon = require("sinon"); import MongoDB = require("mongodb"); -import { MongoClient } from "../../../src/lib/connectors/mongo/MongoClient"; +import { MongoClient } from "./MongoClient"; -describe("MongoClient", function () { +describe("connectors/mongo/MongoClient", function () { let mongoClientConnectStub: Sinon.SinonStub; let mongoDatabase: any; let mongoDatabaseCollectionStub: Sinon.SinonStub; diff --git a/server/test/mocks/connectors/mongo/MongoClientStub.ts b/server/src/lib/connectors/mongo/MongoClientStub.spec.ts similarity index 100% rename from server/test/mocks/connectors/mongo/MongoClientStub.ts rename to server/src/lib/connectors/mongo/MongoClientStub.spec.ts diff --git a/server/test/connectors/mongo/MongoConnector.test.ts b/server/src/lib/connectors/mongo/MongoConnector.spec.ts similarity index 87% rename from server/test/connectors/mongo/MongoConnector.test.ts rename to server/src/lib/connectors/mongo/MongoConnector.spec.ts index 8aebaa9b0..a18026977 100644 --- a/server/test/connectors/mongo/MongoConnector.test.ts +++ b/server/src/lib/connectors/mongo/MongoConnector.spec.ts @@ -2,10 +2,10 @@ import Assert = require("assert"); import Sinon = require("sinon"); import MongoDB = require("mongodb"); import BluebirdPromise = require("bluebird"); -import { IMongoClient } from "../../../src/lib/connectors/mongo/IMongoClient"; -import { MongoConnector } from "../../../src/lib/connectors/mongo/MongoConnector"; +import { IMongoClient } from "./IMongoClient"; +import { MongoConnector } from "./MongoConnector"; -describe("MongoConnector", function () { +describe("connectors/mongo/MongoConnector", function () { let mongoClientConnectStub: Sinon.SinonStub; describe("create", function () { diff --git a/server/test/connectors/mongo/MongoConnectorFactory.test.ts b/server/src/lib/connectors/mongo/MongoConnectorFactory.spec.ts similarity index 65% rename from server/test/connectors/mongo/MongoConnectorFactory.test.ts rename to server/src/lib/connectors/mongo/MongoConnectorFactory.spec.ts index 9d5d9cab4..d82570a8c 100644 --- a/server/test/connectors/mongo/MongoConnectorFactory.test.ts +++ b/server/src/lib/connectors/mongo/MongoConnectorFactory.spec.ts @@ -1,7 +1,7 @@ import Assert = require("assert"); -import { MongoConnectorFactory } from "../../../src/lib/connectors/mongo/MongoConnectorFactory"; +import { MongoConnectorFactory } from "./MongoConnectorFactory"; -describe("MongoConnectorFactory", function () { +describe("connectors/mongo/MongoConnectorFactory", function () { describe("create", function () { it("should create a connector", function () { const factory = new MongoConnectorFactory(); diff --git a/server/test/ldap/Authenticator.test.ts b/server/src/lib/ldap/Authenticator.spec.ts similarity index 92% rename from server/test/ldap/Authenticator.test.ts rename to server/src/lib/ldap/Authenticator.spec.ts index 5300d352e..2a2297569 100644 --- a/server/test/ldap/Authenticator.test.ts +++ b/server/src/lib/ldap/Authenticator.spec.ts @@ -1,16 +1,16 @@ -import { Authenticator } from "../../src/lib/ldap/Authenticator"; -import { LdapConfiguration } from "../../src/lib/configuration/Configuration"; +import { Authenticator } from "./Authenticator"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import { ClientFactoryStub } from "../mocks/ldap/ClientFactoryStub"; -import { ClientStub } from "../mocks/ldap/ClientStub"; +import { ClientFactoryStub } from "./ClientFactoryStub.spec"; +import { ClientStub } from "./ClientStub.spec"; -describe("test ldap authentication", function () { +describe("ldap/Authenticator", function () { const USERNAME = "username"; const PASSWORD = "password"; @@ -31,9 +31,10 @@ describe("test ldap authentication", function () { ldapConfig = { url: "http://localhost:324", - users_dn: "ou=users,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", users_filter: "cn={0}", - groups_dn: "ou=groups,dc=example,dc=com", groups_filter: "member={0}", mail_attribute: "mail", group_name_attribute: "cn", diff --git a/server/src/lib/ldap/Authenticator.ts b/server/src/lib/ldap/Authenticator.ts index a13c68a2f..d804ee590 100644 --- a/server/src/lib/ldap/Authenticator.ts +++ b/server/src/lib/ldap/Authenticator.ts @@ -6,7 +6,7 @@ import { IClientFactory } from "./IClientFactory"; import { GroupsAndEmails } from "./IClient"; import { IAuthenticator } from "./IAuthenticator"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import { EmailsAndGroupsRetriever } from "./EmailsAndGroupsRetriever"; diff --git a/server/test/mocks/ldap/AuthenticatorStub.ts b/server/src/lib/ldap/AuthenticatorStub.spec.ts similarity index 87% rename from server/test/mocks/ldap/AuthenticatorStub.ts rename to server/src/lib/ldap/AuthenticatorStub.spec.ts index 4102b0fe8..1863e45bd 100644 --- a/server/test/mocks/ldap/AuthenticatorStub.ts +++ b/server/src/lib/ldap/AuthenticatorStub.spec.ts @@ -1,6 +1,6 @@ import BluebirdPromise = require("bluebird"); import { IAuthenticator } from "../../../src/lib/ldap/IAuthenticator"; -import { GroupsAndEmails } from "../../../src/lib/ldap/IClient"; +import { GroupsAndEmails } from "./IClient"; import Sinon = require("sinon"); export class AuthenticatorStub implements IAuthenticator { diff --git a/server/test/ldap/Client.test.ts b/server/src/lib/ldap/Client.spec.ts similarity index 86% rename from server/test/ldap/Client.test.ts rename to server/src/lib/ldap/Client.spec.ts index 73073fa2a..b5f705301 100644 --- a/server/test/ldap/Client.test.ts +++ b/server/src/lib/ldap/Client.spec.ts @@ -1,15 +1,15 @@ -import { LdapConfiguration } from "../../src/lib/configuration/Configuration"; -import { Client } from "../../src/lib/ldap/Client"; -import { LdapClientFactoryStub } from "../mocks/ldap/LdapClientFactoryStub"; -import { LdapClientStub } from "../mocks/ldap/LdapClientStub"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; +import { Client } from "./Client"; +import { LdapClientFactoryStub } from "./LdapClientFactoryStub.spec"; +import { LdapClientStub } from "./LdapClientStub.spec"; import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); import Winston = require("winston"); -describe("test authelia ldap client", function () { +describe("ldap/Client", function () { const USERNAME = "username"; const ADMIN_USER_DN = "cn=admin,dc=example,dc=com"; const ADMIN_PASSWORD = "password"; @@ -17,9 +17,10 @@ describe("test authelia ldap client", function () { it("should replace {0} by username when searching for groups in LDAP", function () { const options: LdapConfiguration = { url: "ldap://ldap", - users_dn: "ou=users,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", users_filter: "cn={0}", - groups_dn: "ou=groups,dc=example,dc=com", groups_filter: "member=cn={0},ou=users,dc=example,dc=com", group_name_attribute: "cn", mail_attribute: "mail", @@ -46,9 +47,10 @@ describe("test authelia ldap client", function () { const USER_DN = "cn=user1,ou=users,dc=example,dc=com"; const options: LdapConfiguration = { url: "ldap://ldap", - users_dn: "ou=users,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", users_filter: "cn={0}", - groups_dn: "ou=groups,dc=example,dc=com", groups_filter: "member={dn}", group_name_attribute: "cn", mail_attribute: "mail", @@ -91,9 +93,10 @@ describe("test authelia ldap client", function () { const USER_DN = "cn=user1,ou=users,dc=example,dc=com"; const options: LdapConfiguration = { url: "ldap://ldap", - users_dn: "ou=users,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", users_filter: "cn={0}", - groups_dn: "ou=groups,dc=example,dc=com", groups_filter: "member={dn}", group_name_attribute: "cn", mail_attribute: "custom_mail", diff --git a/server/src/lib/ldap/Client.ts b/server/src/lib/ldap/Client.ts index 4fa5ae981..7ca215bfb 100644 --- a/server/src/lib/ldap/Client.ts +++ b/server/src/lib/ldap/Client.ts @@ -4,7 +4,7 @@ import { EventEmitter } from "events"; import { IClient, GroupsAndEmails } from "./IClient"; import { ILdapClient } from "./ILdapClient"; import { ILdapClientFactory } from "./ILdapClientFactory"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import { Winston } from "../../../types/Dependencies"; import Util = require("util"); import { HashGenerator } from "../utils/HashGenerator"; @@ -16,6 +16,9 @@ export class Client implements IClient { private logger: Winston; private options: LdapConfiguration; + private groupsSearchBase: string; + private usersSearchBase: string; + constructor(userDN: string, password: string, options: LdapConfiguration, ldapClientFactory: ILdapClientFactory, logger: Winston) { this.options = options; @@ -23,6 +26,14 @@ export class Client implements IClient { this.userDN = userDN; this.password = password; this.ldapClient = ldapClientFactory.create(); + + this.groupsSearchBase = (this.options.additional_groups_dn) + ? Util.format("%s,%s", this.options.additional_groups_dn, this.options.base_dn) + : this.options.base_dn; + + this.usersSearchBase = (this.options.additional_users_dn) + ? Util.format("%s,%s", this.options.additional_users_dn, this.options.base_dn) + : this.options.base_dn; } open(): BluebirdPromise { @@ -64,7 +75,7 @@ export class Client implements IClient { attributes: [that.options.group_name_attribute], filter: groupsFilter }; - return that.ldapClient.searchAsync(that.options.groups_dn, query); + return that.ldapClient.searchAsync(that.groupsSearchBase, query); }) .then(function (docs: { cn: string }[]) { const groups = docs.map((doc: any) => { return doc.cn; }); @@ -85,7 +96,7 @@ export class Client implements IClient { }; that.logger.debug("LDAP: searching for user dn of %s", username); - return that.ldapClient.searchAsync(this.options.users_dn, query) + return that.ldapClient.searchAsync(this.usersSearchBase, query) .then(function (users: { dn: string }[]) { if (users.length > 0) { that.logger.debug("LDAP: retrieved user dn is %s", users[0].dn); diff --git a/server/src/lib/ldap/ClientFactory.ts b/server/src/lib/ldap/ClientFactory.ts index bbef51dae..539e37f8a 100644 --- a/server/src/lib/ldap/ClientFactory.ts +++ b/server/src/lib/ldap/ClientFactory.ts @@ -3,7 +3,7 @@ import { IClient } from "./IClient"; import { Client } from "./Client"; import { SanitizedClient } from "./SanitizedClient"; import { ILdapClientFactory } from "./ILdapClientFactory"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import Ldapjs = require("ldapjs"); import Winston = require("winston"); diff --git a/server/test/mocks/ldap/ClientFactoryStub.ts b/server/src/lib/ldap/ClientFactoryStub.spec.ts similarity index 100% rename from server/test/mocks/ldap/ClientFactoryStub.ts rename to server/src/lib/ldap/ClientFactoryStub.spec.ts diff --git a/server/test/mocks/ldap/ClientStub.ts b/server/src/lib/ldap/ClientStub.spec.ts similarity index 94% rename from server/test/mocks/ldap/ClientStub.ts rename to server/src/lib/ldap/ClientStub.spec.ts index 79e50dafc..fabcebe7a 100644 --- a/server/test/mocks/ldap/ClientStub.ts +++ b/server/src/lib/ldap/ClientStub.spec.ts @@ -1,6 +1,6 @@ import BluebirdPromise = require("bluebird"); -import { IClient, GroupsAndEmails } from "../../../src/lib/ldap/IClient"; +import { IClient, GroupsAndEmails } from "./IClient"; import Sinon = require("sinon"); export class ClientStub implements IClient { diff --git a/server/src/lib/ldap/EmailsAndGroupsRetriever.ts b/server/src/lib/ldap/EmailsAndGroupsRetriever.ts index f17f0368f..0c4f1441f 100644 --- a/server/src/lib/ldap/EmailsAndGroupsRetriever.ts +++ b/server/src/lib/ldap/EmailsAndGroupsRetriever.ts @@ -3,7 +3,7 @@ import exceptions = require("../Exceptions"); import ldapjs = require("ldapjs"); import { Client } from "./Client"; import { IClientFactory } from "./IClientFactory"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import { GroupsAndEmails } from "./IClient"; diff --git a/server/test/ldap/EmailsRetriever.test.ts b/server/src/lib/ldap/EmailsRetriever.spec.ts similarity index 84% rename from server/test/ldap/EmailsRetriever.test.ts rename to server/src/lib/ldap/EmailsRetriever.spec.ts index fcc8846d3..83bd5e77b 100644 --- a/server/test/ldap/EmailsRetriever.test.ts +++ b/server/src/lib/ldap/EmailsRetriever.spec.ts @@ -1,15 +1,15 @@ -import { EmailsRetriever } from "../../src/lib/ldap/EmailsRetriever"; -import { LdapConfiguration } from "../../src/lib/configuration/Configuration"; +import { EmailsRetriever } from "./EmailsRetriever"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import { ClientFactoryStub } from "../mocks/ldap/ClientFactoryStub"; -import { ClientStub } from "../mocks/ldap/ClientStub"; +import { ClientFactoryStub } from "./ClientFactoryStub.spec"; +import { ClientStub } from "./ClientStub.spec"; -describe("test emails retriever", function () { +describe("ldap/EmailsRetriever", function () { const USERNAME = "username"; const ADMIN_USER_DN = "cn=admin,dc=example,dc=com"; const ADMIN_PASSWORD = "password"; @@ -28,8 +28,9 @@ describe("test emails retriever", function () { url: "http://ldap", user: ADMIN_USER_DN, password: ADMIN_PASSWORD, - users_dn: "ou=users,dc=example,dc=com", - groups_dn: "ou=groups,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", group_name_attribute: "cn", groups_filter: "cn={0}", mail_attribute: "mail", diff --git a/server/src/lib/ldap/EmailsRetriever.ts b/server/src/lib/ldap/EmailsRetriever.ts index 34a93a750..21a38ed13 100644 --- a/server/src/lib/ldap/EmailsRetriever.ts +++ b/server/src/lib/ldap/EmailsRetriever.ts @@ -5,7 +5,7 @@ import { Client } from "./Client"; import { IClientFactory } from "./IClientFactory"; import { IEmailsRetriever } from "./IEmailsRetriever"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; export class EmailsRetriever implements IEmailsRetriever { diff --git a/server/test/mocks/ldap/EmailsRetrieverStub.ts b/server/src/lib/ldap/EmailsRetrieverStub.spec.ts similarity index 73% rename from server/test/mocks/ldap/EmailsRetrieverStub.ts rename to server/src/lib/ldap/EmailsRetrieverStub.spec.ts index 0e2b87546..442edea00 100644 --- a/server/test/mocks/ldap/EmailsRetrieverStub.ts +++ b/server/src/lib/ldap/EmailsRetrieverStub.spec.ts @@ -1,6 +1,6 @@ import BluebirdPromise = require("bluebird"); -import { IClient } from "../../../src/lib/ldap/IClient"; -import { IEmailsRetriever } from "../../../src/lib/ldap/IEmailsRetriever"; +import { IClient } from "./IClient"; +import { IEmailsRetriever } from "./IEmailsRetriever"; import Sinon = require("sinon"); export class EmailsRetrieverStub implements IEmailsRetriever { diff --git a/server/test/ldap/InputsSanitizer.test.ts b/server/src/lib/ldap/InputsSanitizer.spec.ts similarity index 90% rename from server/test/ldap/InputsSanitizer.test.ts rename to server/src/lib/ldap/InputsSanitizer.spec.ts index d991d0cd8..791d390b0 100644 --- a/server/test/ldap/InputsSanitizer.test.ts +++ b/server/src/lib/ldap/InputsSanitizer.spec.ts @@ -1,7 +1,7 @@ import Assert = require("assert"); -import { InputsSanitizer } from "../../src/lib/ldap/InputsSanitizer"; +import { InputsSanitizer } from "./InputsSanitizer"; -describe("test InputsSanitizer", function () { +describe("ldap/InputsSanitizer", function () { it("should fail when special characters are used", function () { Assert.throws(() => { InputsSanitizer.sanitize("ab,c"); }, Error); Assert.throws(() => { InputsSanitizer.sanitize("a\\bc"); }, Error); diff --git a/server/src/lib/ldap/LdapClientFactory.ts b/server/src/lib/ldap/LdapClientFactory.ts index 39977808f..6e1fe2920 100644 --- a/server/src/lib/ldap/LdapClientFactory.ts +++ b/server/src/lib/ldap/LdapClientFactory.ts @@ -1,7 +1,7 @@ import { ILdapClientFactory } from "./ILdapClientFactory"; import { ILdapClient } from "./ILdapClient"; import { LdapClient } from "./LdapClient"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import Ldapjs = require("ldapjs"); diff --git a/server/test/mocks/ldap/LdapClientFactoryStub.ts b/server/src/lib/ldap/LdapClientFactoryStub.spec.ts similarity index 67% rename from server/test/mocks/ldap/LdapClientFactoryStub.ts rename to server/src/lib/ldap/LdapClientFactoryStub.spec.ts index 01c3573e6..31f26149f 100644 --- a/server/test/mocks/ldap/LdapClientFactoryStub.ts +++ b/server/src/lib/ldap/LdapClientFactoryStub.spec.ts @@ -1,7 +1,7 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); -import { ILdapClientFactory } from "../../../src/lib/ldap/ILdapClientFactory"; -import { ILdapClient } from "../../../src/lib/ldap/ILdapClient"; +import { ILdapClientFactory } from "./ILdapClientFactory"; +import { ILdapClient } from "./ILdapClient"; export class LdapClientFactoryStub implements ILdapClientFactory { createStub: Sinon.SinonStub; diff --git a/server/test/mocks/ldap/LdapClientStub.ts b/server/src/lib/ldap/LdapClientStub.spec.ts similarity index 93% rename from server/test/mocks/ldap/LdapClientStub.ts rename to server/src/lib/ldap/LdapClientStub.spec.ts index 9f99392da..c5ea45fff 100644 --- a/server/test/mocks/ldap/LdapClientStub.ts +++ b/server/src/lib/ldap/LdapClientStub.spec.ts @@ -1,6 +1,6 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); -import { ILdapClient } from "../../../src/lib/ldap/ILdapClient"; +import { ILdapClient } from "./ILdapClient"; export class LdapClientStub implements ILdapClient { bindAsyncStub: Sinon.SinonStub; diff --git a/server/test/ldap/PasswordUpdater.test.ts b/server/src/lib/ldap/PasswordUpdater.spec.ts similarity index 84% rename from server/test/ldap/PasswordUpdater.test.ts rename to server/src/lib/ldap/PasswordUpdater.spec.ts index e88192614..8afb6ada5 100644 --- a/server/test/ldap/PasswordUpdater.test.ts +++ b/server/src/lib/ldap/PasswordUpdater.spec.ts @@ -1,13 +1,13 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import { PasswordUpdater } from "../../src/lib/ldap/PasswordUpdater"; -import { LdapConfiguration } from "../../src/lib/configuration/Configuration"; -import { ClientFactoryStub } from "../mocks/ldap/ClientFactoryStub"; -import { ClientStub } from "../mocks/ldap/ClientStub"; -import { HashGenerator } from "../../src/lib/utils/HashGenerator"; +import { PasswordUpdater } from "./PasswordUpdater"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; +import { ClientFactoryStub } from "./ClientFactoryStub.spec"; +import { ClientStub } from "./ClientStub.spec"; +import { HashGenerator } from "../utils/HashGenerator"; -describe("test password update", function () { +describe("ldap/PasswordUpdater", function () { const USERNAME = "username"; const NEW_PASSWORD = "new-password"; @@ -28,8 +28,9 @@ describe("test password update", function () { url: "http://ldap", user: ADMIN_USER_DN, password: ADMIN_PASSWORD, - users_dn: "ou=users,dc=example,dc=com", - groups_dn: "ou=groups,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", group_name_attribute: "cn", groups_filter: "cn={0}", mail_attribute: "mail", diff --git a/server/src/lib/ldap/PasswordUpdater.ts b/server/src/lib/ldap/PasswordUpdater.ts index e492f03b5..03a23ba3b 100644 --- a/server/src/lib/ldap/PasswordUpdater.ts +++ b/server/src/lib/ldap/PasswordUpdater.ts @@ -4,7 +4,7 @@ import ldapjs = require("ldapjs"); import { Client } from "./Client"; import { IPasswordUpdater } from "./IPasswordUpdater"; -import { LdapConfiguration } from "../configuration/Configuration"; +import { LdapConfiguration } from "../configuration/schema/LdapConfiguration"; import { IClientFactory } from "./IClientFactory"; diff --git a/server/test/mocks/ldap/PasswordUpdaterStub.ts b/server/src/lib/ldap/PasswordUpdaterStub.spec.ts similarity index 74% rename from server/test/mocks/ldap/PasswordUpdaterStub.ts rename to server/src/lib/ldap/PasswordUpdaterStub.spec.ts index 9443dddbb..add6465c2 100644 --- a/server/test/mocks/ldap/PasswordUpdaterStub.ts +++ b/server/src/lib/ldap/PasswordUpdaterStub.spec.ts @@ -1,6 +1,6 @@ import BluebirdPromise = require("bluebird"); -import { IClient } from "../../../src/lib/ldap/IClient"; -import { IPasswordUpdater } from "../../../src/lib/ldap/IPasswordUpdater"; +import { IClient } from "./IClient"; +import { IPasswordUpdater } from "./IPasswordUpdater"; import Sinon = require("sinon"); export class PasswordUpdaterStub implements IPasswordUpdater { diff --git a/server/test/ldap/SanitizedClient.test.ts b/server/src/lib/ldap/SanitizedClient.spec.ts similarity index 93% rename from server/test/ldap/SanitizedClient.test.ts rename to server/src/lib/ldap/SanitizedClient.spec.ts index 08aa8c804..6b8009c17 100644 --- a/server/test/ldap/SanitizedClient.test.ts +++ b/server/src/lib/ldap/SanitizedClient.spec.ts @@ -1,8 +1,8 @@ import BluebirdPromise = require("bluebird"); -import { ClientStub } from "../mocks/ldap/ClientStub"; -import { SanitizedClient } from "../../src/lib/ldap/SanitizedClient"; +import { ClientStub } from "./ClientStub.spec"; +import { SanitizedClient } from "./SanitizedClient"; -describe("test SanitizedClient", function () { +describe("ldap/SanitizedClient", function () { let client: SanitizedClient; beforeEach(function () { diff --git a/server/test/mocks/RequestLoggerStub.ts b/server/src/lib/logging/RequestLoggerStub.spec.ts similarity index 88% rename from server/test/mocks/RequestLoggerStub.ts rename to server/src/lib/logging/RequestLoggerStub.spec.ts index 9326ebfcc..b0e375210 100644 --- a/server/test/mocks/RequestLoggerStub.ts +++ b/server/src/lib/logging/RequestLoggerStub.spec.ts @@ -1,6 +1,6 @@ -import { IRequestLogger } from "../../src/lib/logging/IRequestLogger"; +import { IRequestLogger } from "./IRequestLogger"; import Sinon = require("sinon"); -import { RequestLogger } from "../../src/lib/logging/RequestLogger"; +import { RequestLogger } from "./RequestLogger"; import Winston = require("winston"); import Express = require("express"); diff --git a/server/test/notifiers/EMailNotifier.test.ts b/server/src/lib/notifiers/EmailNotifier.spec.ts similarity index 82% rename from server/test/notifiers/EMailNotifier.test.ts rename to server/src/lib/notifiers/EmailNotifier.spec.ts index ca796fca9..8211bbc02 100644 --- a/server/test/notifiers/EMailNotifier.test.ts +++ b/server/src/lib/notifiers/EmailNotifier.spec.ts @@ -2,11 +2,11 @@ import * as sinon from "sinon"; import * as Assert from "assert"; import BluebirdPromise = require("bluebird"); -import { MailSenderStub } from "../mocks/notifiers/MailSenderStub"; -import EMailNotifier = require("../../src/lib/notifiers/EMailNotifier"); +import { MailSenderStub } from "./MailSenderStub.spec"; +import EmailNotifier = require("./EmailNotifier"); -describe("test email notifier", function () { +describe("notifiers/EmailNotifier", function () { it("should send an email to given user", function () { const mailSender = new MailSenderStub(); const options = { @@ -17,7 +17,7 @@ describe("test email notifier", function () { }; mailSender.sendStub.returns(BluebirdPromise.resolve()); - const sender = new EMailNotifier.EMailNotifier(options, mailSender); + const sender = new EmailNotifier.EmailNotifier(options, mailSender); const subject = "subject"; const url = "http://test.com"; @@ -39,7 +39,7 @@ describe("test email notifier", function () { }; mailSender.sendStub.returns(BluebirdPromise.reject(new Error("Failed to send mail"))); - const sender = new EMailNotifier.EMailNotifier(options, mailSender); + const sender = new EmailNotifier.EmailNotifier(options, mailSender); const subject = "subject"; const url = "http://test.com"; diff --git a/server/src/lib/notifiers/EMailNotifier.ts b/server/src/lib/notifiers/EmailNotifier.ts similarity index 80% rename from server/src/lib/notifiers/EMailNotifier.ts rename to server/src/lib/notifiers/EmailNotifier.ts index 5366dfae8..4df7c861e 100644 --- a/server/src/lib/notifiers/EMailNotifier.ts +++ b/server/src/lib/notifiers/EmailNotifier.ts @@ -2,10 +2,10 @@ import * as BluebirdPromise from "bluebird"; import { AbstractEmailNotifier } from "../notifiers/AbstractEmailNotifier"; -import { EmailNotifierConfiguration } from "../configuration/Configuration"; +import { EmailNotifierConfiguration } from "../configuration/schema/NotifierConfiguration"; import { IMailSender } from "./IMailSender"; -export class EMailNotifier extends AbstractEmailNotifier { +export class EmailNotifier extends AbstractEmailNotifier { private mailSender: IMailSender; private sender: string; diff --git a/server/src/lib/notifiers/FileSystemNotifier.ts b/server/src/lib/notifiers/FileSystemNotifier.ts index c5a9f30cd..23f6242c4 100644 --- a/server/src/lib/notifiers/FileSystemNotifier.ts +++ b/server/src/lib/notifiers/FileSystemNotifier.ts @@ -4,7 +4,7 @@ import * as Fs from "fs"; import { INotifier } from "./INotifier"; import { Identity } from "../../../types/Identity"; -import { FileSystemNotifierConfiguration } from "../configuration/Configuration"; +import { FileSystemNotifierConfiguration } from "../configuration/schema/NotifierConfiguration"; export class FileSystemNotifier implements INotifier { private filename: string; diff --git a/server/src/lib/notifiers/IMailSenderBuilder.ts b/server/src/lib/notifiers/IMailSenderBuilder.ts index 59aa677b0..36d4dcdf7 100644 --- a/server/src/lib/notifiers/IMailSenderBuilder.ts +++ b/server/src/lib/notifiers/IMailSenderBuilder.ts @@ -1,5 +1,5 @@ import { IMailSender } from "./IMailSender"; -import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../configuration/Configuration"; +import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../configuration/schema/NotifierConfiguration"; export interface IMailSenderBuilder { buildEmail(options: EmailNotifierConfiguration): IMailSender; diff --git a/server/test/notifiers/MailSenderBuilder.test.ts b/server/src/lib/notifiers/MailSenderBuilder.spec.ts similarity index 93% rename from server/test/notifiers/MailSenderBuilder.test.ts rename to server/src/lib/notifiers/MailSenderBuilder.spec.ts index e328ac563..41e0db426 100644 --- a/server/test/notifiers/MailSenderBuilder.test.ts +++ b/server/src/lib/notifiers/MailSenderBuilder.spec.ts @@ -1,10 +1,10 @@ -import { MailSenderBuilder } from "../../src/lib/notifiers/MailSenderBuilder"; +import { MailSenderBuilder } from ".//MailSenderBuilder"; import Nodemailer = require("nodemailer"); import Sinon = require("sinon"); import Assert = require("assert"); -describe("test MailSenderBuilder", function() { +describe("notifiers/MailSenderBuilder", function() { let createTransportStub: Sinon.SinonStub; beforeEach(function() { createTransportStub = Sinon.stub(Nodemailer, "createTransport"); diff --git a/server/src/lib/notifiers/MailSenderBuilder.ts b/server/src/lib/notifiers/MailSenderBuilder.ts index 4b22ad743..1d06be52f 100644 --- a/server/src/lib/notifiers/MailSenderBuilder.ts +++ b/server/src/lib/notifiers/MailSenderBuilder.ts @@ -3,7 +3,7 @@ import { IMailSenderBuilder } from "./IMailSenderBuilder"; import { MailSender } from "./MailSender"; import Nodemailer = require("nodemailer"); import NodemailerSmtpTransport = require("nodemailer-smtp-transport"); -import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../configuration/Configuration"; +import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../configuration/schema/NotifierConfiguration"; export class MailSenderBuilder implements IMailSenderBuilder { private nodemailer: typeof Nodemailer; diff --git a/server/test/mocks/notifiers/MailSenderBuilderStub.ts b/server/src/lib/notifiers/MailSenderBuilderStub.spec.ts similarity index 91% rename from server/test/mocks/notifiers/MailSenderBuilderStub.ts rename to server/src/lib/notifiers/MailSenderBuilderStub.spec.ts index fa38b0684..5b76f6e56 100644 --- a/server/test/mocks/notifiers/MailSenderBuilderStub.ts +++ b/server/src/lib/notifiers/MailSenderBuilderStub.spec.ts @@ -3,7 +3,7 @@ import BluebirdPromise = require("bluebird"); import Nodemailer = require("nodemailer"); import Sinon = require("sinon"); import { IMailSender } from "../../../src/lib/notifiers/IMailSender"; -import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../../../src/lib/configuration/Configuration"; +import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../../../src/lib/configuration/schema/NotifierConfiguration"; export class MailSenderBuilderStub implements IMailSenderBuilder { buildEmailStub: Sinon.SinonStub; diff --git a/server/test/mocks/notifiers/MailSenderStub.ts b/server/src/lib/notifiers/MailSenderStub.spec.ts similarity index 100% rename from server/test/mocks/notifiers/MailSenderStub.ts rename to server/src/lib/notifiers/MailSenderStub.spec.ts diff --git a/server/test/notifiers/NotifierFactory.test.ts b/server/src/lib/notifiers/NotifierFactory.spec.ts similarity index 71% rename from server/test/notifiers/NotifierFactory.test.ts rename to server/src/lib/notifiers/NotifierFactory.spec.ts index 7ae7d0c38..f15e7667f 100644 --- a/server/test/notifiers/NotifierFactory.test.ts +++ b/server/src/lib/notifiers/NotifierFactory.spec.ts @@ -3,13 +3,13 @@ import * as sinon from "sinon"; import * as BluebirdPromise from "bluebird"; import * as assert from "assert"; -import { NotifierFactory } from "../../src/lib/notifiers/NotifierFactory"; -import { EMailNotifier } from "../../src/lib/notifiers/EMailNotifier"; -import { SmtpNotifier } from "../../src/lib/notifiers/SmtpNotifier"; -import { MailSenderBuilderStub } from "../mocks/notifiers/MailSenderBuilderStub"; +import { NotifierFactory } from "./NotifierFactory"; +import { EmailNotifier } from "./EmailNotifier"; +import { SmtpNotifier } from "./SmtpNotifier"; +import { MailSenderBuilderStub } from "./MailSenderBuilderStub.spec"; -describe("test notifier factory", function () { +describe("notifiers/NotifierFactory", function () { let mailSenderBuilderStub: MailSenderBuilderStub; it("should build a Email Notifier", function () { const options = { @@ -21,7 +21,7 @@ describe("test notifier factory", function () { } }; mailSenderBuilderStub = new MailSenderBuilderStub(); - assert(NotifierFactory.build(options, mailSenderBuilderStub) instanceof EMailNotifier); + assert(NotifierFactory.build(options, mailSenderBuilderStub) instanceof EmailNotifier); }); it("should build a SMTP Notifier", function () { diff --git a/server/src/lib/notifiers/NotifierFactory.ts b/server/src/lib/notifiers/NotifierFactory.ts index c03de76ad..a89155feb 100644 --- a/server/src/lib/notifiers/NotifierFactory.ts +++ b/server/src/lib/notifiers/NotifierFactory.ts @@ -1,10 +1,10 @@ -import { NotifierConfiguration } from "../configuration/Configuration"; +import { NotifierConfiguration } from "../configuration/schema/NotifierConfiguration"; import Nodemailer = require("nodemailer"); import { INotifier } from "./INotifier"; import { FileSystemNotifier } from "./FileSystemNotifier"; -import { EMailNotifier } from "./EMailNotifier"; +import { EmailNotifier } from "./EmailNotifier"; import { SmtpNotifier } from "./SmtpNotifier"; import { IMailSender } from "./IMailSender"; import { IMailSenderBuilder } from "./IMailSenderBuilder"; @@ -13,7 +13,7 @@ export class NotifierFactory { static build(options: NotifierConfiguration, mailSenderBuilder: IMailSenderBuilder): INotifier { if ("email" in options) { const mailSender = mailSenderBuilder.buildEmail(options.email); - return new EMailNotifier(options.email, mailSender); + return new EmailNotifier(options.email, mailSender); } else if ("smtp" in options) { const mailSender = mailSenderBuilder.buildSmtp(options.smtp); diff --git a/server/test/mocks/NotifierStub.ts b/server/src/lib/notifiers/NotifierStub.spec.ts similarity index 85% rename from server/test/mocks/NotifierStub.ts rename to server/src/lib/notifiers/NotifierStub.spec.ts index 94a178e82..f99231b50 100644 --- a/server/test/mocks/NotifierStub.ts +++ b/server/src/lib/notifiers/NotifierStub.spec.ts @@ -1,7 +1,7 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); -import { INotifier } from "../../src/lib/notifiers/INotifier"; +import { INotifier } from "./INotifier"; export class NotifierStub implements INotifier { notifyStub: Sinon.SinonStub; diff --git a/server/src/lib/notifiers/SmtpNotifier.ts b/server/src/lib/notifiers/SmtpNotifier.ts index cda174c98..f93a6d4a0 100644 --- a/server/src/lib/notifiers/SmtpNotifier.ts +++ b/server/src/lib/notifiers/SmtpNotifier.ts @@ -4,7 +4,7 @@ import * as BluebirdPromise from "bluebird"; import { IMailSender } from "./IMailSender"; import { AbstractEmailNotifier } from "../notifiers/AbstractEmailNotifier"; -import { SmtpNotifierConfiguration } from "../configuration/Configuration"; +import { SmtpNotifierConfiguration } from "../configuration/schema/NotifierConfiguration"; export class SmtpNotifier extends AbstractEmailNotifier { private mailSender: IMailSender; diff --git a/server/test/regulation/Regulator.test.ts b/server/src/lib/regulation/Regulator.spec.ts similarity index 96% rename from server/test/regulation/Regulator.test.ts rename to server/src/lib/regulation/Regulator.spec.ts index 5f10fd056..f9c6e6086 100644 --- a/server/test/regulation/Regulator.test.ts +++ b/server/src/lib/regulation/Regulator.spec.ts @@ -3,12 +3,12 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import { Regulator } from "../../src/lib/regulation/Regulator"; +import { Regulator } from "./Regulator"; import MockDate = require("mockdate"); -import exceptions = require("../../src/lib/Exceptions"); -import { UserDataStoreStub } from "../mocks/storage/UserDataStoreStub"; +import exceptions = require("../Exceptions"); +import { UserDataStoreStub } from "../storage/UserDataStoreStub.spec"; -describe("test authentication regulator", function () { +describe("regulation/Regulator", function () { const USER1 = "USER1"; const USER2 = "USER2"; let userDataStoreStub: UserDataStoreStub; diff --git a/server/src/lib/regulation/RegulatorStub.spec.ts b/server/src/lib/regulation/RegulatorStub.spec.ts new file mode 100644 index 000000000..ca8a00fb1 --- /dev/null +++ b/server/src/lib/regulation/RegulatorStub.spec.ts @@ -0,0 +1,22 @@ +import Bluebird = require("bluebird"); +import Sinon = require("sinon"); +import { IRegulator } from "./IRegulator"; + + +export class RegulatorStub implements IRegulator { + markStub: Sinon.SinonStub; + regulateStub: Sinon.SinonStub; + + constructor() { + this.markStub = Sinon.stub(); + this.regulateStub = Sinon.stub(); + } + + mark(userId: string, isAuthenticationSuccessful: boolean): Bluebird { + return this.markStub(userId, isAuthenticationSuccessful); + } + + regulate(userId: string): Bluebird { + return this.regulateStub(userId); + } +} diff --git a/server/test/routes/errors/401/get.test.ts b/server/src/lib/routes/error/401/get.spec.ts similarity index 87% rename from server/test/routes/errors/401/get.test.ts rename to server/src/lib/routes/error/401/get.spec.ts index 36766f172..9fdac9c3c 100644 --- a/server/test/routes/errors/401/get.test.ts +++ b/server/src/lib/routes/error/401/get.spec.ts @@ -1,12 +1,12 @@ import Sinon = require("sinon"); import Express = require("express"); import Assert = require("assert"); -import Get401 from "../../../../src/lib/routes/error/401/get"; -import { ServerVariables } from "../../../../src/lib/ServerVariables"; +import Get401 from "./get"; +import { ServerVariables } from "../../../ServerVariables"; import { ServerVariablesMockBuilder, ServerVariablesMock } - from "../../../mocks/ServerVariablesMockBuilder"; + from "../../../ServerVariablesMockBuilder.spec"; -describe("Server error 401", function () { +describe("routes/error/401/get", function () { let vars: ServerVariables; let mocks: ServerVariablesMock; let req: any; diff --git a/server/test/routes/errors/403/get.test.ts b/server/src/lib/routes/error/403/get.spec.ts similarity index 87% rename from server/test/routes/errors/403/get.test.ts rename to server/src/lib/routes/error/403/get.spec.ts index 376acb6a9..22eb84853 100644 --- a/server/test/routes/errors/403/get.test.ts +++ b/server/src/lib/routes/error/403/get.spec.ts @@ -1,12 +1,12 @@ import Sinon = require("sinon"); import Express = require("express"); import Assert = require("assert"); -import Get403 from "../../../../src/lib/routes/error/403/get"; -import { ServerVariables } from "../../../../src/lib/ServerVariables"; +import Get403 from "./get"; +import { ServerVariables } from "../../../ServerVariables"; import { ServerVariablesMockBuilder, ServerVariablesMock } - from "../../../mocks/ServerVariablesMockBuilder"; + from "../../../ServerVariablesMockBuilder.spec"; -describe("Server error 403", function () { +describe("routes/error/403/get", function () { let vars: ServerVariables; let mocks: ServerVariablesMock; let req: any; diff --git a/server/test/routes/errors/404/get.test.ts b/server/src/lib/routes/error/404/get.spec.ts similarity index 79% rename from server/test/routes/errors/404/get.test.ts rename to server/src/lib/routes/error/404/get.spec.ts index fe2838605..73e4e6cef 100644 --- a/server/test/routes/errors/404/get.test.ts +++ b/server/src/lib/routes/error/404/get.spec.ts @@ -1,9 +1,9 @@ import Sinon = require("sinon"); import Express = require("express"); import Assert = require("assert"); -import Get404 from "../../../../src/lib/routes/error/404/get"; +import Get404 from "./get"; -describe("Server error 404", function () { +describe("routes/error/404/get", function () { it("should render the page", function () { const req = {} as Express.Request; const res = { diff --git a/server/test/routes/firstfactor/post.test.ts b/server/src/lib/routes/firstfactor/post.spec.ts similarity index 82% rename from server/test/routes/firstfactor/post.test.ts rename to server/src/lib/routes/firstfactor/post.spec.ts index 6f8ba43cb..e3b726b9f 100644 --- a/server/test/routes/firstfactor/post.test.ts +++ b/server/src/lib/routes/firstfactor/post.spec.ts @@ -2,18 +2,18 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import FirstFactorPost = require("../../../src/lib/routes/firstfactor/post"); -import exceptions = require("../../../src/lib/Exceptions"); -import { AuthenticationSessionHandler } from "../../../src/lib/AuthenticationSessionHandler"; -import { AuthenticationSession } from "../../../types/AuthenticationSession"; -import Endpoints = require("../../../../shared/api"); -import AuthenticationRegulatorMock = require("../../mocks/AuthenticationRegulator"); -import { AccessControllerStub } from "../../mocks/AccessControllerStub"; -import ExpressMock = require("../../mocks/express"); -import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../src/lib/ServerVariables"; +import FirstFactorPost = require("./post"); +import exceptions = require("../../Exceptions"); +import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; +import { AuthenticationSession } from "../../../../types/AuthenticationSession"; +import Endpoints = require("../../../../../shared/api"); +import AuthenticationRegulatorMock = require("../../regulation/RegulatorStub.spec"); +import { AccessControllerStub } from "../../access_control/AccessControllerStub.spec"; +import ExpressMock = require("../../stubs/express.spec"); +import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../ServerVariables"; -describe("test the first factor validation route", function () { +describe("routes/firstfactor/post", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let emails: string[]; diff --git a/server/test/routes/password-reset/post.test.ts b/server/src/lib/routes/password-reset/form/post.spec.ts similarity index 83% rename from server/test/routes/password-reset/post.test.ts rename to server/src/lib/routes/password-reset/form/post.spec.ts index 9b86e7a4e..04efe177d 100644 --- a/server/test/routes/password-reset/post.test.ts +++ b/server/src/lib/routes/password-reset/form/post.spec.ts @@ -1,17 +1,17 @@ -import PasswordResetFormPost = require("../../../src/lib/routes/password-reset/form/post"); -import { PasswordUpdater } from "../../../src/lib/ldap/PasswordUpdater"; -import { AuthenticationSessionHandler } from "../../../src/lib/AuthenticationSessionHandler"; -import { AuthenticationSession } from "../../../types/AuthenticationSession"; -import { UserDataStore } from "../../../src/lib/storage/UserDataStore"; +import PasswordResetFormPost = require("./post"); +import { PasswordUpdater } from "../../../ldap/PasswordUpdater"; +import { AuthenticationSessionHandler } from "../../../AuthenticationSessionHandler"; +import { AuthenticationSession } from "../../../../../types/AuthenticationSession"; +import { UserDataStore } from "../../../storage/UserDataStore"; import Sinon = require("sinon"); import Assert = require("assert"); import BluebirdPromise = require("bluebird"); -import ExpressMock = require("../../mocks/express"); -import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../src/lib/ServerVariables"; +import ExpressMock = require("../../../stubs/express.spec"); +import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../ServerVariables"; -describe("test reset password route", function () { +describe("routes/password-reset/form/post", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let vars: ServerVariables; @@ -48,8 +48,9 @@ describe("test reset password route", function () { mail_attribute: "mail", user: "user", password: "password", - users_dn: "ou=users,dc=example,dc=com", - groups_dn: "ou=groups,dc=example,dc=com", + additional_users_dn: "ou=users", + additional_groups_dn: "ou=groups", + base_dn: "dc=example,dc=com", users_filter: "user", group_name_attribute: "cn", groups_filter: "groups" diff --git a/server/test/routes/password-reset/identity/PasswordResetHandler.test.ts b/server/src/lib/routes/password-reset/identity/PasswordResetHandler.spec.ts similarity index 84% rename from server/test/routes/password-reset/identity/PasswordResetHandler.test.ts rename to server/src/lib/routes/password-reset/identity/PasswordResetHandler.spec.ts index f7d906818..34d699cab 100644 --- a/server/test/routes/password-reset/identity/PasswordResetHandler.test.ts +++ b/server/src/lib/routes/password-reset/identity/PasswordResetHandler.spec.ts @@ -1,18 +1,18 @@ import PasswordResetHandler - from "../../../../src/lib/routes/password-reset/identity/PasswordResetHandler"; -import PasswordUpdater = require("../../../../src/lib/ldap/PasswordUpdater"); -import { UserDataStore } from "../../../../src/lib/storage/UserDataStore"; + from "./PasswordResetHandler"; +import PasswordUpdater = require("../../../ldap/PasswordUpdater"); +import { UserDataStore } from "../../../storage/UserDataStore"; import Sinon = require("sinon"); import winston = require("winston"); import assert = require("assert"); import BluebirdPromise = require("bluebird"); -import ExpressMock = require("../../../mocks/express"); +import ExpressMock = require("../../../stubs/express.spec"); import { ServerVariablesMock, ServerVariablesMockBuilder } - from "../../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../../src/lib/ServerVariables"; + from "../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../ServerVariables"; -describe("test reset password identity check", function () { +describe("routes/password-reset/identity/PasswordResetHandler", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/src/lib/routes/password-reset/identity/PasswordResetHandler.ts b/server/src/lib/routes/password-reset/identity/PasswordResetHandler.ts index 2baf2fc8d..5cce78ea2 100644 --- a/server/src/lib/routes/password-reset/identity/PasswordResetHandler.ts +++ b/server/src/lib/routes/password-reset/identity/PasswordResetHandler.ts @@ -4,7 +4,7 @@ import objectPath = require("object-path"); import exceptions = require("../../../Exceptions"); import { Identity } from "../../../../../types/Identity"; -import { IdentityValidable } from "../../../IdentityCheckMiddleware"; +import { IdentityValidable } from "../../../IdentityValidable"; import { PRE_VALIDATION_TEMPLATE } from "../../../IdentityCheckPreValidationTemplate"; import Constants = require("../constants"); import { IRequestLogger } from "../../../logging/IRequestLogger"; diff --git a/server/test/routes/secondfactor/get.test.ts b/server/src/lib/routes/secondfactor/get.spec.ts similarity index 83% rename from server/test/routes/secondfactor/get.test.ts rename to server/src/lib/routes/secondfactor/get.spec.ts index b19733e6b..f7cc8cd33 100644 --- a/server/test/routes/secondfactor/get.test.ts +++ b/server/src/lib/routes/secondfactor/get.spec.ts @@ -1,14 +1,14 @@ -import SecondFactorGet from "../../../src/lib/routes/secondfactor/get"; +import SecondFactorGet from "./get"; import { ServerVariablesMockBuilder, ServerVariablesMock } - from "../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../src/lib/ServerVariables"; + from "../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../ServerVariables"; import Sinon = require("sinon"); -import ExpressMock = require("../../mocks/express"); +import ExpressMock = require("../../stubs/express.spec"); import Assert = require("assert"); -import Endpoints = require("../../../../shared/api"); +import Endpoints = require("../../../../../shared/api"); import BluebirdPromise = require("bluebird"); -describe("test second factor GET endpoint handler", function () { +describe("routes/secondfactor/get", function () { let mocks: ServerVariablesMock; let vars: ServerVariables; let req: ExpressMock.RequestMock; diff --git a/server/test/routes/secondfactor/redirect.test.ts b/server/src/lib/routes/secondfactor/redirect.spec.ts similarity index 76% rename from server/test/routes/secondfactor/redirect.test.ts rename to server/src/lib/routes/secondfactor/redirect.spec.ts index 2c0dd5d46..ea66e6dca 100644 --- a/server/test/routes/secondfactor/redirect.test.ts +++ b/server/src/lib/routes/secondfactor/redirect.spec.ts @@ -1,11 +1,11 @@ -import Redirect from "../../../src/lib/routes/secondfactor/redirect"; -import ExpressMock = require("../../mocks/express"); +import Redirect from "./redirect"; +import ExpressMock = require("../../stubs/express.spec"); import { ServerVariablesMockBuilder, ServerVariablesMock } -from "../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../src/lib/ServerVariables"; +from "../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../ServerVariables"; import Assert = require("assert"); -describe("test second factor redirect", function() { +describe("routes/secondfactor/redirect", function() { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/test/routes/secondfactor/totp/register/RegistrationHandler.test.ts b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.spec.ts similarity index 87% rename from server/test/routes/secondfactor/totp/register/RegistrationHandler.test.ts rename to server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.spec.ts index 1b0aaf34a..78b8ea3ea 100644 --- a/server/test/routes/secondfactor/totp/register/RegistrationHandler.test.ts +++ b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.spec.ts @@ -1,15 +1,15 @@ import Sinon = require("sinon"); -import RegistrationHandler from "../../../../../src/lib/routes/secondfactor/totp/identity/RegistrationHandler"; -import { Identity } from "../../../../../types/Identity"; -import { UserDataStore } from "../../../../../src/lib/storage/UserDataStore"; +import RegistrationHandler from "./RegistrationHandler"; +import { Identity } from "../../../../../../types/Identity"; +import { UserDataStore } from "../../../../storage/UserDataStore"; import BluebirdPromise = require("bluebird"); -import ExpressMock = require("../../../../mocks/express"); +import ExpressMock = require("../../../../stubs/express.spec"); import { ServerVariablesMock, ServerVariablesMockBuilder } - from "../../../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; + from "../../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../../ServerVariables"; import Assert = require("assert"); -describe("test totp register", function () { +describe("routes/secondfactor/totp/identity/RegistrationHandler", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts index d8394aadb..b39b6d045 100644 --- a/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts +++ b/server/src/lib/routes/secondfactor/totp/identity/RegistrationHandler.ts @@ -4,7 +4,7 @@ import BluebirdPromise = require("bluebird"); import objectPath = require("object-path"); import { Identity } from "../../../../../../types/Identity"; -import { IdentityValidable } from "../../../../IdentityCheckMiddleware"; +import { IdentityValidable } from "../../../../IdentityValidable"; import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate"; import Constants = require("../constants"); import Endpoints = require("../../../../../../../shared/api"); @@ -16,18 +16,18 @@ import { IRequestLogger } from "../../../../logging/IRequestLogger"; import { IUserDataStore } from "../../../../storage/IUserDataStore"; import { ITotpHandler } from "../../../../authentication/totp/ITotpHandler"; import { TOTPSecret } from "../../../../../../types/TOTPSecret"; -import { TOTPConfiguration } from "../../../../configuration/Configuration"; +import { TotpConfiguration } from "../../../../configuration/schema/TotpConfiguration"; export default class RegistrationHandler implements IdentityValidable { private logger: IRequestLogger; private userDataStore: IUserDataStore; private totp: ITotpHandler; - private configuration: TOTPConfiguration; + private configuration: TotpConfiguration; constructor(logger: IRequestLogger, userDataStore: IUserDataStore, - totp: ITotpHandler, configuration: TOTPConfiguration) { + totp: ITotpHandler, configuration: TotpConfiguration) { this.logger = logger; this.userDataStore = userDataStore; this.totp = totp; diff --git a/server/test/routes/secondfactor/totp/sign/post.test.ts b/server/src/lib/routes/secondfactor/totp/sign/post.spec.ts similarity index 75% rename from server/test/routes/secondfactor/totp/sign/post.test.ts rename to server/src/lib/routes/secondfactor/totp/sign/post.spec.ts index ddf1d26cf..651f7d77f 100644 --- a/server/test/routes/secondfactor/totp/sign/post.test.ts +++ b/server/src/lib/routes/secondfactor/totp/sign/post.spec.ts @@ -2,17 +2,17 @@ import BluebirdPromise = require("bluebird"); import Sinon = require("sinon"); import Assert = require("assert"); -import Exceptions = require("../../../../../src/lib/Exceptions"); -import { AuthenticationSessionHandler } from "../../../../../src/lib/AuthenticationSessionHandler"; -import { AuthenticationSession } from "../../../../../types/AuthenticationSession"; -import SignPost = require("../../../../../src/lib/routes/secondfactor/totp/sign/post"); -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; +import Exceptions = require("../../../../Exceptions"); +import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler"; +import { AuthenticationSession } from "../../../../../../types/AuthenticationSession"; +import SignPost = require("./post"); +import { ServerVariables } from "../../../../ServerVariables"; -import ExpressMock = require("../../../../mocks/express"); -import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub"; -import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../mocks/ServerVariablesMockBuilder"; +import ExpressMock = require("../../../../stubs/express.spec"); +import { UserDataStoreStub } from "../../../../storage/UserDataStoreStub.spec"; +import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../ServerVariablesMockBuilder.spec"; -describe("test totp route", function () { +describe("routes/secondfactor/totp/sign/post", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let authSession: AuthenticationSession; diff --git a/server/src/lib/routes/secondfactor/totp/sign/post.ts b/server/src/lib/routes/secondfactor/totp/sign/post.ts index 45bbec94f..1d62b5497 100644 --- a/server/src/lib/routes/secondfactor/totp/sign/post.ts +++ b/server/src/lib/routes/secondfactor/totp/sign/post.ts @@ -1,11 +1,9 @@ +import Bluebird = require("bluebird"); +import Express = require("express"); -import exceptions = require("../../../../Exceptions"); -import objectPath = require("object-path"); -import express = require("express"); import { TOTPSecretDocument } from "../../../../storage/TOTPSecretDocument"; -import BluebirdPromise = require("bluebird"); import Endpoints = require("../../../../../../../shared/api"); -import redirect from "../../redirect"; +import Redirect from "../../redirect"; import ErrorReplies = require("../../../../ErrorReplies"); import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler"; import { AuthenticationSession } from "../../../../../../types/AuthenticationSession"; @@ -15,11 +13,11 @@ import { ServerVariables } from "../../../../ServerVariables"; const UNAUTHORIZED_MESSAGE = "Unauthorized access"; export default function (vars: ServerVariables) { - function handler(req: express.Request, res: express.Response): BluebirdPromise { + function handler(req: Express.Request, res: Express.Response): Bluebird { let authSession: AuthenticationSession; const token = req.body.token; - return new BluebirdPromise(function (resolve, reject) { + return new Bluebird(function (resolve, reject) { authSession = AuthenticationSessionHandler.get(req, vars.logger); vars.logger.info(req, "Initiate TOTP validation for user \"%s\".", authSession.userid); resolve(); @@ -29,12 +27,12 @@ export default function (vars: ServerVariables) { }) .then(function (doc: TOTPSecretDocument) { if (!vars.totpHandler.validate(token, doc.secret.base32)) - return BluebirdPromise.reject(new Error("Invalid TOTP token.")); + return Bluebird.reject(new Error("Invalid TOTP token.")); vars.logger.debug(req, "TOTP validation succeeded."); authSession.second_factor = true; - redirect(vars)(req, res); - return BluebirdPromise.resolve(); + Redirect(vars)(req, res); + return Bluebird.resolve(); }) .catch(ErrorReplies.replyWithError200(req, res, vars.logger, UserMessages.OPERATION_FAILED)); diff --git a/server/test/routes/secondfactor/u2f/identity/RegistrationHandler.test.ts b/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.spec.ts similarity index 86% rename from server/test/routes/secondfactor/u2f/identity/RegistrationHandler.test.ts rename to server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.spec.ts index d10268f34..a54bfbfe6 100644 --- a/server/test/routes/secondfactor/u2f/identity/RegistrationHandler.test.ts +++ b/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.spec.ts @@ -2,14 +2,14 @@ import Sinon = require("sinon"); import Assert = require("assert"); import BluebirdPromise = require("bluebird"); -import { Identity } from "../../../../../types/Identity"; -import RegistrationHandler from "../../../../../src/lib/routes/secondfactor/u2f/identity/RegistrationHandler"; -import ExpressMock = require("../../../../mocks/express"); -import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub"; -import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; +import { Identity } from "../../../../../../types/Identity"; +import RegistrationHandler from "./RegistrationHandler"; +import ExpressMock = require("../../../../stubs/express.spec"); +import { UserDataStoreStub } from "../../../../storage/UserDataStoreStub.spec"; +import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../../ServerVariables"; -describe("test U2F register handler", function () { +describe("routes/secondfactor/u2f/identity/RegistrationHandler", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts b/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts index 06fd44da8..bc4713c77 100644 --- a/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts +++ b/server/src/lib/routes/secondfactor/u2f/identity/RegistrationHandler.ts @@ -3,7 +3,7 @@ import BluebirdPromise = require("bluebird"); import express = require("express"); import objectPath = require("object-path"); -import { IdentityValidable } from "../../../../IdentityCheckMiddleware"; +import { IdentityValidable } from "../../../../IdentityValidable"; import { Identity } from "../../../../../../types/Identity"; import { PRE_VALIDATION_TEMPLATE } from "../../../../IdentityCheckPreValidationTemplate"; import FirstFactorValidator = require("../../../../FirstFactorValidator"); diff --git a/server/test/routes/secondfactor/u2f/register/post.test.ts b/server/src/lib/routes/secondfactor/u2f/register/post.spec.ts similarity index 88% rename from server/test/routes/secondfactor/u2f/register/post.test.ts rename to server/src/lib/routes/secondfactor/u2f/register/post.spec.ts index 59ee8a761..de3347a21 100644 --- a/server/test/routes/secondfactor/u2f/register/post.test.ts +++ b/server/src/lib/routes/secondfactor/u2f/register/post.spec.ts @@ -2,16 +2,16 @@ import sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import assert = require("assert"); -import U2FRegisterPost = require("../../../../../src/lib/routes/secondfactor/u2f/register/post"); -import { AuthenticationSessionHandler } from "../../../../../src/lib/AuthenticationSessionHandler"; -import { AuthenticationSession } from "../../../../../types/AuthenticationSession"; -import ExpressMock = require("../../../../mocks/express"); -import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub"; -import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; +import U2FRegisterPost = require("./post"); +import { AuthenticationSessionHandler } from "../../../../AuthenticationSessionHandler"; +import { AuthenticationSession } from "../../../../../../types/AuthenticationSession"; +import ExpressMock = require("../../../../stubs/express.spec"); +import { UserDataStoreStub } from "../../../../storage/UserDataStoreStub.spec"; +import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../../ServerVariables"; -describe("test u2f routes: register", function () { +describe("routes/secondfactor/u2f/register/post", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/test/routes/secondfactor/u2f/register_request/get.test.ts b/server/src/lib/routes/secondfactor/u2f/register_request/get.spec.ts similarity index 85% rename from server/test/routes/secondfactor/u2f/register_request/get.test.ts rename to server/src/lib/routes/secondfactor/u2f/register_request/get.spec.ts index 9617e24bb..a207c9109 100644 --- a/server/test/routes/secondfactor/u2f/register_request/get.test.ts +++ b/server/src/lib/routes/secondfactor/u2f/register_request/get.spec.ts @@ -2,13 +2,13 @@ import sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import U2FRegisterRequestGet = require("../../../../../src/lib/routes/secondfactor/u2f/register_request/get"); -import ExpressMock = require("../../../../mocks/express"); -import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub"; -import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; +import U2FRegisterRequestGet = require("./get"); +import ExpressMock = require("../../../../stubs/express.spec"); +import { UserDataStoreStub } from "../../../../storage/UserDataStoreStub.spec"; +import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../../ServerVariables"; -describe("test u2f routes: register_request", function () { +describe("routes/secondfactor/u2f/register_request/get", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/test/routes/secondfactor/u2f/sign/post.test.ts b/server/src/lib/routes/secondfactor/u2f/sign/post.spec.ts similarity index 86% rename from server/test/routes/secondfactor/u2f/sign/post.test.ts rename to server/src/lib/routes/secondfactor/u2f/sign/post.spec.ts index 942d9dbfa..034a73ebd 100644 --- a/server/test/routes/secondfactor/u2f/sign/post.test.ts +++ b/server/src/lib/routes/secondfactor/u2f/sign/post.spec.ts @@ -2,16 +2,16 @@ import sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import Assert = require("assert"); -import U2FSignPost = require("../../../../../src/lib/routes/secondfactor/u2f/sign/post"); -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; +import U2FSignPost = require("./post"); +import { ServerVariables } from "../../../../ServerVariables"; import winston = require("winston"); -import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../mocks/ServerVariablesMockBuilder"; -import ExpressMock = require("../../../../mocks/express"); -import U2FMock = require("../../../../mocks/u2f"); +import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../../../ServerVariablesMockBuilder.spec"; +import ExpressMock = require("../../../../stubs/express.spec"); +import U2FMock = require("../../../../stubs/u2f.spec"); import U2f = require("u2f"); -describe("test u2f routes: sign", function () { +describe("routes/secondfactor/u2f/sign/post", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/test/routes/secondfactor/u2f/sign_request/get.test.ts b/server/src/lib/routes/secondfactor/u2f/sign_request/get.spec.ts similarity index 76% rename from server/test/routes/secondfactor/u2f/sign_request/get.test.ts rename to server/src/lib/routes/secondfactor/u2f/sign_request/get.spec.ts index 49e7cf11e..db2fb0c31 100644 --- a/server/test/routes/secondfactor/u2f/sign_request/get.test.ts +++ b/server/src/lib/routes/secondfactor/u2f/sign_request/get.spec.ts @@ -2,17 +2,17 @@ import sinon = require("sinon"); import BluebirdPromise = require("bluebird"); import assert = require("assert"); -import U2FSignRequestGet = require("../../../../../src/lib/routes/secondfactor/u2f/sign_request/get"); -import ExpressMock = require("../../../../mocks/express"); -import { UserDataStoreStub } from "../../../../mocks/storage/UserDataStoreStub"; -import U2FMock = require("../../../../mocks/u2f"); +import U2FSignRequestGet = require("./get"); +import ExpressMock = require("../../../../stubs/express.spec"); +import { UserDataStoreStub } from "../../../../storage/UserDataStoreStub.spec"; +import U2FMock = require("../../../../stubs/u2f.spec"); import U2f = require("u2f"); -import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../mocks/ServerVariablesMockBuilder"; -import { ServerVariables } from "../../../../../src/lib/ServerVariables"; +import { ServerVariablesMock, ServerVariablesMockBuilder } from "../../../../ServerVariablesMockBuilder.spec"; +import { ServerVariables } from "../../../../ServerVariables"; -import { SignMessage } from "../../../../../../shared/SignMessage"; +import { SignMessage } from "../../../../../../../shared/SignMessage"; -describe("test u2f routes: sign_request", function () { +describe("routes/secondfactor/u2f/sign_request/get", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/test/routes/verify/get.test.ts b/server/src/lib/routes/verify/get.spec.ts similarity index 95% rename from server/test/routes/verify/get.test.ts rename to server/src/lib/routes/verify/get.spec.ts index 2baa49c3b..cb8cb5869 100644 --- a/server/test/routes/verify/get.test.ts +++ b/server/src/lib/routes/verify/get.spec.ts @@ -1,18 +1,17 @@ import Assert = require("assert"); -import VerifyGet = require("../../../src/lib/routes/verify/get"); -import { AuthenticationSessionHandler } from "../../../src/lib/AuthenticationSessionHandler"; -import { AuthenticationSession } from "../../../types/AuthenticationSession"; -import { AuthenticationMethodsConfiguration } from "../../../src/lib/configuration/Configuration"; +import VerifyGet = require("./get"); +import { AuthenticationSessionHandler } from "../../AuthenticationSessionHandler"; +import { AuthenticationSession } from "../../../../types/AuthenticationSession"; import Sinon = require("sinon"); import winston = require("winston"); import BluebirdPromise = require("bluebird"); import express = require("express"); -import ExpressMock = require("../../mocks/express"); -import { ServerVariables } from "../../../src/lib/ServerVariables"; -import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../mocks/ServerVariablesMockBuilder"; +import ExpressMock = require("../../stubs/express.spec"); +import { ServerVariables } from "../../ServerVariables"; +import { ServerVariablesMockBuilder, ServerVariablesMock } from "../../ServerVariablesMockBuilder.spec"; -describe("test /api/verify endpoint", function () { +describe("routes/verify/get", function () { let req: ExpressMock.RequestMock; let res: ExpressMock.ResponseMock; let mocks: ServerVariablesMock; diff --git a/server/src/lib/routes/verify/get_session_cookie.ts b/server/src/lib/routes/verify/get_session_cookie.ts index 6571e8fe8..8b144cd95 100644 --- a/server/src/lib/routes/verify/get_session_cookie.ts +++ b/server/src/lib/routes/verify/get_session_cookie.ts @@ -4,7 +4,7 @@ import Util = require("util"); import ObjectPath = require("object-path"); import Exceptions = require("../../Exceptions"); -import { AppConfiguration } from "../../configuration/Configuration"; +import { Configuration } from "../../configuration/schema/Configuration"; import Constants = require("../../../../../shared/constants"); import { DomainExtractor } from "../../utils/DomainExtractor"; import { ServerVariables } from "../../ServerVariables"; @@ -21,7 +21,7 @@ const SECOND_FACTOR_NOT_VALIDATED_MESSAGE = "Second factor not yet validated"; function verify_inactivity(req: Express.Request, authSession: AuthenticationSession, - configuration: AppConfiguration, logger: IRequestLogger) + configuration: Configuration, logger: IRequestLogger) : BluebirdPromise { // If inactivity is not specified, then inactivity timeout does not apply diff --git a/server/test/mocks/storage/CollectionFactoryStub.ts b/server/src/lib/storage/CollectionFactoryStub.spec.ts similarity index 70% rename from server/test/mocks/storage/CollectionFactoryStub.ts rename to server/src/lib/storage/CollectionFactoryStub.spec.ts index 947be55f5..17f8bb021 100644 --- a/server/test/mocks/storage/CollectionFactoryStub.ts +++ b/server/src/lib/storage/CollectionFactoryStub.spec.ts @@ -1,7 +1,7 @@ import BluebirdPromise = require("bluebird"); import Sinon = require("sinon"); -import { ICollection } from "../../../src/lib/storage/ICollection"; -import { ICollectionFactory } from "../../../src/lib/storage/ICollectionFactory"; +import { ICollection } from "./ICollection"; +import { ICollectionFactory } from "./ICollectionFactory"; export class CollectionFactoryStub implements ICollectionFactory { buildStub: Sinon.SinonStub; diff --git a/server/test/mocks/storage/CollectionStub.ts b/server/src/lib/storage/CollectionStub.spec.ts similarity index 94% rename from server/test/mocks/storage/CollectionStub.ts rename to server/src/lib/storage/CollectionStub.spec.ts index 05dc76ba6..42895d672 100644 --- a/server/test/mocks/storage/CollectionStub.ts +++ b/server/src/lib/storage/CollectionStub.spec.ts @@ -1,6 +1,6 @@ import BluebirdPromise = require("bluebird"); import Sinon = require("sinon"); -import { ICollection } from "../../../src/lib/storage/ICollection"; +import { ICollection } from "./ICollection"; export class CollectionStub implements ICollection { findStub: Sinon.SinonStub; diff --git a/server/test/storage/UserDataStore.test.ts b/server/src/lib/storage/UserDataStore.spec.ts similarity index 94% rename from server/test/storage/UserDataStore.test.ts rename to server/src/lib/storage/UserDataStore.spec.ts index c43d52a1d..66fb85461 100644 --- a/server/test/storage/UserDataStore.test.ts +++ b/server/src/lib/storage/UserDataStore.spec.ts @@ -4,14 +4,14 @@ import * as Sinon from "sinon"; import * as MockDate from "mockdate"; import BluebirdPromise = require("bluebird"); -import { UserDataStore } from "../../src/lib/storage/UserDataStore"; -import { TOTPSecret } from "../../types/TOTPSecret"; -import { U2FRegistration } from "../../types/U2FRegistration"; -import { AuthenticationTraceDocument } from "../../src/lib/storage/AuthenticationTraceDocument"; -import { CollectionStub } from "../mocks/storage/CollectionStub"; -import { CollectionFactoryStub } from "../mocks/storage/CollectionFactoryStub"; +import { UserDataStore } from "./UserDataStore"; +import { TOTPSecret } from "../../../types/TOTPSecret"; +import { U2FRegistration } from "../../../types/U2FRegistration"; +import { AuthenticationTraceDocument } from "./AuthenticationTraceDocument"; +import { CollectionStub } from "./CollectionStub.spec"; +import { CollectionFactoryStub } from "./CollectionFactoryStub.spec"; -describe("test user data store", function () { +describe("storage/UserDataStore", function () { let factory: CollectionFactoryStub; let collection: CollectionStub; let userId: string; diff --git a/server/test/mocks/storage/UserDataStoreStub.ts b/server/src/lib/storage/UserDataStoreStub.spec.ts similarity index 85% rename from server/test/mocks/storage/UserDataStoreStub.ts rename to server/src/lib/storage/UserDataStoreStub.spec.ts index 41fa0bb97..5ea27a2de 100644 --- a/server/test/mocks/storage/UserDataStoreStub.ts +++ b/server/src/lib/storage/UserDataStoreStub.spec.ts @@ -1,14 +1,13 @@ import Sinon = require("sinon"); import BluebirdPromise = require("bluebird"); -import { TOTPSecretDocument } from "../../../src/lib/storage/TOTPSecretDocument"; -import { U2FRegistrationDocument } from "../../../src/lib/storage/U2FRegistrationDocument"; +import { TOTPSecretDocument } from "./TOTPSecretDocument"; +import { U2FRegistrationDocument } from "./U2FRegistrationDocument"; import { U2FRegistration } from "../../../types/U2FRegistration"; import { TOTPSecret } from "../../../types/TOTPSecret"; -import { AuthenticationTraceDocument } from "../../../src/lib/storage/AuthenticationTraceDocument"; -import { IdentityValidationDocument } from "../../../src/lib/storage/IdentityValidationDocument"; - -import { IUserDataStore } from "../../../src/lib/storage/IUserDataStore"; +import { AuthenticationTraceDocument } from "./AuthenticationTraceDocument"; +import { IdentityValidationDocument } from "./IdentityValidationDocument"; +import { IUserDataStore } from "./IUserDataStore"; export class UserDataStoreStub implements IUserDataStore { saveU2FRegistrationStub: Sinon.SinonStub; diff --git a/server/test/storage/mongo/MongoCollection.test.ts b/server/src/lib/storage/mongo/MongoCollection.spec.ts similarity index 94% rename from server/test/storage/mongo/MongoCollection.test.ts rename to server/src/lib/storage/mongo/MongoCollection.spec.ts index bce9026c6..49208b5df 100644 --- a/server/test/storage/mongo/MongoCollection.test.ts +++ b/server/src/lib/storage/mongo/MongoCollection.spec.ts @@ -2,10 +2,10 @@ import Assert = require("assert"); import Sinon = require("sinon"); import MongoDB = require("mongodb"); import BluebirdPromise = require("bluebird"); -import { MongoClientStub } from "../../mocks/connectors/mongo/MongoClientStub"; -import { MongoCollection } from "../../../src/lib/storage/mongo/MongoCollection"; +import { MongoClientStub } from "../../connectors/mongo/MongoClientStub.spec"; +import { MongoCollection } from "./MongoCollection"; -describe("MongoCollection", function () { +describe("storage/mongo/MongoCollection", function () { let mongoCollectionStub: any; let findStub: Sinon.SinonStub; let findOneStub: Sinon.SinonStub; diff --git a/server/test/storage/mongo/MongoCollectionFactory.test.ts b/server/src/lib/storage/mongo/MongoCollectionFactory.spec.ts similarity index 66% rename from server/test/storage/mongo/MongoCollectionFactory.test.ts rename to server/src/lib/storage/mongo/MongoCollectionFactory.spec.ts index eab3da9a6..bd959cacb 100644 --- a/server/test/storage/mongo/MongoCollectionFactory.test.ts +++ b/server/src/lib/storage/mongo/MongoCollectionFactory.spec.ts @@ -1,9 +1,9 @@ import Assert = require("assert"); import Sinon = require("sinon"); -import { MongoClientStub } from "../../mocks/connectors/mongo/MongoClientStub"; -import { MongoCollectionFactory } from "../../../src/lib/storage/mongo/MongoCollectionFactory"; +import { MongoClientStub } from "../../connectors/mongo/MongoClientStub.spec"; +import { MongoCollectionFactory } from "./MongoCollectionFactory"; -describe("MongoCollectionFactory", function () { +describe("storage/mongo/MongoCollectionFactory", function () { let mongoClient: MongoClientStub; before(function() { diff --git a/server/test/storage/nedb/NedbCollection.test.ts b/server/src/lib/storage/nedb/NedbCollection.spec.ts similarity index 96% rename from server/test/storage/nedb/NedbCollection.test.ts rename to server/src/lib/storage/nedb/NedbCollection.spec.ts index 16c79b4ef..a69962b67 100644 --- a/server/test/storage/nedb/NedbCollection.test.ts +++ b/server/src/lib/storage/nedb/NedbCollection.spec.ts @@ -1,9 +1,9 @@ import Sinon = require("sinon"); import Assert = require("assert"); -import { NedbCollection } from "../../../src/lib/storage/nedb/NedbCollection"; +import { NedbCollection } from "./NedbCollection"; -describe("NedbCollection", function () { +describe("storage/nedb/NedbCollection", function () { describe("insert", function () { it("should insert one entry", function () { const nedbOptions = { diff --git a/server/test/storage/nedb/NedbCollectionFactory.test.ts b/server/src/lib/storage/nedb/NedbCollectionFactory.spec.ts similarity index 69% rename from server/test/storage/nedb/NedbCollectionFactory.test.ts rename to server/src/lib/storage/nedb/NedbCollectionFactory.spec.ts index d63390914..da90c661f 100644 --- a/server/test/storage/nedb/NedbCollectionFactory.test.ts +++ b/server/src/lib/storage/nedb/NedbCollectionFactory.spec.ts @@ -1,9 +1,9 @@ import Sinon = require("sinon"); import Assert = require("assert"); -import { NedbCollectionFactory } from "../../../src/lib/storage/nedb/NedbCollectionFactory"; +import { NedbCollectionFactory } from "./NedbCollectionFactory"; -describe("NedbCollectionFactory", function() { +describe("storage/nedb/NedbCollectionFactory", function() { it("should create a nedb collection", function() { const nedbOptions = { inMemoryOnly: true diff --git a/server/test/mocks/express.ts b/server/src/lib/stubs/express.spec.ts similarity index 100% rename from server/test/mocks/express.ts rename to server/src/lib/stubs/express.spec.ts diff --git a/server/test/mocks/ldapjs.ts b/server/src/lib/stubs/ldapjs.spec.ts similarity index 100% rename from server/test/mocks/ldapjs.ts rename to server/src/lib/stubs/ldapjs.spec.ts diff --git a/server/test/mocks/speakeasy.ts b/server/src/lib/stubs/speakeasy.spec.ts similarity index 100% rename from server/test/mocks/speakeasy.ts rename to server/src/lib/stubs/speakeasy.spec.ts diff --git a/server/test/mocks/u2f.ts b/server/src/lib/stubs/u2f.spec.ts similarity index 100% rename from server/test/mocks/u2f.ts rename to server/src/lib/stubs/u2f.spec.ts diff --git a/server/test/utils/DomainExtractor.test.ts b/server/src/lib/utils/DomainExtractor.spec.ts similarity index 85% rename from server/test/utils/DomainExtractor.test.ts rename to server/src/lib/utils/DomainExtractor.spec.ts index 80c971d2b..c5910d886 100644 --- a/server/test/utils/DomainExtractor.test.ts +++ b/server/src/lib/utils/DomainExtractor.spec.ts @@ -1,7 +1,7 @@ -import { DomainExtractor } from "../../src/lib/utils/DomainExtractor"; +import { DomainExtractor } from "./DomainExtractor"; import Assert = require("assert"); -describe("test DomainExtractor", function () { +describe("utils/DomainExtractor", function () { describe("test fromUrl", function () { it("should return domain from https url", function () { const domain = DomainExtractor.fromUrl("https://www.example.com/test/abc"); diff --git a/server/test/utils/HashGenerator.test.ts b/server/src/lib/utils/HashGenerator.spec.ts similarity index 86% rename from server/test/utils/HashGenerator.test.ts rename to server/src/lib/utils/HashGenerator.spec.ts index e1637c5fc..0a94e3292 100644 --- a/server/test/utils/HashGenerator.test.ts +++ b/server/src/lib/utils/HashGenerator.spec.ts @@ -1,7 +1,7 @@ import Assert = require("assert"); -import { HashGenerator } from "../../src/lib/utils/HashGenerator"; +import { HashGenerator } from "./HashGenerator"; -describe("test HashGenerator", function () { +describe("utils/HashGenerator", function () { it("should compute correct ssha512 (password)", function () { return HashGenerator.ssha512("password", "jgiCMRyGXzoqpxS3") .then(function (hash: string) { diff --git a/server/src/lib/web_server/Configurator.ts b/server/src/lib/web_server/Configurator.ts index 5c3034d82..6e404874a 100644 --- a/server/src/lib/web_server/Configurator.ts +++ b/server/src/lib/web_server/Configurator.ts @@ -1,4 +1,4 @@ -import { AppConfiguration } from "../configuration/Configuration"; +import { Configuration } from "../configuration/schema/Configuration"; import { GlobalDependencies } from "../../../types/Dependencies"; import { SessionConfigurationBuilder } from "../configuration/SessionConfigurationBuilder"; @@ -20,7 +20,7 @@ const VIEW_ENGINE = "view engine"; const PUG = "pug"; export class Configurator { - static configure(config: AppConfiguration, + static configure(config: Configuration, app: Express.Application, vars: ServerVariables, deps: GlobalDependencies): void { diff --git a/server/src/lib/web_server/middlewares/RequireTwoFactorEnabled.ts b/server/src/lib/web_server/middlewares/RequireTwoFactorEnabled.ts index c97b57d99..6f8db4058 100644 --- a/server/src/lib/web_server/middlewares/RequireTwoFactorEnabled.ts +++ b/server/src/lib/web_server/middlewares/RequireTwoFactorEnabled.ts @@ -4,7 +4,7 @@ import ErrorReplies = require("../../ErrorReplies"); import { IRequestLogger } from "../../logging/IRequestLogger"; import { MethodCalculator } from "../../authentication/MethodCalculator"; import { AuthenticationMethodsConfiguration } from - "../../configuration/Configuration"; + "../../configuration/schema/AuthenticationMethodsConfiguration"; export class RequireTwoFactorEnabled { static middleware(logger: IRequestLogger, diff --git a/server/test/configuration/LdapConfigurationAdaptation.test.ts b/server/test/configuration/LdapConfigurationAdaptation.test.ts deleted file mode 100644 index bfcc8fc00..000000000 --- a/server/test/configuration/LdapConfigurationAdaptation.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import * as Assert from "assert"; -import { UserConfiguration, LdapConfiguration } from "../../src/lib/configuration/Configuration"; -import { ConfigurationParser } from "../../src/lib/configuration/ConfigurationParser"; - -describe("test ldap configuration adaptation", function () { - function build_yaml_config(): UserConfiguration { - const yaml_config: UserConfiguration = { - port: 8080, - ldap: { - url: "http://ldap", - base_dn: "dc=example,dc=com", - additional_users_dn: "ou=users", - additional_groups_dn: "ou=groups", - user: "user", - password: "pass" - }, - session: { - domain: "example.com", - secret: "secret", - expiration: 40000 - }, - storage: { - local: { - path: "/mydirectory" - } - }, - regulation: { - max_retries: 3, - ban_time: 5 * 60, - find_time: 5 * 60, - }, - logs_level: "debug", - notifier: { - email: { - username: "user", - password: "password", - sender: "admin@example.com", - service: "email" - } - } - }; - return yaml_config; - } - - it("should adapt correctly while user only specify mandatory fields", function () { - const userConfig = build_yaml_config(); - userConfig.ldap = { - url: "http://ldap", - base_dn: "dc=example,dc=com", - user: "admin", - password: "password" - }; - - const config = ConfigurationParser.parse(userConfig); - const expectedConfig: LdapConfiguration = { - url: "http://ldap", - users_dn: "dc=example,dc=com", - users_filter: "cn={0}", - groups_dn: "dc=example,dc=com", - groups_filter: "member={dn}", - group_name_attribute: "cn", - mail_attribute: "mail", - user: "admin", - password: "password" - }; - - Assert.deepEqual(config.ldap, expectedConfig); - }); - - it("should adapt correctly while user specify every fields", function () { - const userConfig = build_yaml_config(); - userConfig.ldap = { - url: "http://ldap-server", - base_dn: "dc=example,dc=com", - additional_users_dn: "ou=users", - users_filter: "uid={0}", - additional_groups_dn: "ou=groups", - groups_filter: "uniqueMember={0}", - mail_attribute: "email", - group_name_attribute: "groupName", - user: "admin2", - password: "password2" - }; - - const config = ConfigurationParser.parse(userConfig); - const expectedConfig: LdapConfiguration = { - url: "http://ldap-server", - users_dn: "ou=users,dc=example,dc=com", - users_filter: "uid={0}", - groups_dn: "ou=groups,dc=example,dc=com", - groups_filter: "uniqueMember={0}", - mail_attribute: "email", - group_name_attribute: "groupName", - user: "admin2", - password: "password2" - }; - - Assert.deepEqual(config.ldap, expectedConfig); - }); -}); diff --git a/server/test/configuration/Validator.test.ts b/server/test/configuration/Validator.test.ts deleted file mode 100644 index e3cd48da7..000000000 --- a/server/test/configuration/Validator.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { Validator } from "../../src/lib/configuration/Validator"; -import Assert = require("assert"); - -describe("test validator", function () { - it("should validate wrong user configurations", function () { - // Some examples - Assert.deepStrictEqual(Validator.isValid({}), [ - "data should have required property 'ldap'", - "data should have required property 'notifier'", - "data should have required property 'regulation'", - "data should have required property 'session'", - "data should have required property 'storage'" - ]); - - Assert.deepStrictEqual(Validator.isValid({ - ldap: {}, - notifier: {}, - regulation: {}, - session: {}, - storage: {} - }), [ - "data.ldap should have required property 'base_dn'", - "data.ldap should have required property 'password'", - "data.ldap should have required property 'url'", - "data.ldap should have required property 'user'", - "data.regulation should have required property 'ban_time'", - "data.regulation should have required property 'find_time'", - "data.regulation should have required property 'max_retries'", - "data.session should have required property 'domain'", - "data.session should have required property 'secret'", - "Storage must be either 'local' or 'mongo'", - "A notifier needs to be declared when server is used with two-factor" - ]); - - Assert.deepStrictEqual(Validator.isValid({ - ldap: { - base_dn: "dc=example,dc=com", - password: "password", - url: "ldap://ldap", - user: "user" - }, - notifier: { - abcd: [] - }, - regulation: { - ban_time: 120, - find_time: 30, - max_retries: 3 - }, - session: { - secret: "unsecure_secret", - domain: "mydomain" - }, - storage: { - abc: {} - } - }), [ - "data.storage has unknown key 'abc'", - "Notifier must be either 'filesystem', 'email' or 'smtp'" - ]); - }); - - it("should validate correct user configurations", function () { - Assert.deepStrictEqual(Validator.isValid({ - ldap: { - base_dn: "dc=example,dc=com", - password: "password", - url: "ldap://ldap", - user: "user" - }, - notifier: { - email: { - username: "user@gmail.com", - password: "pass", - sender: "admin@example.com", - service: "gmail" - } - }, - regulation: { - ban_time: 120, - find_time: 30, - max_retries: 3 - }, - session: { - secret: "unsecure_secret", - domain: "mydomain" - }, - storage: { - local: { - path: "/var/lib/authelia" - } - } - }), []); - }); - - it("should return false when notifier is not defined while there is at least \ -one second factor enabled sub-domain", function () { - const options1 = { - ldap: { - base_dn: "dc=example,dc=com", - password: "password", - url: "ldap://ldap", - user: "user" - }, - authentication_methods: { - default_method: "two_factor" - }, - notifier: {}, - regulation: { - ban_time: 120, - find_time: 30, - max_retries: 3 - }, - session: { - secret: "unsecure_secret", - domain: "mydomain" - }, - storage: { - local: { - path: "/var/lib/authelia" - } - } - }; - const options2 = { - ldap: { - base_dn: "dc=example,dc=com", - password: "password", - url: "ldap://ldap", - user: "user" - }, - authentication_methods: { - default_method: "two_factor" - }, - notifier: { - email: { - username: "user@gmail.com", - password: "pass", - sender: "admin@example.com", - service: "gmail" - } - }, - regulation: { - ban_time: 120, - find_time: 30, - max_retries: 3 - }, - session: { - secret: "unsecure_secret", - domain: "mydomain" - }, - storage: { - local: { - path: "/var/lib/authelia" - } - } - }; - const options3 = { - ldap: { - base_dn: "dc=example,dc=com", - password: "password", - url: "ldap://ldap", - user: "user" - }, - authentication_methods: { - default_method: "single_factor" - }, - notifier: {}, - regulation: { - ban_time: 120, - find_time: 30, - max_retries: 3 - }, - session: { - secret: "unsecure_secret", - domain: "mydomain" - }, - storage: { - local: { - path: "/var/lib/authelia" - } - } - }; - Assert.deepStrictEqual(Validator.isValid(options1), ["A notifier needs to be declared when server is used with two-factor"]); - Assert.deepStrictEqual(Validator.isValid(options2), []); - Assert.deepStrictEqual(Validator.isValid(options3), []); - }); -}); \ No newline at end of file diff --git a/server/test/configuration/adapters/ACLAdapter.test.ts b/server/test/configuration/adapters/ACLAdapter.test.ts deleted file mode 100644 index 01bb32585..000000000 --- a/server/test/configuration/adapters/ACLAdapter.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { ACLAdapter } from "../../../src/lib/configuration/adapters/ACLAdapter"; -import Assert = require("assert"); - -describe("test ACL configuration adapter", function () { - - describe("bad default_policy", function () { - it("should adapt a configuration missing default_policy", function () { - const userConfiguration: any = { - any: [], - groups: {}, - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - - it("should adapt a configuration with bad default_policy value", function () { - const userConfiguration: any = { - default_policy: "anything", // it should be 'allow' or 'deny' - any: [], - groups: {}, - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - - it("should adapt a configuration with bad default_policy type", function () { - const userConfiguration: any = { - default_policy: {}, // it should be 'allow' or 'deny' - any: [], - groups: {}, - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - }); - - describe("bad any", function () { - it("should adapt a configuration missing any key", function () { - const userConfiguration: any = { - default_policy: "deny", - groups: {}, - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - - it("should adapt a configuration with any not being an array", function () { - const userConfiguration: any = { - default_policy: "deny", - any: "abc", - groups: {}, - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - }); - - describe("bad groups", function () { - it("should adapt a configuration missing groups key", function () { - const userConfiguration: any = { - default_policy: "deny", - any: [], - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - - it("should adapt configuration with groups being of wrong type", function () { - const userConfiguration: any = { - default_policy: "deny", - any: [], - groups: [], - users: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - }); - - describe("bad users", function () { - it("should adapt a configuration missing users key", function () { - const userConfiguration: any = { - default_policy: "deny", - any: [], - groups: {} - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - - it("should adapt a configuration with users being of wrong type", function () { - const userConfiguration: any = { - default_policy: "deny", - any: [], - groups: {}, - users: [] - }; - - const appConfiguration = ACLAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_policy: "deny", - any: [], - groups: {}, - users: {} - }); - }); - }); -}); \ No newline at end of file diff --git a/server/test/configuration/adapters/AuthenticationMethodsAdapter.test.ts b/server/test/configuration/adapters/AuthenticationMethodsAdapter.test.ts deleted file mode 100644 index 3e88e5721..000000000 --- a/server/test/configuration/adapters/AuthenticationMethodsAdapter.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { AuthenticationMethodsAdapter } from "../../../src/lib/configuration/adapters/AuthenticationMethodsAdapter"; -import Assert = require("assert"); - -describe("test authentication methods configuration adapter", function () { - describe("no authentication methods defined", function () { - it("should adapt a configuration when no authentication methods config is defined", function () { - const userConfiguration: any = undefined; - - const appConfiguration = AuthenticationMethodsAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_method: "two_factor", - per_subdomain_methods: {} - }); - }); - }); - - describe("partial authentication methods config", function() { - it("should adapt a configuration when default_method is not defined", function () { - const userConfiguration: any = { - per_subdomain_methods: { - "example.com": "single_factor" - } - }; - - const appConfiguration = AuthenticationMethodsAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_method: "two_factor", - per_subdomain_methods: { - "example.com": "single_factor" - } - }); - }); - - it("should adapt a configuration when per_subdomain_methods is not defined", function () { - const userConfiguration: any = { - default_method: "single_factor" - }; - - const appConfiguration = AuthenticationMethodsAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_method: "single_factor", - per_subdomain_methods: {} - }); - }); - - it("should adapt a configuration when per_subdomain_methods has wrong type", function () { - const userConfiguration: any = { - default_method: "single_factor", - per_subdomain_methods: [] - }; - - const appConfiguration = AuthenticationMethodsAdapter.adapt(userConfiguration); - Assert.deepStrictEqual(appConfiguration, { - default_method: "single_factor", - per_subdomain_methods: {} - }); - }); - }); -}); diff --git a/server/test/mocks/AuthenticationRegulator.ts b/server/test/mocks/AuthenticationRegulator.ts deleted file mode 100644 index 2d789d94e..000000000 --- a/server/test/mocks/AuthenticationRegulator.ts +++ /dev/null @@ -1,15 +0,0 @@ - -import sinon = require("sinon"); - - -export interface AuthenticationRegulatorMock { - mark: sinon.SinonStub; - regulate: sinon.SinonStub; -} - -export function AuthenticationRegulatorMock() { - return { - mark: sinon.stub(), - regulate: sinon.stub() - }; -} diff --git a/server/test/mocks/IdentityValidator.ts b/server/test/mocks/IdentityValidator.ts deleted file mode 100644 index 3fbe44dc3..000000000 --- a/server/test/mocks/IdentityValidator.ts +++ /dev/null @@ -1,39 +0,0 @@ - -import sinon = require("sinon"); -import { IdentityValidable } from "../../src/lib/IdentityCheckMiddleware"; -import express = require("express"); -import BluebirdPromise = require("bluebird"); -import { Identity } from "../../types/Identity"; - - -export interface IdentityValidableMock { - challenge: sinon.SinonStub; - preValidationInit: sinon.SinonStub; - preValidationResponse: sinon.SinonStub | sinon.SinonSpy; - postValidationInit: sinon.SinonStub; - postValidationResponse: sinon.SinonStub | sinon.SinonSpy; - mailSubject: sinon.SinonStub; -} - -export function IdentityValidableMock() { - return { - challenge: sinon.stub(), - preValidationInit: sinon.stub(), - preValidationResponse: sinon.stub(), - postValidationInit: sinon.stub(), - postValidationResponse: sinon.stub(), - mailSubject: sinon.stub() - }; -} - -export interface IdentityValidatorMock { - consume_token: sinon.SinonStub; - issue_token: sinon.SinonStub; -} - -export function IdentityValidatorMock() { - return { - consume_token: sinon.stub(), - issue_token: sinon.stub() - }; -} \ No newline at end of file diff --git a/server/test/mocks/Notifier.ts b/server/test/mocks/Notifier.ts deleted file mode 100644 index 951604088..000000000 --- a/server/test/mocks/Notifier.ts +++ /dev/null @@ -1,12 +0,0 @@ - -import sinon = require("sinon"); - -export interface NotifierMock { - notify: sinon.SinonStub; -} - -export function NotifierMock(): NotifierMock { - return { - notify: sinon.stub() - }; -} diff --git a/server/test/mocks/RegulatorStub.ts b/server/test/mocks/RegulatorStub.ts deleted file mode 100644 index 203c0e23a..000000000 --- a/server/test/mocks/RegulatorStub.ts +++ /dev/null @@ -1,21 +0,0 @@ -import Sinon = require("sinon"); -import BluebirdPromise = require("bluebird"); -import { IRegulator } from "../../src/lib/regulation/IRegulator"; - -export class RegulatorStub implements IRegulator { - markStub: Sinon.SinonStub; - regulateStub: Sinon.SinonStub; - - constructor() { - this.markStub = Sinon.stub(); - this.regulateStub = Sinon.stub(); - } - - mark(userId: string, isAuthenticationSuccessful: boolean): BluebirdPromise { - return this.markStub(userId, isAuthenticationSuccessful); - } - - regulate(userId: string): BluebirdPromise { - return this.regulateStub(userId); - } -} \ No newline at end of file diff --git a/server/test/mocks/TOTPValidator.ts b/server/test/mocks/TOTPValidator.ts deleted file mode 100644 index 56434c79b..000000000 --- a/server/test/mocks/TOTPValidator.ts +++ /dev/null @@ -1,12 +0,0 @@ - -import sinon = require("sinon"); - -export interface TOTPValidatorMock { - validate: sinon.SinonStub; -} - -export function TOTPValidatorMock(): TOTPValidatorMock { - return { - validate: sinon.stub() - }; -} diff --git a/server/tsconfig.json b/server/tsconfig.json index 0bb4d62ff..ebe98c5ed 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -15,10 +15,7 @@ ] } }, - "include": [ - "src/**/*" - ], "exclude": [ - "test/**/*" + "src/**/*.spec.ts" ] } diff --git a/test/features/step_definitions/authentication.ts b/test/features/step_definitions/authentication.ts index 4fad123a9..7c12e4da0 100644 --- a/test/features/step_definitions/authentication.ts +++ b/test/features/step_definitions/authentication.ts @@ -64,7 +64,7 @@ When("I visit {string} and get redirected {string}", const that = this; return this.driver.get(url) .then(function () { - return that.driver.wait(seleniumWebdriver.until.urlIs(redirectUrl), 6000); + return that.driver.wait(seleniumWebdriver.until.urlIs(redirectUrl), 5000); }); }); @@ -96,4 +96,4 @@ Then("the following endpoints reply with:", function (dataTable: TableDefinition promises.push(endpointReplyWith(this, url, method, code)); } return BluebirdPromise.all(promises); -}); \ No newline at end of file +}); diff --git a/test/features/support/world.ts b/test/features/support/world.ts index b848f643d..1a27bd250 100644 --- a/test/features/support/world.ts +++ b/test/features/support/world.ts @@ -34,7 +34,7 @@ function CustomWorld() { this.getErrorPage = function (code: number) { const that = this; - return this.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.tagName("h1")), 2000) + return this.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.tagName("h1")), 5000) .then(function () { return that.driver .findElement(seleniumWebdriver.By.tagName("h1")).getText(); @@ -51,7 +51,7 @@ function CustomWorld() { this.clickOnButton = function (buttonText: string) { const that = this; - return this.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.tagName("button")), 2000) + return this.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.tagName("button")), 5000) .then(function () { return that.driver .findElement(seleniumWebdriver.By.tagName("button")) @@ -73,7 +73,7 @@ function CustomWorld() { }; this.loginWithUserPassword = function (username: string, password: string) { - return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.id("username")), 4000) + return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.id("username")), 5000) .then(function () { return that.driver.findElement(seleniumWebdriver.By.id("username")) .sendKeys(username); @@ -114,7 +114,7 @@ function CustomWorld() { }; this.registerTotpSecret = function (totpSecretHandle: string) { - return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.className("register-totp")), 4000) + return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.className("register-totp")), 5000) .then(function () { return that.driver.findElement(seleniumWebdriver.By.className("register-totp")).click(); })