Merge branch 'master' into JSON-export
This commit is contained in:
commit
29a20fa4fb
4 changed files with 131 additions and 43 deletions
|
@ -30,14 +30,15 @@ private:
|
||||||
public:
|
public:
|
||||||
Nullable!AuthInfo checkUser(string username, string password) @safe
|
Nullable!AuthInfo checkUser(string username, string password) @safe
|
||||||
{
|
{
|
||||||
auto result = users.findOne(["username" : username]);
|
import vibe.core.concurrency : async;
|
||||||
/* checkHash should be called using vibe.core.concurrency.async to
|
|
||||||
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
|
immutable result = users.findOne(["username" : username]);
|
||||||
blocking this */
|
|
||||||
if (result != Bson(null))
|
if (result != Bson(null))
|
||||||
{
|
{
|
||||||
auto authInfo = result.deserializeBson!AuthInfo;
|
auto authInfo = result.deserializeBson!AuthInfo;
|
||||||
if (passwordHasher.checkHash(password, authInfo.passwordHash))
|
if ((()@trusted => async(() => passwordHasher.checkHash(password,
|
||||||
|
authInfo.passwordHash)).getResult)())
|
||||||
{
|
{
|
||||||
return authInfo.nullable;
|
return authInfo.nullable;
|
||||||
}
|
}
|
||||||
|
@ -90,15 +91,19 @@ private:
|
||||||
|
|
||||||
@Autowire MySQLPool pool;
|
@Autowire MySQLPool pool;
|
||||||
@Autowire PasswordHasher passwordHasher;
|
@Autowire PasswordHasher passwordHasher;
|
||||||
|
@Value("mysql.table.users") string usersTableName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nullable!AuthInfo checkUser(string username, string password) @trusted
|
Nullable!AuthInfo checkUser(string username, string password) @trusted
|
||||||
{
|
{
|
||||||
|
import vibe.core.concurrency : async;
|
||||||
|
|
||||||
auto cn = pool.lockConnection();
|
auto cn = pool.lockConnection();
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close();
|
cn.close();
|
||||||
auto prepared = cn.prepare(
|
auto prepared = cn.prepare(
|
||||||
"SELECT id, username, passwordHash, privilege FROM users WHERE username = ?");
|
"SELECT id, username, passwordHash, privilege FROM "
|
||||||
|
~ usersTableName ~ " WHERE username = ?");
|
||||||
prepared.setArg(0, username);
|
prepared.setArg(0, username);
|
||||||
auto result = prepared.query();
|
auto result = prepared.query();
|
||||||
/* checkHash should be called using vibe.core.concurrency.async to
|
/* checkHash should be called using vibe.core.concurrency.async to
|
||||||
|
@ -107,7 +112,7 @@ public:
|
||||||
if (!result.empty)
|
if (!result.empty)
|
||||||
{
|
{
|
||||||
auto authInfo = toAuthInfo(result.front);
|
auto authInfo = toAuthInfo(result.front);
|
||||||
if (passwordHasher.checkHash(password, authInfo.passwordHash))
|
if (async(() => passwordHasher.checkHash(password, authInfo.passwordHash)).getResult)
|
||||||
{
|
{
|
||||||
return authInfo.nullable;
|
return authInfo.nullable;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +126,7 @@ public:
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare(
|
auto prepared = cn.prepare(
|
||||||
"INSERT INTO users (username, passwordHash, privilege) VALUES(?, ?, ?)");
|
"INSERT INTO " ~ usersTableName ~ " (username, passwordHash, privilege) VALUES(?, ?, ?)");
|
||||||
prepared.setArgs(authInfo.username, authInfo.passwordHash, authInfo.privilege.to!uint);
|
prepared.setArgs(authInfo.username, authInfo.passwordHash, authInfo.privilege.to!uint);
|
||||||
prepared.exec();
|
prepared.exec();
|
||||||
}
|
}
|
||||||
|
@ -134,7 +139,7 @@ public:
|
||||||
auto cn = pool.lockConnection();
|
auto cn = pool.lockConnection();
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare("SELECT id, username, passwordHash, privilege FROM users");
|
auto prepared = cn.prepare("SELECT id, username, passwordHash, privilege FROM " ~ usersTableName ~ "");
|
||||||
return prepared.querySet.map!(r => toAuthInfo(r)).inputRangeObject;
|
return prepared.querySet.map!(r => toAuthInfo(r)).inputRangeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,14 +148,14 @@ public:
|
||||||
auto cn = pool.lockConnection();
|
auto cn = pool.lockConnection();
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare("DELETE FROM users WHERE id = ?");
|
auto prepared = cn.prepare("DELETE FROM " ~ usersTableName ~ " WHERE id = ?");
|
||||||
prepared.setArg(0, id.to!uint);
|
prepared.setArg(0, id.to!uint);
|
||||||
prepared.exec();
|
prepared.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AuthInfo toAuthInfo(Row r)
|
AuthInfo toAuthInfo(in Row r)
|
||||||
{
|
{
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ public:
|
||||||
render!("createevent.dt", _error, authInfo);
|
render!("createevent.dt", _error, authInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@auth(Role.user | Role.admin) @errorDisplay!getCreateevent void postCreateevent(Date begin,
|
@auth(Role.user | Role.admin) @errorDisplay!getCreateevent void postCreateevent(Date begin,
|
||||||
Nullable!Date end, string description, string name, EventType type, bool shout)
|
Nullable!Date end, string description, string name, EventType type, bool shout)
|
||||||
{
|
{
|
||||||
|
@ -109,8 +108,10 @@ public:
|
||||||
@auth(Role.admin) @errorDisplay!getCreateuser void postCreateuser(string username,
|
@auth(Role.admin) @errorDisplay!getCreateuser void postCreateuser(string username,
|
||||||
string password, Privilege role)
|
string password, Privilege role)
|
||||||
{
|
{
|
||||||
|
import vibe.core.concurrency : async;
|
||||||
|
|
||||||
authenticator.addUser(AuthInfo("", username,
|
authenticator.addUser(AuthInfo("", username,
|
||||||
passwordHasher.generateHash(password), role));
|
async(() => passwordHasher.generateHash(password)).getResult, role));
|
||||||
redirect("/users");
|
redirect("/users");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,8 +122,8 @@ private:
|
||||||
string field;
|
string field;
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionVar!(AuthInfo, "authInfo") authInfo = AuthInfo("",
|
SessionVar!(AuthInfo, "authInfo") authInfo = AuthInfo("", string.init,
|
||||||
string.init, string.init, Privilege.None);
|
string.init, Privilege.None);
|
||||||
|
|
||||||
@Autowire EventStore eventStore;
|
@Autowire EventStore eventStore;
|
||||||
@Autowire Authenticator authenticator;
|
@Autowire Authenticator authenticator;
|
||||||
|
|
|
@ -1,34 +1,53 @@
|
||||||
module calendarwebapp.configuration;
|
module calendarwebapp.configuration;
|
||||||
|
|
||||||
import calendarwebapp.authenticator : Authenticator, MongoDBAuthenticator,
|
import calendarwebapp.authenticator : Authenticator;
|
||||||
MySQLAuthenticator;
|
|
||||||
import calendarwebapp.calendarwebapp : CalendarWebapp;
|
import calendarwebapp.calendarwebapp : CalendarWebapp;
|
||||||
import calendarwebapp.event : EventStore, MongoDBEventStore, MySQLEventStore;
|
import calendarwebapp.event : EventStore;
|
||||||
import calendarwebapp.passhash : PasswordHasher, SHA256PasswordHasher;
|
import calendarwebapp.passhash : PasswordHasher, SHA256PasswordHasher;
|
||||||
|
|
||||||
import mysql : MySQLPool;
|
|
||||||
|
|
||||||
import poodinis;
|
import poodinis;
|
||||||
|
|
||||||
import vibe.db.mongo.client : MongoClient;
|
import vibe.core.log : logInfo;
|
||||||
import vibe.db.mongo.collection : MongoCollection;
|
import vibe.db.mongo.collection : MongoCollection;
|
||||||
import vibe.db.mongo.mongo : connectMongoDB;
|
|
||||||
|
|
||||||
class Context : ApplicationContext
|
class Context : ApplicationContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
override void registerDependencies(shared(DependencyContainer) container)
|
override void registerDependencies(shared(DependencyContainer) container)
|
||||||
{
|
{
|
||||||
auto mongoClient = connectMongoDB("localhost");
|
container.register!(ValueInjector!Arguments, AppArgumentsInjector);
|
||||||
auto pool = new MySQLPool("localhost", "username", "password", "CalendarWebapp");
|
auto arguments = container.resolve!(AppArgumentsInjector).get("");
|
||||||
container.register!MySQLPool.existingInstance(pool);
|
final switch (arguments.database) with (DatabaseArgument)
|
||||||
container.register!MongoClient.existingInstance(mongoClient);
|
{
|
||||||
container.register!(EventStore, MySQLEventStore);
|
case mongodb:
|
||||||
container.register!(Authenticator, MySQLAuthenticator);
|
import vibe.db.mongo.client : MongoClient;
|
||||||
|
import vibe.db.mongo.mongo : connectMongoDB;
|
||||||
|
import calendarwebapp.authenticator : MongoDBAuthenticator;
|
||||||
|
import calendarwebapp.event : MongoDBEventStore;
|
||||||
|
|
||||||
|
auto mongoClient = connectMongoDB(arguments.mongodb.host);
|
||||||
|
container.register!MongoClient.existingInstance(mongoClient);
|
||||||
|
container.register!(EventStore, MongoDBEventStore!());
|
||||||
|
container.register!(Authenticator, MongoDBAuthenticator!());
|
||||||
|
container.register!(ValueInjector!MongoCollection, MongoCollectionInjector);
|
||||||
|
logInfo("Using MongoDB as database system");
|
||||||
|
break;
|
||||||
|
case mysql:
|
||||||
|
import mysql : MySQLPool;
|
||||||
|
import calendarwebapp.authenticator : MySQLAuthenticator;
|
||||||
|
import calendarwebapp.event : MySQLEventStore;
|
||||||
|
|
||||||
|
auto pool = new MySQLPool(arguments.mysql.host, arguments.mysql.username,
|
||||||
|
arguments.mysql.password, arguments.mysql.database);
|
||||||
|
container.register!MySQLPool.existingInstance(pool);
|
||||||
|
container.register!(EventStore, MySQLEventStore);
|
||||||
|
container.register!(Authenticator, MySQLAuthenticator);
|
||||||
|
logInfo("Using MySQL as database system");
|
||||||
|
break;
|
||||||
|
}
|
||||||
container.register!(PasswordHasher, SHA256PasswordHasher);
|
container.register!(PasswordHasher, SHA256PasswordHasher);
|
||||||
container.register!CalendarWebapp;
|
container.register!CalendarWebapp;
|
||||||
container.register!(ValueInjector!string, StringInjector);
|
container.register!(ValueInjector!string, StringInjector);
|
||||||
container.register!(ValueInjector!MongoCollection, MongoCollectionInjector);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,19 +55,18 @@ class StringInjector : ValueInjector!string
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
string[string] config;
|
string[string] config;
|
||||||
|
@Value() Arguments arguments;
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
this() const @safe pure nothrow
|
|
||||||
{
|
|
||||||
// dfmt off
|
|
||||||
config = ["Database name" : "CalendarWebapp",
|
|
||||||
"Users collection name": "users",
|
|
||||||
"Events collection name" : "events"];
|
|
||||||
// dfmt on
|
|
||||||
}
|
|
||||||
|
|
||||||
override string get(string key) const @safe pure nothrow
|
override string get(string key) @safe nothrow
|
||||||
{
|
{
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
config = ["MongoDB database name" : arguments.mongodb.database,
|
||||||
|
"mysql.table.users" : "users", "mysql.table.events" : "events"];
|
||||||
|
}
|
||||||
return config[key];
|
return config[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +74,10 @@ public:
|
||||||
class MongoCollectionInjector : ValueInjector!MongoCollection
|
class MongoCollectionInjector : ValueInjector!MongoCollection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
import vibe.db.mongo.client : MongoClient;
|
||||||
|
|
||||||
@Autowire MongoClient mongoClient;
|
@Autowire MongoClient mongoClient;
|
||||||
@Value("Database name")
|
@Value("MongoDB database name")
|
||||||
string databaseName;
|
string databaseName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -66,3 +86,63 @@ public:
|
||||||
return mongoClient.getCollection(databaseName ~ "." ~ key);
|
return mongoClient.getCollection(databaseName ~ "." ~ key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AppArgumentsInjector : ValueInjector!Arguments
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Arguments arguments;
|
||||||
|
public:
|
||||||
|
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
import vibe.core.args : readOption;
|
||||||
|
|
||||||
|
readOption("database", &arguments.database, "The database system to use.");
|
||||||
|
readOption("mongodb.host", &arguments.mongodb.host,
|
||||||
|
"The host of the MongoDB instance to use.");
|
||||||
|
readOption("mongodb.database", &arguments.mongodb.database,
|
||||||
|
"The name of the MongoDB database to use.");
|
||||||
|
readOption("mysql.host", &arguments.mysql.host, "The host of the MySQL instance to use.");
|
||||||
|
readOption("mysql.username", &arguments.mysql.username,
|
||||||
|
"The username to use for logging into the MySQL instance.");
|
||||||
|
readOption("mysql.password", &arguments.mysql.password,
|
||||||
|
"The password to use for logging into the MySQL instance.");
|
||||||
|
readOption("mysql.database", &arguments.mysql.database,
|
||||||
|
"The name of the MySQL database to use.");
|
||||||
|
}
|
||||||
|
|
||||||
|
override Arguments get(string key) @safe
|
||||||
|
{
|
||||||
|
import std.exception : enforce;
|
||||||
|
|
||||||
|
enforce(key == "", "There is only one instance of Arguments, to inject it use @Value().");
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DatabaseArgument
|
||||||
|
{
|
||||||
|
mongodb,
|
||||||
|
mysql
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MySQLArguments
|
||||||
|
{
|
||||||
|
string host = "localhost";
|
||||||
|
string username = "username";
|
||||||
|
string password = "password";
|
||||||
|
string database = "CalendarWebapp";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MongoDBArguments
|
||||||
|
{
|
||||||
|
string host = "localhost";
|
||||||
|
string database = "CalendarWebapp";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Arguments
|
||||||
|
{
|
||||||
|
DatabaseArgument database = DatabaseArgument.mongodb;
|
||||||
|
MySQLArguments mysql;
|
||||||
|
MongoDBArguments mongodb;
|
||||||
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ class MySQLEventStore : EventStore
|
||||||
private:
|
private:
|
||||||
import mysql;
|
import mysql;
|
||||||
|
|
||||||
|
@Value("mysql.table.events") string eventsTableName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Event getEvent(string id)
|
Event getEvent(string id)
|
||||||
{
|
{
|
||||||
|
@ -80,7 +82,7 @@ public:
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare(
|
auto prepared = cn.prepare(
|
||||||
"SELECT id begin end name description type shout FROM events WHERE id = ?");
|
"SELECT id begin end name description type shout FROM " ~ eventsTableName ~ " WHERE id = ?");
|
||||||
prepared.setArg(0, id.to!uint);
|
prepared.setArg(0, id.to!uint);
|
||||||
return toEvent(prepared.query.front);
|
return toEvent(prepared.query.front);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +93,7 @@ public:
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare(
|
auto prepared = cn.prepare(
|
||||||
"SELECT id, begin, end, name, description, type, shout FROM events");
|
"SELECT id, begin, end, name, description, type, shout FROM " ~ eventsTableName ~ "");
|
||||||
return prepared.querySet.map!(r => toEvent(r)).inputRangeObject;
|
return prepared.querySet.map!(r => toEvent(r)).inputRangeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +103,7 @@ public:
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare(
|
auto prepared = cn.prepare(
|
||||||
"INSERT INTO events (begin, end, name, description, type, shout) VALUES(?, ?, ?, ?, ?, ?)");
|
"INSERT INTO " ~ eventsTableName ~ " (begin, end, name, description, type, shout) VALUES(?, ?, ?, ?, ?, ?)");
|
||||||
prepared.setArgs(event.begin, event.end, event.name, event.description,
|
prepared.setArgs(event.begin, event.end, event.name, event.description,
|
||||||
event.type.to!uint, event.shout);
|
event.type.to!uint, event.shout);
|
||||||
prepared.exec();
|
prepared.exec();
|
||||||
|
@ -123,7 +125,7 @@ public:
|
||||||
auto cn = pool.lockConnection();
|
auto cn = pool.lockConnection();
|
||||||
scope (exit)
|
scope (exit)
|
||||||
cn.close;
|
cn.close;
|
||||||
auto prepared = cn.prepare("DELETE FROM events WHERE id = ?");
|
auto prepared = cn.prepare("DELETE FROM " ~ eventsTableName ~ " WHERE id = ?");
|
||||||
prepared.setArg(0, id.to!uint);
|
prepared.setArg(0, id.to!uint);
|
||||||
prepared.exec();
|
prepared.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue