diff --git a/.travis.yml b/.travis.yml
index b5052c4fe..2ec3f9f54 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,23 +1,37 @@
+dist: trusty
language: node_js
+sudo: required
node_js:
-- node
+ - "7"
services:
-- docker
-- ntp
+ - docker
+ - ntp
addons:
+ chrome: stable
apt:
+ sources:
+ - google-chrome
packages:
- - libgif-dev
+ - libgif-dev
+ - google-chrome-stable
hosts:
- auth.test.local
- home.test.local
+ - public.test.local
- secret.test.local
- secret1.test.local
- secret2.test.local
- mx1.mail.test.local
- mx2.mail.test.local
-before_install: npm install -g npm@'>=2.13.5'
+before_install:
+ - npm install -g npm@'>=2.13.5'
+
+before_script:
+ - export DISPLAY=:99.0
+ - sh -e /etc/init.d/xvfb start
+ - sleep 3
+
script:
- ./scripts/travis.sh
diff --git a/Gruntfile.js b/Gruntfile.js
index ba2c93e8f..c5b590bb7 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -12,17 +12,13 @@ module.exports = function (grunt) {
cmd: "./node_modules/.bin/tslint",
args: ['-c', 'tslint.json', '-p', 'tsconfig.json']
},
- "test": {
+ "unit-tests": {
cmd: "./node_modules/.bin/mocha",
args: ['--compilers', 'ts:ts-node/register', '--recursive', 'test/unit']
},
- "test-int": {
- cmd: "./node_modules/.bin/mocha",
- args: ['--compilers', 'ts:ts-node/register', '--recursive', 'test/integration']
- },
- "test-system": {
- cmd: "./node_modules/.bin/mocha",
- args: ['--compilers', 'ts:ts-node/register', '--recursive', 'test/system']
+ "integration-tests": {
+ cmd: "./node_modules/.bin/cucumber-js",
+ args: ["--compiler", "ts:ts-node/register", "./test/features"]
},
"docker-build": {
cmd: "docker",
@@ -165,5 +161,8 @@ module.exports = function (grunt) {
grunt.registerTask('docker-build', ['run:docker-build']);
grunt.registerTask('docker-restart', ['run:docker-restart']);
- grunt.registerTask('test', ['run:test']);
+ grunt.registerTask('unit-tests', ['run:unit-tests']);
+ grunt.registerTask('integration-tests', ['run:unit-tests']);
+
+ grunt.registerTask('test', ['unit-tests']);
};
diff --git a/README.md b/README.md
index 669960862..aa8d2d07f 100644
--- a/README.md
+++ b/README.md
@@ -91,6 +91,7 @@ Make sure you don't have anything listening on port 8080.
Add the following lines to your **/etc/hosts** to alias multiple subdomains so that nginx can redirect request to the correct virtual host.
+ 127.0.0.1 public.test.local
127.0.0.1 secret.test.local
127.0.0.1 secret1.test.local
127.0.0.1 secret2.test.local
diff --git a/config.template.yml b/config.template.yml
index 29625f84f..638b59202 100644
--- a/config.template.yml
+++ b/config.template.yml
@@ -48,7 +48,7 @@ ldap:
# beginning of the pattern.
access_control:
default:
- - home.test.local
+ - public.test.local
groups:
admin:
- '*.test.local'
@@ -77,9 +77,13 @@ session:
host: redis
port: 6379
-# The directory where the DB files will be saved
-store_directory: /var/lib/authelia/store
-
+storage:
+ # The directory where the DB files will be saved
+ # local: /var/lib/authelia/store
+
+ # Settings to connect to mongo server
+ mongo:
+ url: mongodb://mongo/authelia
# Notifications are sent to users when they require a password reset, a u2f
# registration or a TOTP registration.
diff --git a/example/ldap/base.ldif b/example/ldap/base.ldif
index f1fbdb887..06e962c04 100644
--- a/example/ldap/base.ldif
+++ b/example/ldap/base.ldif
@@ -45,3 +45,10 @@ mail: bob.dylan@example.com
sn: Bob Dylan
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
+dn: cn=james,ou=users,dc=example,dc=com
+cn: james
+objectclass: inetOrgPerson
+objectclass: top
+mail: james.dean@example.com
+sn: James Dean
+userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
diff --git a/example/mongo/docker-compose.yml b/example/mongo/docker-compose.yml
new file mode 100644
index 000000000..3af27f215
--- /dev/null
+++ b/example/mongo/docker-compose.yml
@@ -0,0 +1,6 @@
+version: '2'
+services:
+ mongo:
+ image: mongo:3.4
+ networks:
+ - example-network
diff --git a/example/nginx/html/index.html b/example/nginx/html/index.html
index 8f76ab5b3..f009d515e 100644
--- a/example/nginx/html/index.html
+++ b/example/nginx/html/index.html
@@ -9,6 +9,9 @@
You need to log in to access the secret!
Try to access it via one of the following links.
+ -
+ public.test.local
+
-
secret.test.local
@@ -18,9 +21,6 @@
-
secret2.test.local
- -
- home.test.local
-
-
mx1.mail.test.local
@@ -45,7 +45,7 @@
- Default policy
- - home.test.local
+ - public.test.local
- Groups policy
diff --git a/example/nginx/nginx.conf b/example/nginx/nginx.conf
index 53e4e3b8f..c9688f8f3 100644
--- a/example/nginx/nginx.conf
+++ b/example/nginx/nginx.conf
@@ -53,7 +53,8 @@ http {
root /usr/share/nginx/html;
server_name secret1.test.local secret2.test.local secret.test.local
- home.test.local mx1.mail.test.local mx2.mail.test.local;
+ home.test.local mx1.mail.test.local mx2.mail.test.local
+ public.test.local;
ssl on;
ssl_certificate /etc/ssl/server.crt;
diff --git a/example/redis/docker-compose.yml b/example/redis/docker-compose.yml
index 5e4153624..62cc6edd1 100644
--- a/example/redis/docker-compose.yml
+++ b/example/redis/docker-compose.yml
@@ -1,6 +1,6 @@
version: '2'
services:
redis:
- image: redis
+ image: redis:4.0-alpine
networks:
- example-network
diff --git a/package.json b/package.json
index 0ea74f552..33c880322 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"authelia": "dist/src/server/index.js"
},
"scripts": {
- "test": "./node_modules/.bin/grunt test",
+ "test": "./node_modules/.bin/grunt unit-tests",
"cover": "NODE_ENV=test nyc npm t",
"serve": "node dist/server/index.js"
},
@@ -24,7 +24,6 @@
"title": "Authelia API documentation"
},
"dependencies": {
- "@types/cors": "^2.8.1",
"bluebird": "^3.4.7",
"body-parser": "^1.15.2",
"connect-redis": "^3.3.0",
@@ -33,6 +32,7 @@
"express": "^4.14.0",
"express-session": "^1.14.2",
"ldapjs": "^1.0.1",
+ "mongodb": "^2.2.30",
"nedb": "^1.8.0",
"nodemailer": "^4.0.1",
"object-path": "^0.11.3",
@@ -47,6 +47,8 @@
"@types/bluebird": "^3.5.4",
"@types/body-parser": "^1.16.3",
"@types/connect-redis": "0.0.6",
+ "@types/cors": "^2.8.1",
+ "@types/cucumber": "^2.0.1",
"@types/ejs": "^2.3.33",
"@types/express": "^4.0.35",
"@types/express-session": "0.0.32",
@@ -55,6 +57,7 @@
"@types/ldapjs": "^1.0.0",
"@types/mocha": "^2.2.41",
"@types/mockdate": "^2.0.0",
+ "@types/mongodb": "^2.2.7",
"@types/nedb": "^1.8.3",
"@types/nodemailer": "^1.3.32",
"@types/object-path": "^0.9.28",
@@ -62,6 +65,7 @@
"@types/query-string": "^4.3.1",
"@types/randomstring": "^1.1.5",
"@types/request": "0.0.46",
+ "@types/selenium-webdriver": "^3.0.4",
"@types/sinon": "^2.2.1",
"@types/speakeasy": "^2.0.1",
"@types/tmp": "0.0.33",
@@ -69,6 +73,8 @@
"@types/yamljs": "^0.2.30",
"apidoc": "^0.17.6",
"browserify": "^14.3.0",
+ "chromedriver": "^2.31.0",
+ "cucumber": "^2.3.1",
"grunt": "^1.0.1",
"grunt-browserify": "^5.0.0",
"grunt-contrib-concat": "^1.0.1",
@@ -80,7 +86,7 @@
"jquery": "^3.2.1",
"js-logger": "^1.3.0",
"jsdom": "^11.0.0",
- "mocha": "^3.2.0",
+ "mocha": "^3.4.2",
"mockdate": "^2.0.1",
"notifyjs-browser": "^0.4.2",
"nyc": "^10.3.2",
@@ -88,11 +94,12 @@
"proxyquire": "^1.8.0",
"query-string": "^4.3.4",
"request": "^2.81.0",
+ "selenium-webdriver": "^3.5.0",
"should": "^11.1.1",
- "sinon": "^1.17.6",
+ "sinon": "^2.3.8",
"sinon-promise": "^0.1.3",
"tmp": "0.0.31",
- "ts-node": "^3.0.4",
+ "ts-node": "^3.3.0",
"tslint": "^5.2.0",
"typescript": "^2.3.2",
"u2f-api": "0.0.9",
@@ -107,7 +114,8 @@
"doc",
"src/types",
"dist",
- "test"
+ "test",
+ "src/**/*.d.ts"
],
"extension": [
".ts"
diff --git a/scripts/dc-dev.sh b/scripts/dc-dev.sh
index 4d4bff935..b9cd0630b 100755
--- a/scripts/dc-dev.sh
+++ b/scripts/dc-dev.sh
@@ -2,4 +2,11 @@
set -e
-docker-compose -f docker-compose.base.yml -f docker-compose.yml -f docker-compose.dev.yml -f example/redis/docker-compose.yml -f example/nginx/docker-compose.yml -f example/ldap/docker-compose.yml -f test/integration/docker-compose.yml $*
+docker-compose \
+ -f docker-compose.base.yml \
+ -f docker-compose.yml \
+ -f docker-compose.dev.yml \
+ -f example/mongo/docker-compose.yml \
+ -f example/redis/docker-compose.yml \
+ -f example/nginx/docker-compose.yml \
+ -f example/ldap/docker-compose.yml $*
diff --git a/scripts/example/dc-example.sh b/scripts/example/dc-example.sh
index 82c77f066..640976d62 100755
--- a/scripts/example/dc-example.sh
+++ b/scripts/example/dc-example.sh
@@ -2,4 +2,10 @@
set -e
-docker-compose -f docker-compose.base.yml -f docker-compose.yml -f example/redis/docker-compose.yml -f example/nginx/docker-compose.yml -f example/ldap/docker-compose.yml -f test/integration/docker-compose.yml $*
+docker-compose \
+ -f docker-compose.base.yml \
+ -f docker-compose.yml \
+ -f example/mongo/docker-compose.yml \
+ -f example/redis/docker-compose.yml \
+ -f example/nginx/docker-compose.yml \
+ -f example/ldap/docker-compose.yml $*
diff --git a/scripts/example/deploy-example.sh b/scripts/example/deploy-example.sh
index 4c50d935b..bae41949c 100755
--- a/scripts/example/deploy-example.sh
+++ b/scripts/example/deploy-example.sh
@@ -3,4 +3,4 @@
DC_SCRIPT=./scripts/example/dc-example.sh
$DC_SCRIPT build
-$DC_SCRIPT up -d redis openldap authelia nginx
+$DC_SCRIPT up -d mongo redis openldap authelia nginx
diff --git a/scripts/integration-tests.sh b/scripts/integration-tests.sh
index 4b33a6361..10d4973dd 100755
--- a/scripts/integration-tests.sh
+++ b/scripts/integration-tests.sh
@@ -1,9 +1,10 @@
#!/bin/bash
DC_SCRIPT=./scripts/example/dc-example.sh
+EXPECTED_SERVICES_COUNT=5
start_services() {
- $DC_SCRIPT up -d redis openldap authelia nginx nginx-tests
+ $DC_SCRIPT up -d mongo redis openldap authelia nginx
sleep 3
}
@@ -26,39 +27,12 @@ expect_services_count() {
}
run_integration_tests() {
- echo "Prepare nginx-test configuration"
- cat example/nginx/nginx.conf | sed 's/listen 443 ssl/listen 8080 ssl/g' | dd of="test/integration/nginx.conf"
-
- echo "Build services images..."
- $DC_SCRIPT build
-
echo "Start services..."
start_services
- docker ps -a
+ expect_services_count $EXPECTED_SERVICES_COUNT
- echo "Display services logs..."
- $DC_SCRIPT logs redis
- $DC_SCRIPT logs openldap
- $DC_SCRIPT logs nginx
- $DC_SCRIPT logs nginx-tests
- $DC_SCRIPT logs authelia
-
- echo "Check number of services"
- expect_services_count 5
-
- echo "Run integration tests..."
- $DC_SCRIPT run --rm integration-tests
-
- echo "Shutdown services..."
- shut_services
-}
-
-run_system_tests() {
- echo "Start services..."
- start_services
- expect_services_count 5
-
- ./node_modules/.bin/mocha --compilers ts:ts-node/register --recursive test/system
+ sleep 5
+ ./node_modules/.bin/grunt run:integration-tests
shut_services
}
@@ -67,7 +41,7 @@ run_other_tests() {
npm install --only=dev
./node_modules/.bin/grunt build-dist
./scripts/example/deploy-example.sh
- expect_services_count 4
+ expect_services_count 5
}
@@ -79,11 +53,8 @@ set -e
echo "Make sure services are not already running"
shut_services
-# Prepare & run integration tests
-run_integration_tests
-
# Prepare & test example from end user perspective
-run_system_tests
+run_integration_tests
# Other tests like executing the deployment script
run_other_tests
diff --git a/src/client/firstfactor/FirstFactorValidator.ts b/src/client/firstfactor/FirstFactorValidator.ts
index 369cd535c..07a27f7d6 100644
--- a/src/client/firstfactor/FirstFactorValidator.ts
+++ b/src/client/firstfactor/FirstFactorValidator.ts
@@ -13,7 +13,7 @@ export function validate(username: string, password: string, $: JQueryStatic): B
})
.fail(function (xhr: JQueryXHR, textStatus: string) {
if (xhr.status == 401)
- reject(new Error("Authetication failed. Please check your credentials"));
+ reject(new Error("Authetication failed. Please check your credentials."));
reject(new Error(textStatus));
});
});
diff --git a/src/client/reset-password/reset-password-request.ts b/src/client/reset-password/reset-password-request.ts
index e390fbc5e..606309773 100644
--- a/src/client/reset-password/reset-password-request.ts
+++ b/src/client/reset-password/reset-password-request.ts
@@ -30,7 +30,7 @@ export default function(window: Window, $: JQueryStatic) {
requestPasswordReset(username)
.then(function () {
- $.notify("An email has been sent. Click on the link to change your password", "success");
+ $.notify("An email has been sent. Click on the link to change your password.", "success");
setTimeout(function () {
window.location.replace(Endpoints.FIRST_FACTOR_GET);
}, 1000);
diff --git a/src/server/lib/AuthenticationRegulator.ts b/src/server/lib/AuthenticationRegulator.ts
index d15c6d166..b3319b4e9 100644
--- a/src/server/lib/AuthenticationRegulator.ts
+++ b/src/server/lib/AuthenticationRegulator.ts
@@ -1,43 +1,40 @@
import * as BluebirdPromise from "bluebird";
import exceptions = require("./Exceptions");
+import { UserDataStore } from "./storage/UserDataStore";
+import { AuthenticationTraceDocument } from "./storage/AuthenticationTraceDocument";
-const REGULATION_TRACE_TYPE = "regulation";
const MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE = 3;
-interface DatedDocument {
- date: Date;
-}
-
export class AuthenticationRegulator {
- private _user_data_store: any;
- private _lock_time_in_seconds: number;
+ private userDataStore: UserDataStore;
+ private lockTimeInSeconds: number;
- constructor(user_data_store: any, lock_time_in_seconds: number) {
- this._user_data_store = user_data_store;
- this._lock_time_in_seconds = lock_time_in_seconds;
+ constructor(userDataStore: any, lockTimeInSeconds: number) {
+ this.userDataStore = userDataStore;
+ this.lockTimeInSeconds = lockTimeInSeconds;
}
// Mark authentication
- mark(userid: string, is_success: boolean): BluebirdPromise {
- return this._user_data_store.save_authentication_trace(userid, REGULATION_TRACE_TYPE, is_success);
+ mark(userId: string, isAuthenticationSuccessful: boolean): BluebirdPromise {
+ return this.userDataStore.saveAuthenticationTrace(userId, isAuthenticationSuccessful);
}
- regulate(userid: string): BluebirdPromise {
- return this._user_data_store.get_last_authentication_traces(userid, REGULATION_TRACE_TYPE, false, 3)
- .then((docs: Array) => {
- if (docs.length < MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE) {
- // less than the max authorized number of authentication in time range, thus authorizing access
+ regulate(userId: string): BluebirdPromise {
+ return this.userDataStore.retrieveLatestAuthenticationTraces(userId, false, 3)
+ .then((docs: AuthenticationTraceDocument[]) => {
+ if (docs.length < MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE) {
+ // less than the max authorized number of authentication in time range, thus authorizing access
+ return BluebirdPromise.resolve();
+ }
+
+ const oldestDocument = docs[MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE - 1];
+ const noLockMinDate = new Date(new Date().getTime() - this.lockTimeInSeconds * 1000);
+ if (oldestDocument.date > noLockMinDate) {
+ throw new exceptions.AuthenticationRegulationError("Max number of authentication. Please retry in few minutes.");
+ }
+
return BluebirdPromise.resolve();
- }
-
- const oldest_doc = docs[MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE - 1];
- const no_lock_min_date = new Date(new Date().getTime() - this._lock_time_in_seconds * 1000);
- if (oldest_doc.date > no_lock_min_date) {
- throw new exceptions.AuthenticationRegulationError("Max number of authentication. Please retry in few minutes.");
- }
-
- return BluebirdPromise.resolve();
- });
+ });
}
}
diff --git a/src/server/lib/FirstFactorValidator.ts b/src/server/lib/FirstFactorValidator.ts
index 348b6840a..d82a1ad2e 100644
--- a/src/server/lib/FirstFactorValidator.ts
+++ b/src/server/lib/FirstFactorValidator.ts
@@ -6,9 +6,9 @@ import Exceptions = require("./Exceptions");
import AuthenticationSession = require("./AuthenticationSession");
export function validate(req: express.Request): BluebirdPromise {
- const authSession = AuthenticationSession.get(req);
- if (!authSession.userid || !authSession.first_factor)
- return BluebirdPromise.reject(new Exceptions.FirstFactorValidationError("First factor has not been validated yet."));
+ const authSession = AuthenticationSession.get(req);
+ if (!authSession.userid || !authSession.first_factor)
+ return BluebirdPromise.reject(new Exceptions.FirstFactorValidationError("First factor has not been validated yet."));
- return BluebirdPromise.resolve();
+ return BluebirdPromise.resolve();
}
\ No newline at end of file
diff --git a/src/server/lib/IdentityCheckMiddleware.ts b/src/server/lib/IdentityCheckMiddleware.ts
index 41cdd1133..8523f9f05 100644
--- a/src/server/lib/IdentityCheckMiddleware.ts
+++ b/src/server/lib/IdentityCheckMiddleware.ts
@@ -6,15 +6,15 @@ import util = require("util");
import Exceptions = require("./Exceptions");
import fs = require("fs");
import ejs = require("ejs");
-import UserDataStore from "./UserDataStore";
+import { IUserDataStore } from "./storage/IUserDataStore";
import { Winston } from "../../types/Dependencies";
import express = require("express");
import ErrorReplies = require("./ErrorReplies");
-import ServerVariables = require("./ServerVariables");
+import { ServerVariablesHandler } from "./ServerVariablesHandler";
import AuthenticationSession = require("./AuthenticationSession");
import Identity = require("../../types/Identity");
-import { IdentityValidationRequestContent } from "./UserDataStore";
+import { IdentityValidationDocument } from "./storage/IdentityValidationDocument";
const filePath = __dirname + "/../resources/email-template.ejs";
const email_template = fs.readFileSync(filePath, "utf8");
@@ -33,21 +33,21 @@ export interface IdentityValidable {
mailSubject(): string;
}
-function issue_token(userid: string, content: Object, userDataStore: UserDataStore, logger: Winston): BluebirdPromise {
+function createAndSaveToken(userid: string, challenge: string, userDataStore: IUserDataStore, logger: Winston): BluebirdPromise {
const five_minutes = 4 * 60 * 1000;
const token = randomstring.generate({ length: 64 });
const that = this;
logger.debug("identity_check: issue identity token %s for 5 minutes", token);
- return userDataStore.issue_identity_check_token(userid, token, content, five_minutes)
+ return userDataStore.produceIdentityValidationToken(userid, token, challenge, five_minutes)
.then(function () {
return BluebirdPromise.resolve(token);
});
}
-function consume_token(token: string, userDataStore: UserDataStore, logger: Winston): BluebirdPromise {
+function consumeToken(token: string, challenge: string, userDataStore: IUserDataStore, logger: Winston): BluebirdPromise {
logger.debug("identity_check: consume token %s", token);
- return userDataStore.consume_identity_check_token(token);
+ return userDataStore.consumeIdentityValidationToken(token, challenge);
}
export function register(app: express.Application, pre_validation_endpoint: string, post_validation_endpoint: string, handler: IdentityValidable) {
@@ -63,8 +63,8 @@ function checkIdentityToken(req: express.Request, identityToken: string): Bluebi
export function get_finish_validation(handler: IdentityValidable): express.RequestHandler {
return function (req: express.Request, res: express.Response): BluebirdPromise {
- const logger = ServerVariables.getLogger(req.app);
- const userDataStore = ServerVariables.getUserDataStore(req.app);
+ const logger = ServerVariablesHandler.getLogger(req.app);
+ const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
const authSession = AuthenticationSession.get(req);
const identityToken = objectPath.get(req, "query.identity_token");
@@ -75,12 +75,12 @@ export function get_finish_validation(handler: IdentityValidable): express.Reque
return handler.postValidationInit(req);
})
.then(function () {
- return consume_token(identityToken, userDataStore, logger);
+ return consumeToken(identityToken, handler.challenge(), userDataStore, logger);
})
- .then(function (content: IdentityValidationRequestContent) {
+ .then(function (doc: IdentityValidationDocument) {
authSession.identity_check = {
challenge: handler.challenge(),
- userid: content.userid
+ userid: doc.userId
};
handler.postValidationResponse(req, res);
return BluebirdPromise.resolve();
@@ -94,9 +94,9 @@ export function get_finish_validation(handler: IdentityValidable): express.Reque
export function get_start_validation(handler: IdentityValidable, postValidationEndpoint: string): express.RequestHandler {
return function (req: express.Request, res: express.Response): BluebirdPromise {
- const logger = ServerVariables.getLogger(req.app);
- const notifier = ServerVariables.getNotifier(req.app);
- const userDataStore = ServerVariables.getUserDataStore(req.app);
+ const logger = ServerVariablesHandler.getLogger(req.app);
+ const notifier = ServerVariablesHandler.getNotifier(req.app);
+ const userDataStore = ServerVariablesHandler.getUserDataStore(req.app);
let identity: Identity.Identity;
logger.info("Identity Validation: Start identity validation");
@@ -104,13 +104,13 @@ export function get_start_validation(handler: IdentityValidable, postValidationE
.then(function (id: Identity.Identity) {
logger.debug("Identity Validation: retrieved identity is %s", JSON.stringify(id));
identity = id;
- const email_address = objectPath.get(identity, "email");
- const userid = objectPath.get(identity, "userid");
+ const email = identity.email;
+ const userid = identity.userid;
- if (!(email_address && userid))
+ if (!(email && userid))
return BluebirdPromise.reject(new Exceptions.IdentityError("Missing user id or email address"));
- return issue_token(userid, undefined, userDataStore, logger);
+ return createAndSaveToken(userid, handler.challenge(), userDataStore, logger);
})
.then(function (token: string) {
const host = req.get("Host");
diff --git a/src/server/lib/RestApi.ts b/src/server/lib/RestApi.ts
index ca51d9ddb..b4ec25411 100644
--- a/src/server/lib/RestApi.ts
+++ b/src/server/lib/RestApi.ts
@@ -1,6 +1,6 @@
import express = require("express");
-import UserDataStore from "./UserDataStore";
+import { UserDataStore } from "./storage/UserDataStore";
import { Winston } from "../../types/Dependencies";
import FirstFactorGet = require("./routes/firstfactor/get");
@@ -34,7 +34,7 @@ import Error404Get = require("./routes/error/404/get");
import Endpoints = require("../endpoints");
-export default class RestApi {
+export class RestApi {
static setup(app: express.Application): void {
app.get(Endpoints.FIRST_FACTOR_GET, FirstFactorGet.default);
app.get(Endpoints.SECOND_FACTOR_GET, SecondFactorGet.default);
diff --git a/src/server/lib/Server.ts b/src/server/lib/Server.ts
index 401844ba8..bc42e883b 100644
--- a/src/server/lib/Server.ts
+++ b/src/server/lib/Server.ts
@@ -1,43 +1,54 @@
+import BluebirdPromise = require("bluebird");
import { AccessController } from "./access_control/AccessController";
-import { UserConfiguration } from "./../../types/Configuration";
+import { AppConfiguration, UserConfiguration } from "./configuration/Configuration";
import { GlobalDependencies } from "../../types/Dependencies";
import { AuthenticationRegulator } from "./AuthenticationRegulator";
-import UserDataStore from "./UserDataStore";
-import ConfigurationAdapter from "./ConfigurationAdapter";
+import { UserDataStore } from "./storage/UserDataStore";
+import { ConfigurationAdapter } from "./configuration/ConfigurationAdapter";
import { TOTPValidator } from "./TOTPValidator";
import { TOTPGenerator } from "./TOTPGenerator";
-import RestApi from "./RestApi";
+import { RestApi } from "./RestApi";
import { Client } from "./ldap/Client";
-import BluebirdPromise = require("bluebird");
-import ServerVariables = require("./ServerVariables");
-import SessionConfigurationBuilder from "./SessionConfigurationBuilder";
+import { ServerVariablesHandler } from "./ServerVariablesHandler";
+import { SessionConfigurationBuilder } from "./configuration/SessionConfigurationBuilder";
import * as Express from "express";
import * as BodyParser from "body-parser";
import * as Path from "path";
import * as http from "http";
+// Constants
+
+const TRUST_PROXY = "trust proxy";
+const VIEWS = "views";
+const VIEW_ENGINE = "view engine";
+const PUG = "pug";
+
+
export default class Server {
private httpServer: http.Server;
- start(yamlConfiguration: UserConfiguration, deps: GlobalDependencies): BluebirdPromise {
- const config = ConfigurationAdapter.adapt(yamlConfiguration);
-
+ private setupExpressApplication(config: AppConfiguration, app: Express.Application, deps: GlobalDependencies): void {
const viewsDirectory = Path.resolve(__dirname, "../views");
const publicHtmlDirectory = Path.resolve(__dirname, "../public_html");
const expressSessionOptions = SessionConfigurationBuilder.build(config, deps);
- const app = Express();
app.use(Express.static(publicHtmlDirectory));
app.use(BodyParser.urlencoded({ extended: false }));
app.use(BodyParser.json());
app.use(deps.session(expressSessionOptions));
- app.set("trust proxy", 1);
- app.set("views", viewsDirectory);
- app.set("view engine", "pug");
+ app.set(TRUST_PROXY, 1);
+ app.set(VIEWS, viewsDirectory);
+ app.set(VIEW_ENGINE, PUG);
+
+ RestApi.setup(app);
+ }
+
+ private transformConfiguration(yamlConfiguration: UserConfiguration, deps: GlobalDependencies): AppConfiguration {
+ const config = ConfigurationAdapter.adapt(yamlConfiguration);
// by default the level of logs is info
deps.winston.level = config.logs_level;
@@ -45,18 +56,33 @@ export default class Server {
deps.winston.debug("Content of YAML configuration file is %s", JSON.stringify(yamlConfiguration, undefined, 2));
deps.winston.debug("Authelia configuration is %s", JSON.stringify(config, undefined, 2));
+ return config;
+ }
- ServerVariables.fill(app, config, deps);
- RestApi.setup(app);
+ private setup(config: AppConfiguration, app: Express.Application, deps: GlobalDependencies): BluebirdPromise {
+ this.setupExpressApplication(config, app, deps);
+ return ServerVariablesHandler.initialize(app, config, deps);
+ }
+ private startServer(app: Express.Application, port: number) {
return new BluebirdPromise((resolve, reject) => {
- this.httpServer = app.listen(config.port, function (err: string) {
- console.log("Listening on %d...", config.port);
+ this.httpServer = app.listen(port, function (err: string) {
+ console.log("Listening on %d...", port);
resolve();
});
});
}
+ start(yamlConfiguration: UserConfiguration, deps: GlobalDependencies): BluebirdPromise {
+ const that = this;
+ const app = Express();
+ const config = this.transformConfiguration(yamlConfiguration, deps);
+ return this.setup(config, app, deps)
+ .then(function () {
+ return that.startServer(app, config.port);
+ });
+ }
+
stop() {
this.httpServer.close();
}
diff --git a/src/server/lib/ServerVariables.ts b/src/server/lib/ServerVariables.ts
deleted file mode 100644
index 5282052b6..000000000
--- a/src/server/lib/ServerVariables.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-
-import winston = require("winston");
-import { Authenticator } from "./ldap/Authenticator";
-import { PasswordUpdater } from "./ldap/PasswordUpdater";
-import { EmailsRetriever } from "./ldap/EmailsRetriever";
-
-import { TOTPValidator } from "./TOTPValidator";
-import { TOTPGenerator } from "./TOTPGenerator";
-import U2F = require("u2f");
-import UserDataStore from "./UserDataStore";
-import { INotifier } from "./notifiers/INotifier";
-import { AuthenticationRegulator } from "./AuthenticationRegulator";
-import Configuration = require("../../types/Configuration");
-import { AccessController } from "./access_control/AccessController";
-import { NotifierFactory } from "./notifiers/NotifierFactory";
-
-import { GlobalDependencies } from "../../types/Dependencies";
-
-import express = require("express");
-
-export const VARIABLES_KEY = "authelia-variables";
-
-export interface ServerVariables {
- logger: typeof winston;
- ldapAuthenticator: Authenticator;
- ldapPasswordUpdater: PasswordUpdater;
- ldapEmailsRetriever: EmailsRetriever;
- totpValidator: TOTPValidator;
- totpGenerator: TOTPGenerator;
- u2f: typeof U2F;
- userDataStore: UserDataStore;
- notifier: INotifier;
- regulator: AuthenticationRegulator;
- config: Configuration.AppConfiguration;
- accessController: AccessController;
-}
-
-
-export function fill(app: express.Application, config: Configuration.AppConfiguration, deps: GlobalDependencies) {
- const five_minutes = 5 * 60;
- const datastore_options = {
- directory: config.store_directory,
- inMemory: config.store_in_memory
- };
-
- const userDataStore = new UserDataStore(datastore_options, deps.nedb);
- const regulator = new AuthenticationRegulator(userDataStore, five_minutes);
- const notifier = NotifierFactory.build(config.notifier, deps.nodemailer);
- const ldapAuthenticator = new Authenticator(config.ldap, deps.ldapjs, deps.winston);
- const ldapPasswordUpdater = new PasswordUpdater(config.ldap, deps.ldapjs, deps.dovehash, deps.winston);
- const ldapEmailsRetriever = new EmailsRetriever(config.ldap, deps.ldapjs, deps.winston);
- const accessController = new AccessController(config.access_control, deps.winston);
- const totpValidator = new TOTPValidator(deps.speakeasy);
- const totpGenerator = new TOTPGenerator(deps.speakeasy);
-
- const variables: ServerVariables = {
- accessController: accessController,
- config: config,
- ldapAuthenticator: ldapAuthenticator,
- ldapPasswordUpdater: ldapPasswordUpdater,
- ldapEmailsRetriever: ldapEmailsRetriever,
- logger: deps.winston,
- notifier: notifier,
- regulator: regulator,
- totpGenerator: totpGenerator,
- totpValidator: totpValidator,
- u2f: deps.u2f,
- userDataStore: userDataStore
- };
-
- app.set(VARIABLES_KEY, variables);
-}
-
-export function getLogger(app: express.Application): typeof winston {
- return (app.get(VARIABLES_KEY) as ServerVariables).logger;
-}
-
-export function getUserDataStore(app: express.Application): UserDataStore {
- return (app.get(VARIABLES_KEY) as ServerVariables).userDataStore;
-}
-
-export function getNotifier(app: express.Application): INotifier {
- return (app.get(VARIABLES_KEY) as ServerVariables).notifier;
-}
-
-export function getLdapAuthenticator(app: express.Application): Authenticator {
- return (app.get(VARIABLES_KEY) as ServerVariables).ldapAuthenticator;
-}
-
-export function getLdapPasswordUpdater(app: express.Application): PasswordUpdater {
- return (app.get(VARIABLES_KEY) as ServerVariables).ldapPasswordUpdater;
-}
-
-export function getLdapEmailsRetriever(app: express.Application): EmailsRetriever {
- return (app.get(VARIABLES_KEY) as ServerVariables).ldapEmailsRetriever;
-}
-
-export function getConfiguration(app: express.Application): Configuration.AppConfiguration {
- return (app.get(VARIABLES_KEY) as ServerVariables).config;
-}
-
-export function getAuthenticationRegulator(app: express.Application): AuthenticationRegulator {
- return (app.get(VARIABLES_KEY) as ServerVariables).regulator;
-}
-
-export function getAccessController(app: express.Application): AccessController {
- return (app.get(VARIABLES_KEY) as ServerVariables).accessController;
-}
-
-export function getTOTPGenerator(app: express.Application): TOTPGenerator {
- return (app.get(VARIABLES_KEY) as ServerVariables).totpGenerator;
-}
-
-export function getTOTPValidator(app: express.Application): TOTPValidator {
- return (app.get(VARIABLES_KEY) as ServerVariables).totpValidator;
-}
-
-export function getU2F(app: express.Application): typeof U2F {
- return (app.get(VARIABLES_KEY) as ServerVariables).u2f;
-}
diff --git a/src/server/lib/ServerVariablesHandler.ts b/src/server/lib/ServerVariablesHandler.ts
new file mode 100644
index 000000000..a7d6df7b3
--- /dev/null
+++ b/src/server/lib/ServerVariablesHandler.ts
@@ -0,0 +1,151 @@
+
+import winston = require("winston");
+import BluebirdPromise = require("bluebird");
+import { Authenticator } from "./ldap/Authenticator";
+import { PasswordUpdater } from "./ldap/PasswordUpdater";
+import { EmailsRetriever } from "./ldap/EmailsRetriever";
+
+import { TOTPValidator } from "./TOTPValidator";
+import { TOTPGenerator } from "./TOTPGenerator";
+import U2F = require("u2f");
+import { IUserDataStore } from "./storage/IUserDataStore";
+import { UserDataStore } from "./storage/UserDataStore";
+import { INotifier } from "./notifiers/INotifier";
+import { AuthenticationRegulator } from "./AuthenticationRegulator";
+import Configuration = require("./configuration/Configuration");
+import { AccessController } from "./access_control/AccessController";
+import { NotifierFactory } from "./notifiers/NotifierFactory";
+import { CollectionFactoryFactory } from "./storage/CollectionFactoryFactory";
+import { ICollectionFactory } from "./storage/ICollectionFactory";
+import { MongoCollectionFactory } from "./storage/mongo/MongoCollectionFactory";
+import { MongoConnectorFactory } from "./connectors/mongo/MongoConnectorFactory";
+import { IMongoClient } from "./connectors/mongo/IMongoClient";
+
+import { GlobalDependencies } from "../../types/Dependencies";
+
+import express = require("express");
+
+export const VARIABLES_KEY = "authelia-variables";
+
+export interface ServerVariables {
+ logger: typeof winston;
+ ldapAuthenticator: Authenticator;
+ ldapPasswordUpdater: PasswordUpdater;
+ ldapEmailsRetriever: EmailsRetriever;
+ totpValidator: TOTPValidator;
+ totpGenerator: TOTPGenerator;
+ u2f: typeof U2F;
+ userDataStore: IUserDataStore;
+ notifier: INotifier;
+ regulator: AuthenticationRegulator;
+ config: Configuration.AppConfiguration;
+ accessController: AccessController;
+}
+
+class UserDataStoreFactory {
+ static create(config: Configuration.AppConfiguration): BluebirdPromise {
+ if (config.storage.local) {
+ const nedbOptions = {
+ directory: config.storage.local.path,
+ inMemory: config.storage.local.in_memory
+ };
+ const collectionFactory = CollectionFactoryFactory.createNedb(nedbOptions);
+ return BluebirdPromise.resolve(new UserDataStore(collectionFactory));
+ }
+ else if (config.storage.mongo) {
+ const mongoConnectorFactory = new MongoConnectorFactory();
+ const mongoConnector = mongoConnectorFactory.create(config.storage.mongo.url);
+ return mongoConnector.connect()
+ .then(function (client: IMongoClient) {
+ const collectionFactory = CollectionFactoryFactory.createMongo(client);
+ return BluebirdPromise.resolve(new UserDataStore(collectionFactory));
+ });
+ }
+
+ return BluebirdPromise.reject(new Error("Storage backend incorrectly configured."));
+ }
+}
+
+export class ServerVariablesHandler {
+ static initialize(app: express.Application, config: Configuration.AppConfiguration, deps: GlobalDependencies): BluebirdPromise {
+ const five_minutes = 5 * 60;
+
+ const notifier = NotifierFactory.build(config.notifier, deps.nodemailer);
+ const ldapAuthenticator = new Authenticator(config.ldap, deps.ldapjs, deps.winston);
+ const ldapPasswordUpdater = new PasswordUpdater(config.ldap, deps.ldapjs, deps.dovehash, deps.winston);
+ const ldapEmailsRetriever = new EmailsRetriever(config.ldap, deps.ldapjs, deps.winston);
+ const accessController = new AccessController(config.access_control, deps.winston);
+ const totpValidator = new TOTPValidator(deps.speakeasy);
+ const totpGenerator = new TOTPGenerator(deps.speakeasy);
+
+ return UserDataStoreFactory.create(config)
+ .then(function (userDataStore: UserDataStore) {
+ const regulator = new AuthenticationRegulator(userDataStore, five_minutes);
+
+ const variables: ServerVariables = {
+ accessController: accessController,
+ config: config,
+ ldapAuthenticator: ldapAuthenticator,
+ ldapPasswordUpdater: ldapPasswordUpdater,
+ ldapEmailsRetriever: ldapEmailsRetriever,
+ logger: deps.winston,
+ notifier: notifier,
+ regulator: regulator,
+ totpGenerator: totpGenerator,
+ totpValidator: totpValidator,
+ u2f: deps.u2f,
+ userDataStore: userDataStore
+ };
+
+ app.set(VARIABLES_KEY, variables);
+ });
+ }
+
+ static getLogger(app: express.Application): typeof winston {
+ return (app.get(VARIABLES_KEY) as ServerVariables).logger;
+ }
+
+ static getUserDataStore(app: express.Application): IUserDataStore {
+ return (app.get(VARIABLES_KEY) as ServerVariables).userDataStore;
+ }
+
+ static getNotifier(app: express.Application): INotifier {
+ return (app.get(VARIABLES_KEY) as ServerVariables).notifier;
+ }
+
+ static getLdapAuthenticator(app: express.Application): Authenticator {
+ return (app.get(VARIABLES_KEY) as ServerVariables).ldapAuthenticator;
+ }
+
+ static getLdapPasswordUpdater(app: express.Application): PasswordUpdater {
+ return (app.get(VARIABLES_KEY) as ServerVariables).ldapPasswordUpdater;
+ }
+
+ static getLdapEmailsRetriever(app: express.Application): EmailsRetriever {
+ return (app.get(VARIABLES_KEY) as ServerVariables).ldapEmailsRetriever;
+ }
+
+ static getConfiguration(app: express.Application): Configuration.AppConfiguration {
+ return (app.get(VARIABLES_KEY) as ServerVariables).config;
+ }
+
+ static getAuthenticationRegulator(app: express.Application): AuthenticationRegulator {
+ return (app.get(VARIABLES_KEY) as ServerVariables).regulator;
+ }
+
+ static getAccessController(app: express.Application): AccessController {
+ return (app.get(VARIABLES_KEY) as ServerVariables).accessController;
+ }
+
+ static getTOTPGenerator(app: express.Application): TOTPGenerator {
+ return (app.get(VARIABLES_KEY) as ServerVariables).totpGenerator;
+ }
+
+ static getTOTPValidator(app: express.Application): TOTPValidator {
+ return (app.get(VARIABLES_KEY) as ServerVariables).totpValidator;
+ }
+
+ static getU2F(app: express.Application): typeof U2F {
+ return (app.get(VARIABLES_KEY) as ServerVariables).u2f;
+ }
+}
diff --git a/src/server/lib/SessionConfigurationBuilder.ts b/src/server/lib/SessionConfigurationBuilder.ts
deleted file mode 100644
index 3fa6c661d..000000000
--- a/src/server/lib/SessionConfigurationBuilder.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-
-import ExpressSession = require("express-session");
-import { AppConfiguration } from "../../types/Configuration";
-import { GlobalDependencies } from "../../types/Dependencies";
-
-export default class SessionConfigurationBuilder {
-
- static build(configuration: AppConfiguration, deps: GlobalDependencies): ExpressSession.SessionOptions {
- const sessionOptions: ExpressSession.SessionOptions = {
- secret: configuration.session.secret,
- resave: false,
- saveUninitialized: true,
- cookie: {
- secure: false,
- maxAge: configuration.session.expiration,
- domain: configuration.session.domain
- },
- };
-
- if (configuration.session.redis) {
- let redisOptions;
- if (configuration.session.redis.host
- && configuration.session.redis.port) {
- redisOptions = {
- host: configuration.session.redis.host,
- port: configuration.session.redis.port
- };
- }
-
- if (redisOptions) {
- const RedisStore = deps.ConnectRedis(deps.session);
- sessionOptions.store = new RedisStore(redisOptions);
- }
- }
- return sessionOptions;
- }
-}
\ No newline at end of file
diff --git a/src/server/lib/UserDataStore.ts b/src/server/lib/UserDataStore.ts
deleted file mode 100644
index 0d74062a5..000000000
--- a/src/server/lib/UserDataStore.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-import * as BluebirdPromise from "bluebird";
-import * as path from "path";
-import { NedbAsync } from "nedb";
-import { TOTPSecret } from "../../types/TOTPSecret";
-import { Nedb } from "../../types/Dependencies";
-import u2f = require("u2f");
-
-// Constants
-
-const U2F_META_COLLECTION_NAME = "u2f_meta";
-const IDENTITY_CHECK_TOKENS_COLLECTION_NAME = "identity_check_tokens";
-const AUTHENTICATION_TRACES_COLLECTION_NAME = "authentication_traces";
-const TOTP_SECRETS_COLLECTION_NAME = "totp_secrets";
-
-
-export interface TOTPSecretDocument {
- userid: string;
- secret: TOTPSecret;
-}
-
-export interface U2FRegistrationDocument {
- keyHandle: string;
- publicKey: string;
- userId: string;
- appId: string;
-}
-
-export interface Options {
- inMemoryOnly?: boolean;
- directory?: string;
-}
-
-export interface IdentityValidationRequestContent {
- userid: string;
- data: string;
-}
-
-export interface IdentityValidationRequestDocument {
- userid: string;
- token: string;
- content: IdentityValidationRequestContent;
- max_date: Date;
-}
-
-interface U2FRegistrationFilter {
- userId: string;
- appId: string;
-}
-
-// Source
-
-export default class UserDataStore {
- private _u2f_meta_collection: NedbAsync;
- private _identity_check_tokens_collection: NedbAsync;
- private _authentication_traces_collection: NedbAsync;
- private _totp_secret_collection: NedbAsync;
- private nedb: Nedb;
-
- constructor(options: Options, nedb: Nedb) {
- this.nedb = nedb;
- this._u2f_meta_collection = this.create_collection(U2F_META_COLLECTION_NAME, options);
- this._identity_check_tokens_collection =
- this.create_collection(IDENTITY_CHECK_TOKENS_COLLECTION_NAME, options);
- this._authentication_traces_collection =
- this.create_collection(AUTHENTICATION_TRACES_COLLECTION_NAME, options);
- this._totp_secret_collection =
- this.create_collection(TOTP_SECRETS_COLLECTION_NAME, options);
- }
-
- set_u2f_meta(userId: string, appId: string, keyHandle: string, publicKey: string): BluebirdPromise {
- const newDocument: U2FRegistrationDocument = {
- userId: userId,
- appId: appId,
- keyHandle: keyHandle,
- publicKey: publicKey
- };
-
- const filter: U2FRegistrationFilter = {
- userId: userId,
- appId: appId
- };
-
- return this._u2f_meta_collection.updateAsync(filter, newDocument, { upsert: true });
- }
-
- get_u2f_meta(userId: string, appId: string): BluebirdPromise {
- const filter: U2FRegistrationFilter = {
- userId: userId,
- appId: appId
- };
- return this._u2f_meta_collection.findOneAsync(filter);
- }
-
- save_authentication_trace(userid: string, type: string, is_success: boolean) {
- const newDocument = {
- userid: userid,
- date: new Date(),
- is_success: is_success,
- type: type
- };
-
- return this._authentication_traces_collection.insertAsync(newDocument);
- }
-
- get_last_authentication_traces(userid: string, type: string, is_success: boolean, count: number): BluebirdPromise {
- const q = {
- userid: userid,
- type: type,
- is_success: is_success
- };
-
- const query = this._authentication_traces_collection.find(q)
- .sort({ date: -1 }).limit(count);
- const query_promisified = BluebirdPromise.promisify(query.exec, { context: query });
- return query_promisified();
- }
-
- issue_identity_check_token(userid: string, token: string, data: string | object, max_age: number): BluebirdPromise {
- const newDocument = {
- userid: userid,
- token: token,
- content: {
- userid: userid,
- data: data
- },
- max_date: new Date(new Date().getTime() + max_age)
- };
-
- return this._identity_check_tokens_collection.insertAsync(newDocument);
- }
-
- consume_identity_check_token(token: string): BluebirdPromise {
- const query = {
- token: token
- };
-
- return this._identity_check_tokens_collection.findOneAsync(query)
- .then(function (doc) {
- if (!doc) {
- return BluebirdPromise.reject(new Error("Registration token does not exist"));
- }
-
- const max_date = doc.max_date;
- const current_date = new Date();
- if (current_date > max_date)
- return BluebirdPromise.reject(new Error("Registration token is not valid anymore"));
-
- return BluebirdPromise.resolve(doc.content);
- })
- .then((content) => {
- return BluebirdPromise.join(this._identity_check_tokens_collection.removeAsync(query),
- BluebirdPromise.resolve(content));
- })
- .then((v) => {
- return BluebirdPromise.resolve(v[1]);
- });
- }
-
- set_totp_secret(userid: string, secret: TOTPSecret): BluebirdPromise {
- const doc = {
- userid: userid,
- secret: secret
- };
-
- const query = {
- userid: userid
- };
- return this._totp_secret_collection.updateAsync(query, doc, { upsert: true });
- }
-
- get_totp_secret(userid: string): BluebirdPromise {
- const query = {
- userid: userid
- };
- return this._totp_secret_collection.findOneAsync(query);
- }
-
- private create_collection(name: string, options: any): NedbAsync {
- const datastore_options = {
- inMemoryOnly: options.inMemoryOnly || false,
- autoload: true,
- filename: ""
- };
-
- if (options.directory)
- datastore_options.filename = path.resolve(options.directory, name);
-
- return BluebirdPromise.promisifyAll(new this.nedb(datastore_options)) as NedbAsync;
- }
-}
diff --git a/src/server/lib/access_control/AccessController.ts b/src/server/lib/access_control/AccessController.ts
index e5b3605fa..c23157ff6 100644
--- a/src/server/lib/access_control/AccessController.ts
+++ b/src/server/lib/access_control/AccessController.ts
@@ -1,5 +1,5 @@
-import { ACLConfiguration } from "../../../types/Configuration";
+import { ACLConfiguration } from "../configuration/Configuration";
import PatternBuilder from "./PatternBuilder";
import { Winston } from "../../../types/Dependencies";
diff --git a/src/server/lib/access_control/PatternBuilder.ts b/src/server/lib/access_control/PatternBuilder.ts
index 69d37278d..17d4f7e69 100644
--- a/src/server/lib/access_control/PatternBuilder.ts
+++ b/src/server/lib/access_control/PatternBuilder.ts
@@ -1,6 +1,6 @@
import { Winston } from "../../../types/Dependencies";
-import { ACLConfiguration, ACLGroupsRules, ACLUsersRules, ACLDefaultRules } from "../../../types/Configuration";
+import { ACLConfiguration, ACLGroupsRules, ACLUsersRules, ACLDefaultRules } from "../configuration/Configuration";
import objectPath = require("object-path");
export default class AccessControlPatternBuilder {
diff --git a/src/types/Configuration.ts b/src/server/lib/configuration/Configuration.d.ts
similarity index 82%
rename from src/types/Configuration.ts
rename to src/server/lib/configuration/Configuration.d.ts
index 8c2c9192a..ec0608736 100644
--- a/src/types/Configuration.ts
+++ b/src/server/lib/configuration/Configuration.d.ts
@@ -50,12 +50,26 @@ export interface NotifierConfiguration {
filesystem?: FileSystemNotifierConfiguration;
}
+export interface MongoStorageConfiguration {
+ url: string;
+}
+
+export interface LocalStorageConfiguration {
+ path?: string;
+ in_memory?: boolean;
+}
+
+export interface StorageConfiguration {
+ local?: LocalStorageConfiguration;
+ mongo?: MongoStorageConfiguration;
+}
+
export interface UserConfiguration {
port?: number;
logs_level?: string;
ldap: LdapConfiguration;
session: SessionCookieConfiguration;
- store_directory?: string;
+ storage: StorageConfiguration;
notifier: NotifierConfiguration;
access_control?: ACLConfiguration;
}
@@ -65,8 +79,7 @@ export interface AppConfiguration {
logs_level: string;
ldap: LdapConfiguration;
session: SessionCookieConfiguration;
- store_in_memory?: boolean;
- store_directory?: string;
+ storage: StorageConfiguration;
notifier: NotifierConfiguration;
access_control?: ACLConfiguration;
}
diff --git a/src/server/lib/ConfigurationAdapter.ts b/src/server/lib/configuration/ConfigurationAdapter.ts
similarity index 79%
rename from src/server/lib/ConfigurationAdapter.ts
rename to src/server/lib/configuration/ConfigurationAdapter.ts
index 3cbca9168..fe4c33eb6 100644
--- a/src/server/lib/ConfigurationAdapter.ts
+++ b/src/server/lib/configuration/ConfigurationAdapter.ts
@@ -1,6 +1,10 @@
import * as ObjectPath from "object-path";
-import { AppConfiguration, UserConfiguration, NotifierConfiguration, ACLConfiguration, LdapConfiguration, SessionRedisOptions } from "./../../types/Configuration";
+import {
+ AppConfiguration, UserConfiguration, NotifierConfiguration,
+ ACLConfiguration, LdapConfiguration, SessionRedisOptions,
+ MongoStorageConfiguration, LocalStorageConfiguration
+} from "./Configuration";
const LDAP_URL_ENV_VARIABLE = "LDAP_URL";
@@ -34,14 +38,17 @@ function adaptFromUserConfiguration(userConfiguration: UserConfiguration): AppCo
expiration: get_optional(userConfiguration, "session.expiration", 3600000), // in ms
redis: ObjectPath.get