Enable authentication to Mongo and Redis. (#263)
* Fix issue in unit test of IdentityCheckMiddleware. * Enable authentication to Mongo server. * Enable authentication to Redis.pull/259/head^2
parent
9dab40c2ce
commit
67f84b97c8
|
@ -213,6 +213,7 @@ session:
|
||||||
redis:
|
redis:
|
||||||
host: redis
|
host: redis
|
||||||
port: 6379
|
port: 6379
|
||||||
|
password: authelia
|
||||||
|
|
||||||
# Configuration of the authentication regulation mechanism.
|
# Configuration of the authentication regulation mechanism.
|
||||||
#
|
#
|
||||||
|
@ -243,6 +244,9 @@ storage:
|
||||||
mongo:
|
mongo:
|
||||||
url: mongodb://mongo
|
url: mongodb://mongo
|
||||||
database: authelia
|
database: authelia
|
||||||
|
auth:
|
||||||
|
username: authelia
|
||||||
|
password: authelia
|
||||||
|
|
||||||
# Configuration of the notification system.
|
# Configuration of the notification system.
|
||||||
#
|
#
|
||||||
|
|
|
@ -2,6 +2,10 @@ version: '2'
|
||||||
services:
|
services:
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:3.4
|
image: mongo:3.4
|
||||||
|
command: mongod --auth
|
||||||
|
environment:
|
||||||
|
- MONGO_INITDB_ROOT_USERNAME=authelia
|
||||||
|
- MONGO_INITDB_ROOT_PASSWORD=authelia
|
||||||
ports:
|
ports:
|
||||||
- "27017:27017"
|
- "27017:27017"
|
||||||
networks:
|
networks:
|
||||||
|
|
|
@ -2,5 +2,6 @@ version: '2'
|
||||||
services:
|
services:
|
||||||
redis:
|
redis:
|
||||||
image: redis:4.0-alpine
|
image: redis:4.0-alpine
|
||||||
|
command: redis-server --requirepass authelia
|
||||||
networks:
|
networks:
|
||||||
- example-network
|
- example-network
|
||||||
|
|
|
@ -73,8 +73,7 @@ throws a first factor error", function () {
|
||||||
identityValidable, "/endpoint", vars);
|
identityValidable, "/endpoint", vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () { return BluebirdPromise.reject("Should fail"); })
|
.then(() => {
|
||||||
.catch(function () {
|
|
||||||
Assert(res.redirect.calledWith("/error/401"));
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -137,16 +136,12 @@ throws a first factor error", function () {
|
||||||
|
|
||||||
|
|
||||||
describe("test finish GET", function () {
|
describe("test finish GET", function () {
|
||||||
it("should send 401 if no identity_token is provided", function () {
|
it("should send 401 if no identity_token is provided", () => {
|
||||||
|
|
||||||
const callback = IdentityValidator
|
const callback = IdentityValidator
|
||||||
.get_finish_validation(identityValidable, vars);
|
.get_finish_validation(identityValidable, vars);
|
||||||
|
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return BluebirdPromise.reject("Should fail");
|
|
||||||
})
|
|
||||||
.catch(function () {
|
|
||||||
Assert(res.redirect.calledWith("/error/401"));
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -164,16 +159,16 @@ valid", function () {
|
||||||
function () {
|
function () {
|
||||||
req.query.identity_token = "token";
|
req.query.identity_token = "token";
|
||||||
|
|
||||||
|
identityValidable.postValidationInitStub
|
||||||
|
.returns(BluebirdPromise.resolve());
|
||||||
|
mocks.userDataStore.consumeIdentityValidationTokenStub.reset();
|
||||||
mocks.userDataStore.consumeIdentityValidationTokenStub
|
mocks.userDataStore.consumeIdentityValidationTokenStub
|
||||||
.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
.returns(BluebirdPromise.reject(new Error("Invalid token")));
|
||||||
|
|
||||||
const callback = IdentityValidator
|
const callback = IdentityValidator
|
||||||
.get_finish_validation(identityValidable, vars);
|
.get_finish_validation(identityValidable, vars);
|
||||||
return callback(req as any, res as any, undefined)
|
return callback(req as any, res as any, undefined)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
return BluebirdPromise.reject("Should fail");
|
|
||||||
})
|
|
||||||
.catch(function () {
|
|
||||||
Assert(res.redirect.calledWith("/error/401"));
|
Assert(res.redirect.calledWith("/error/401"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -73,15 +73,15 @@ export function get_finish_validation(handler: IdentityValidable,
|
||||||
vars.logger.debug(req, "Identity token provided is %s", identityToken);
|
vars.logger.debug(req, "Identity token provided is %s", identityToken);
|
||||||
|
|
||||||
return checkIdentityToken(req, identityToken)
|
return checkIdentityToken(req, identityToken)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
authSession = AuthenticationSessionHandler.get(req, vars.logger);
|
authSession = AuthenticationSessionHandler.get(req, vars.logger);
|
||||||
return handler.postValidationInit(req);
|
return handler.postValidationInit(req);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
return consumeToken(identityToken, handler.challenge(),
|
return consumeToken(identityToken, handler.challenge(),
|
||||||
vars.userDataStore);
|
vars.userDataStore);
|
||||||
})
|
})
|
||||||
.then(function (doc: IdentityValidationDocument) {
|
.then((doc: IdentityValidationDocument) => {
|
||||||
authSession.identity_check = {
|
authSession.identity_check = {
|
||||||
challenge: handler.challenge(),
|
challenge: handler.challenge(),
|
||||||
userid: doc.userId
|
userid: doc.userId
|
||||||
|
|
|
@ -18,7 +18,7 @@ export class IdentityValidableStub implements IdentityValidable {
|
||||||
this.challengeStub = Sinon.stub();
|
this.challengeStub = Sinon.stub();
|
||||||
|
|
||||||
this.preValidationInitStub = Sinon.stub();
|
this.preValidationInitStub = Sinon.stub();
|
||||||
this.postValidationResponseStub = Sinon.stub();
|
this.postValidationInitStub = Sinon.stub();
|
||||||
|
|
||||||
this.preValidationResponseStub = Sinon.stub();
|
this.preValidationResponseStub = Sinon.stub();
|
||||||
this.postValidationResponseStub = Sinon.stub();
|
this.postValidationResponseStub = Sinon.stub();
|
||||||
|
|
|
@ -48,8 +48,7 @@ class UserDataStoreFactory {
|
||||||
}
|
}
|
||||||
else if (config.storage.mongo) {
|
else if (config.storage.mongo) {
|
||||||
const mongoClient = new MongoClient(
|
const mongoClient = new MongoClient(
|
||||||
config.storage.mongo.url,
|
config.storage.mongo,
|
||||||
config.storage.mongo.database,
|
|
||||||
globalLogger);
|
globalLogger);
|
||||||
const collectionFactory = CollectionFactoryFactory.createMongo(mongoClient);
|
const collectionFactory = CollectionFactoryFactory.createMongo(mongoClient);
|
||||||
return BluebirdPromise.resolve(new UserDataStore(collectionFactory));
|
return BluebirdPromise.resolve(new UserDataStore(collectionFactory));
|
||||||
|
|
|
@ -8,73 +8,72 @@ import Sinon = require("sinon");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
|
|
||||||
describe("configuration/SessionConfigurationBuilder", function () {
|
describe("configuration/SessionConfigurationBuilder", function () {
|
||||||
it("should return session options without redis options", function () {
|
const configuration: Configuration = {
|
||||||
const configuration: Configuration = {
|
access_control: {
|
||||||
access_control: {
|
default_policy: "deny",
|
||||||
default_policy: "deny",
|
any: [],
|
||||||
any: [],
|
users: {},
|
||||||
users: {},
|
groups: {}
|
||||||
groups: {}
|
},
|
||||||
|
totp: {
|
||||||
|
issuer: "authelia.com"
|
||||||
|
},
|
||||||
|
authentication_backend: {
|
||||||
|
ldap: {
|
||||||
|
url: "ldap://ldap",
|
||||||
|
user: "user",
|
||||||
|
base_dn: "dc=example,dc=com",
|
||||||
|
password: "password",
|
||||||
|
additional_groups_dn: "ou=groups",
|
||||||
|
additional_users_dn: "ou=users",
|
||||||
|
group_name_attribute: "",
|
||||||
|
groups_filter: "",
|
||||||
|
mail_attribute: "",
|
||||||
|
users_filter: ""
|
||||||
},
|
},
|
||||||
totp: {
|
},
|
||||||
issuer: "authelia.com"
|
logs_level: "debug",
|
||||||
},
|
notifier: {
|
||||||
authentication_backend: {
|
filesystem: {
|
||||||
ldap: {
|
filename: "/test"
|
||||||
url: "ldap://ldap",
|
|
||||||
user: "user",
|
|
||||||
base_dn: "dc=example,dc=com",
|
|
||||||
password: "password",
|
|
||||||
additional_groups_dn: "ou=groups",
|
|
||||||
additional_users_dn: "ou=users",
|
|
||||||
group_name_attribute: "",
|
|
||||||
groups_filter: "",
|
|
||||||
mail_attribute: "",
|
|
||||||
users_filter: ""
|
|
||||||
},
|
|
||||||
},
|
|
||||||
logs_level: "debug",
|
|
||||||
notifier: {
|
|
||||||
filesystem: {
|
|
||||||
filename: "/test"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
port: 8080,
|
|
||||||
session: {
|
|
||||||
name: "authelia_session",
|
|
||||||
domain: "example.com",
|
|
||||||
expiration: 3600,
|
|
||||||
secret: "secret"
|
|
||||||
},
|
|
||||||
regulation: {
|
|
||||||
max_retries: 3,
|
|
||||||
ban_time: 5 * 60,
|
|
||||||
find_time: 5 * 60
|
|
||||||
},
|
|
||||||
storage: {
|
|
||||||
local: {
|
|
||||||
in_memory: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
authentication_methods: {
|
|
||||||
default_method: "two_factor",
|
|
||||||
per_subdomain_methods: {}
|
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
port: 8080,
|
||||||
|
session: {
|
||||||
|
name: "authelia_session",
|
||||||
|
domain: "example.com",
|
||||||
|
expiration: 3600,
|
||||||
|
secret: "secret"
|
||||||
|
},
|
||||||
|
regulation: {
|
||||||
|
max_retries: 3,
|
||||||
|
ban_time: 5 * 60,
|
||||||
|
find_time: 5 * 60
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
local: {
|
||||||
|
in_memory: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
authentication_methods: {
|
||||||
|
default_method: "two_factor",
|
||||||
|
per_subdomain_methods: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const deps: GlobalDependencies = {
|
const deps: GlobalDependencies = {
|
||||||
ConnectRedis: Sinon.spy() as any,
|
ConnectRedis: Sinon.spy() as any,
|
||||||
ldapjs: Sinon.spy() as any,
|
ldapjs: Sinon.spy() as any,
|
||||||
nedb: Sinon.spy() as any,
|
nedb: Sinon.spy() as any,
|
||||||
session: Sinon.spy() as any,
|
session: Sinon.spy() as any,
|
||||||
speakeasy: Sinon.spy() as any,
|
speakeasy: Sinon.spy() as any,
|
||||||
u2f: Sinon.spy() as any,
|
u2f: Sinon.spy() as any,
|
||||||
winston: Sinon.spy() as any,
|
winston: Sinon.spy() as any,
|
||||||
Redis: Sinon.spy() as any
|
Redis: Sinon.spy() as any
|
||||||
};
|
};
|
||||||
|
|
||||||
|
it("should return session options without redis options", function () {
|
||||||
const options = SessionConfigurationBuilder.build(configuration, deps);
|
const options = SessionConfigurationBuilder.build(configuration, deps);
|
||||||
|
|
||||||
const expectedOptions = {
|
const expectedOptions = {
|
||||||
name: "authelia_session",
|
name: "authelia_session",
|
||||||
secret: "secret",
|
secret: "secret",
|
||||||
|
@ -92,79 +91,17 @@ describe("configuration/SessionConfigurationBuilder", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return session options with redis options", function () {
|
it("should return session options with redis options", function () {
|
||||||
const configuration: Configuration = {
|
configuration.session["redis"] = {
|
||||||
access_control: {
|
host: "redis.example.com",
|
||||||
default_policy: "deny",
|
port: 6379
|
||||||
any: [],
|
|
||||||
users: {},
|
|
||||||
groups: {}
|
|
||||||
},
|
|
||||||
totp: {
|
|
||||||
issuer: "authelia.com"
|
|
||||||
},
|
|
||||||
authentication_backend: {
|
|
||||||
ldap: {
|
|
||||||
url: "ldap://ldap",
|
|
||||||
user: "user",
|
|
||||||
password: "password",
|
|
||||||
base_dn: "dc=example,dc=com",
|
|
||||||
additional_groups_dn: "ou=groups",
|
|
||||||
additional_users_dn: "ou=users",
|
|
||||||
group_name_attribute: "",
|
|
||||||
groups_filter: "",
|
|
||||||
mail_attribute: "",
|
|
||||||
users_filter: ""
|
|
||||||
},
|
|
||||||
},
|
|
||||||
logs_level: "debug",
|
|
||||||
notifier: {
|
|
||||||
filesystem: {
|
|
||||||
filename: "/test"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
port: 8080,
|
|
||||||
session: {
|
|
||||||
name: "authelia_session",
|
|
||||||
domain: "example.com",
|
|
||||||
expiration: 3600,
|
|
||||||
secret: "secret",
|
|
||||||
inactivity: 4000,
|
|
||||||
redis: {
|
|
||||||
host: "redis.example.com",
|
|
||||||
port: 6379
|
|
||||||
}
|
|
||||||
},
|
|
||||||
regulation: {
|
|
||||||
max_retries: 3,
|
|
||||||
ban_time: 5 * 60,
|
|
||||||
find_time: 5 * 60
|
|
||||||
},
|
|
||||||
storage: {
|
|
||||||
local: {
|
|
||||||
in_memory: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
authentication_methods: {
|
|
||||||
default_method: "two_factor",
|
|
||||||
per_subdomain_methods: {}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const RedisStoreMock = Sinon.spy();
|
const RedisStoreMock = Sinon.spy();
|
||||||
const redisClient = Sinon.mock().returns({ on: Sinon.spy() });
|
const redisClient = Sinon.mock().returns({ on: Sinon.spy() });
|
||||||
|
|
||||||
const deps: GlobalDependencies = {
|
deps.ConnectRedis = Sinon.stub().returns(RedisStoreMock) as any;
|
||||||
ConnectRedis: Sinon.stub().returns(RedisStoreMock) as any,
|
deps.Redis = {
|
||||||
ldapjs: Sinon.spy() as any,
|
createClient: Sinon.mock().returns(redisClient)
|
||||||
nedb: Sinon.spy() as any,
|
} as any;
|
||||||
session: Sinon.spy() as any,
|
|
||||||
speakeasy: Sinon.spy() as any,
|
|
||||||
u2f: Sinon.spy() as any,
|
|
||||||
winston: Sinon.spy() as any,
|
|
||||||
Redis: {
|
|
||||||
createClient: Sinon.mock().returns(redisClient)
|
|
||||||
} as any
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = SessionConfigurationBuilder.build(configuration, deps);
|
const options = SessionConfigurationBuilder.build(configuration, deps);
|
||||||
|
|
||||||
|
@ -189,4 +126,30 @@ describe("configuration/SessionConfigurationBuilder", function () {
|
||||||
Assert.deepEqual(options.cookie, expectedOptions.cookie);
|
Assert.deepEqual(options.cookie, expectedOptions.cookie);
|
||||||
Assert(options.store != undefined);
|
Assert(options.store != undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return session options with redis password", function () {
|
||||||
|
configuration.session["redis"] = {
|
||||||
|
host: "redis.example.com",
|
||||||
|
port: 6379,
|
||||||
|
password: "authelia_pass"
|
||||||
|
};
|
||||||
|
const RedisStoreMock = Sinon.spy();
|
||||||
|
const redisClient = Sinon.mock().returns({ on: Sinon.spy() });
|
||||||
|
const createClientStub = Sinon.stub();
|
||||||
|
|
||||||
|
deps.ConnectRedis = Sinon.stub().returns(RedisStoreMock) as any;
|
||||||
|
deps.Redis = {
|
||||||
|
createClient: createClientStub
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
createClientStub.returns(redisClient);
|
||||||
|
|
||||||
|
const options = SessionConfigurationBuilder.build(configuration, deps);
|
||||||
|
|
||||||
|
Assert(createClientStub.calledWith({
|
||||||
|
host: "redis.example.com",
|
||||||
|
port: 6379,
|
||||||
|
password: "authelia_pass"
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -1,7 +1,9 @@
|
||||||
|
|
||||||
import ExpressSession = require("express-session");
|
import ExpressSession = require("express-session");
|
||||||
|
import Redis = require("redis");
|
||||||
|
|
||||||
import { Configuration } from "./schema/Configuration";
|
import { Configuration } from "./schema/Configuration";
|
||||||
import { GlobalDependencies } from "../../../types/Dependencies";
|
import { GlobalDependencies } from "../../../types/Dependencies";
|
||||||
|
import { RedisStoreOptions } from "connect-redis";
|
||||||
|
|
||||||
export class SessionConfigurationBuilder {
|
export class SessionConfigurationBuilder {
|
||||||
|
|
||||||
|
@ -21,20 +23,24 @@ export class SessionConfigurationBuilder {
|
||||||
|
|
||||||
if (configuration.session.redis) {
|
if (configuration.session.redis) {
|
||||||
let redisOptions;
|
let redisOptions;
|
||||||
if (configuration.session.redis.host
|
const options: Redis.ClientOpts = {
|
||||||
&& configuration.session.redis.port) {
|
host: configuration.session.redis.host,
|
||||||
const client = deps.Redis.createClient({
|
port: configuration.session.redis.port
|
||||||
host: configuration.session.redis.host,
|
};
|
||||||
port: configuration.session.redis.port
|
|
||||||
});
|
if (configuration.session.redis.password) {
|
||||||
client.on("error", function (err: Error) {
|
options["password"] = configuration.session.redis.password;
|
||||||
console.error("Redis error:", err);
|
|
||||||
});
|
|
||||||
redisOptions = {
|
|
||||||
client: client,
|
|
||||||
logErrors: true
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
const client = deps.Redis.createClient(options);
|
||||||
|
|
||||||
|
client.on("error", function (err: Error) {
|
||||||
|
console.error("Redis error:", err);
|
||||||
|
});
|
||||||
|
|
||||||
|
redisOptions = {
|
||||||
|
client: client,
|
||||||
|
logErrors: true
|
||||||
|
};
|
||||||
|
|
||||||
if (redisOptions) {
|
if (redisOptions) {
|
||||||
const RedisStore = deps.ConnectRedis(deps.session);
|
const RedisStore = deps.ConnectRedis(deps.session);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export interface SessionRedisOptions {
|
export interface SessionRedisOptions {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
password?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SessionConfiguration {
|
export interface SessionConfiguration {
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
export interface MongoStorageConfiguration {
|
export interface MongoStorageConfiguration {
|
||||||
url: string;
|
url: string;
|
||||||
database: string;
|
database: string;
|
||||||
|
auth?: {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocalStorageConfiguration {
|
export interface LocalStorageConfiguration {
|
||||||
|
@ -21,5 +25,6 @@ export function complete(configuration: StorageConfiguration): StorageConfigurat
|
||||||
in_memory: true
|
in_memory: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return newConfiguration;
|
return newConfiguration;
|
||||||
}
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import Sinon = require("sinon");
|
|
||||||
import MongoDB = require("mongodb");
|
|
||||||
import Bluebird = require("bluebird");
|
import Bluebird = require("bluebird");
|
||||||
|
import MongoDB = require("mongodb");
|
||||||
|
import Sinon = require("sinon");
|
||||||
|
|
||||||
import { MongoClient } from "./MongoClient";
|
import { MongoClient } from "./MongoClient";
|
||||||
import { GlobalLoggerStub } from "../../logging/GlobalLoggerStub.spec";
|
import { GlobalLoggerStub } from "../../logging/GlobalLoggerStub.spec";
|
||||||
|
import { MongoStorageConfiguration } from "../../configuration/schema/StorageConfiguration";
|
||||||
|
|
||||||
describe("connectors/mongo/MongoClient", function () {
|
describe("connectors/mongo/MongoClient", function () {
|
||||||
let MongoClientStub: any;
|
let MongoClientStub: any;
|
||||||
|
@ -11,7 +13,52 @@ describe("connectors/mongo/MongoClient", function () {
|
||||||
let mongoDatabaseStub: any;
|
let mongoDatabaseStub: any;
|
||||||
let logger: GlobalLoggerStub = new GlobalLoggerStub();
|
let logger: GlobalLoggerStub = new GlobalLoggerStub();
|
||||||
|
|
||||||
describe("collection", function () {
|
const configuration: MongoStorageConfiguration = {
|
||||||
|
url: "mongo://url",
|
||||||
|
database: "databasename"
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("connection", () => {
|
||||||
|
before(() => {
|
||||||
|
mongoClientStub = {
|
||||||
|
db: Sinon.stub()
|
||||||
|
};
|
||||||
|
mongoDatabaseStub = {
|
||||||
|
on: Sinon.stub(),
|
||||||
|
collection: Sinon.stub()
|
||||||
|
}
|
||||||
|
MongoClientStub = Sinon.stub(
|
||||||
|
MongoDB.MongoClient, "connect");
|
||||||
|
MongoClientStub.yields(
|
||||||
|
undefined, mongoClientStub);
|
||||||
|
mongoClientStub.db.returns(
|
||||||
|
mongoDatabaseStub);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
MongoClientStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use credentials from configuration", () => {
|
||||||
|
configuration.auth = {
|
||||||
|
username: "authelia",
|
||||||
|
password: "authelia_pass"
|
||||||
|
};
|
||||||
|
|
||||||
|
const client = new MongoClient(configuration, logger);
|
||||||
|
return client.collection("test")
|
||||||
|
.then(() => {
|
||||||
|
Assert(MongoClientStub.calledWith("mongo://url", {
|
||||||
|
auth: {
|
||||||
|
user: "authelia",
|
||||||
|
password: "authelia_pass"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("collection", () => {
|
||||||
before(function() {
|
before(function() {
|
||||||
mongoClientStub = {
|
mongoClientStub = {
|
||||||
db: Sinon.stub()
|
db: Sinon.stub()
|
||||||
|
@ -38,7 +85,7 @@ describe("connectors/mongo/MongoClient", function () {
|
||||||
|
|
||||||
it("should create a collection", function () {
|
it("should create a collection", function () {
|
||||||
const COLLECTION_NAME = "mycollection";
|
const COLLECTION_NAME = "mycollection";
|
||||||
const client = new MongoClient("mongo://url", "databasename", logger);
|
const client = new MongoClient(configuration, logger);
|
||||||
|
|
||||||
mongoDatabaseStub.collection.returns("COL");
|
mongoDatabaseStub.collection.returns("COL");
|
||||||
return client.collection(COLLECTION_NAME)
|
return client.collection(COLLECTION_NAME)
|
||||||
|
@ -60,12 +107,12 @@ describe("connectors/mongo/MongoClient", function () {
|
||||||
|
|
||||||
it("should fail creating the collection", function() {
|
it("should fail creating the collection", function() {
|
||||||
const COLLECTION_NAME = "mycollection";
|
const COLLECTION_NAME = "mycollection";
|
||||||
const client = new MongoClient("mongo://url", "databasename", logger);
|
const client = new MongoClient(configuration, logger);
|
||||||
|
|
||||||
mongoDatabaseStub.collection.returns("COL");
|
mongoDatabaseStub.collection.returns("COL");
|
||||||
return client.collection(COLLECTION_NAME)
|
return client.collection(COLLECTION_NAME)
|
||||||
.then((collection) => Bluebird.reject(new Error("should not be here")))
|
.then((collection) => Bluebird.reject(new Error("should not be here.")))
|
||||||
.error((err) => Bluebird.resolve());
|
.catch((err) => Bluebird.resolve());
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,31 +4,47 @@ import { IMongoClient } from "./IMongoClient";
|
||||||
import Bluebird = require("bluebird");
|
import Bluebird = require("bluebird");
|
||||||
import { AUTHENTICATION_FAILED } from "../../../../../shared/UserMessages";
|
import { AUTHENTICATION_FAILED } from "../../../../../shared/UserMessages";
|
||||||
import { IGlobalLogger } from "../../logging/IGlobalLogger";
|
import { IGlobalLogger } from "../../logging/IGlobalLogger";
|
||||||
|
import { MongoStorageConfiguration } from "../../configuration/schema/StorageConfiguration";
|
||||||
|
|
||||||
export class MongoClient implements IMongoClient {
|
export class MongoClient implements IMongoClient {
|
||||||
private url: string;
|
private configuration: MongoStorageConfiguration;
|
||||||
private databaseName: string;
|
|
||||||
|
|
||||||
private database: MongoDB.Db;
|
private database: MongoDB.Db;
|
||||||
private client: MongoDB.MongoClient;
|
private client: MongoDB.MongoClient;
|
||||||
private logger: IGlobalLogger;
|
private logger: IGlobalLogger;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
url: string,
|
configuration: MongoStorageConfiguration,
|
||||||
databaseName: string,
|
|
||||||
logger: IGlobalLogger) {
|
logger: IGlobalLogger) {
|
||||||
|
|
||||||
this.url = url;
|
this.configuration = configuration;
|
||||||
this.databaseName = databaseName;
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(): Bluebird<void> {
|
connect(): Bluebird<void> {
|
||||||
const that = this;
|
const that = this;
|
||||||
const connectAsync = Bluebird.promisify(MongoDB.MongoClient.connect);
|
const options: MongoDB.MongoClientOptions = {};
|
||||||
return connectAsync(this.url)
|
if (that.configuration.auth) {
|
||||||
|
options["auth"] = {
|
||||||
|
user: that.configuration.auth.username,
|
||||||
|
password: that.configuration.auth.password
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Bluebird((resolve, reject) => {
|
||||||
|
MongoDB.MongoClient.connect(
|
||||||
|
this.configuration.url,
|
||||||
|
options,
|
||||||
|
function(err, client) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(client);
|
||||||
|
});
|
||||||
|
})
|
||||||
.then(function (client: MongoDB.MongoClient) {
|
.then(function (client: MongoDB.MongoClient) {
|
||||||
that.database = client.db(that.databaseName);
|
that.database = client.db(that.configuration.database);
|
||||||
that.database.on("close", () => {
|
that.database.on("close", () => {
|
||||||
that.logger.info("[MongoClient] Lost connection.");
|
that.logger.info("[MongoClient] Lost connection.");
|
||||||
});
|
});
|
||||||
|
|
|
@ -103,7 +103,14 @@ declareNeedsConfiguration("totp_issuer", createCustomTotpIssuerConfiguration);
|
||||||
|
|
||||||
function registerUser(context: any, username: string) {
|
function registerUser(context: any, username: string) {
|
||||||
let secret: TOTPSecret;
|
let secret: TOTPSecret;
|
||||||
const mongoClient = new MongoClient("mongodb://localhost:27017", "authelia", new GlobalLoggerStub());
|
const mongoClient = new MongoClient({
|
||||||
|
url: "mongodb://localhost:27017",
|
||||||
|
database: "authelia",
|
||||||
|
auth: {
|
||||||
|
username: "authelia",
|
||||||
|
password: "authelia"
|
||||||
|
}
|
||||||
|
}, new GlobalLoggerStub());
|
||||||
const collectionFactory = CollectionFactoryFactory.createMongo(mongoClient);
|
const collectionFactory = CollectionFactoryFactory.createMongo(mongoClient);
|
||||||
const userDataStore = new UserDataStore(collectionFactory);
|
const userDataStore = new UserDataStore(collectionFactory);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue