Update to poodinis 8.0.1, use Value injection for MongoDBCollections, Use an ApplicationContext for registering of components, fix multiday events, use a string for description of events instead of a dynamic array of strings

This commit is contained in:
Johannes Loher 2017-08-13 19:54:40 +02:00
parent 974a741132
commit 64cc7e5b49
10 changed files with 88 additions and 54 deletions

2
.gitignore vendored
View file

@ -4,6 +4,6 @@ __dummy.html
*.o *.o
*.obj *.obj
__test__*__ __test__*__
calendar-webapp calendar-webapp*
events.json events.json
dub.selections.json dub.selections.json

View file

@ -5,7 +5,7 @@
], ],
"dependencies": { "dependencies": {
"vibe-d": "0.8.1-rc.2", "vibe-d": "0.8.1-rc.2",
"poodinis": "~>8.0.0" "poodinis": "~>8.0.1"
}, },
"description": "A simple webapplication to edit and view calendar entries", "description": "A simple webapplication to edit and view calendar entries",
"copyright": "Copyright © 2017, Johannes Loher", "copyright": "Copyright © 2017, Johannes Loher",

View file

@ -1,3 +1,7 @@
.error { .error {
color: red; color: red;
}
td.pre {
white-space: pre;
} }

View file

@ -1,15 +1,12 @@
module app; module app;
import authenticator : Authenticator, MongoDBAuthenticator;
import calendarwebapp : CalendarWebapp; import calendarwebapp : CalendarWebapp;
import configuration : StringInjector; import configuration : Context;
import event : EventStore, MongoDBEventStore;
import poodinis; import poodinis;
import vibe.core.log : logInfo; import vibe.core.log : logInfo;
import vibe.db.mongo.client : MongoClient;
import vibe.db.mongo.mongo : connectMongoDB;
import vibe.http.fileserver : serveStaticFiles; import vibe.http.fileserver : serveStaticFiles;
import vibe.http.router : URLRouter; import vibe.http.router : URLRouter;
import vibe.http.server : HTTPServerSettings, listenHTTP, MemorySessionStore; import vibe.http.server : HTTPServerSettings, listenHTTP, MemorySessionStore;
@ -17,16 +14,11 @@ import vibe.web.web : registerWebInterface;
shared static this() shared static this()
{ {
auto dependencies = new shared DependencyContainer(); auto container = new shared DependencyContainer();
auto db = connectMongoDB("localhost"); container.registerContext!Context;
dependencies.register!MongoClient.existingInstance(db);
dependencies.register!(EventStore, MongoDBEventStore);
dependencies.register!(Authenticator, MongoDBAuthenticator);
dependencies.register!CalendarWebapp;
dependencies.register!(ValueInjector!string, StringInjector);
auto router = new URLRouter; auto router = new URLRouter;
router.registerWebInterface(dependencies.resolve!CalendarWebapp); router.registerWebInterface(container.resolve!CalendarWebapp);
router.get("*", serveStaticFiles("public")); router.get("*", serveStaticFiles("public"));
auto settings = new HTTPServerSettings; auto settings = new HTTPServerSettings;

View file

@ -3,7 +3,7 @@ module authenticator;
import poodinis; import poodinis;
import vibe.data.bson : Bson; import vibe.data.bson : Bson;
import vibe.db.mongo.client : MongoClient; import vibe.db.mongo.collection : MongoCollection;
interface Authenticator interface Authenticator
{ {
@ -13,18 +13,12 @@ interface Authenticator
class MongoDBAuthenticator : Authenticator class MongoDBAuthenticator : Authenticator
{ {
private: private:
@Autowire MongoClient mongoClient; @Value("users")
MongoCollection users;
@Value("Database name")
string databaseName;
@Value("Users collection name")
string usersCollectionName;
public: public:
bool checkUser(string username, string password) @safe bool checkUser(string username, string password) @safe
{ {
auto users = mongoClient.getCollection(databaseName ~ "." ~ usersCollectionName);
auto result = users.findOne(["username" : username, "password" : password]); auto result = users.findOne(["username" : username, "password" : password]);
return result != Bson(null); return result != Bson(null);
} }

View file

@ -72,7 +72,7 @@ public:
enforce(end - begin >= 1.days, enforce(end - begin >= 1.days,
"Mehrtägige Ereignisse müssen mindestens einen Tag dauern"); "Mehrtägige Ereignisse müssen mindestens einen Tag dauern");
auto event = Event(BsonObjectID.generate, begin, end, name, auto event = Event(BsonObjectID.generate, begin, end, name,
description.replace("\r", "").split('\n'), type, shout); description.replace("\r", ""), type, shout);
eventStore.addEvent(event); eventStore.addEvent(event);

View file

@ -1,6 +1,29 @@
module configuration; module configuration;
import poodinis : ValueInjector; import authenticator : Authenticator, MongoDBAuthenticator;
import calendarwebapp : CalendarWebapp;
import event : EventStore, MongoDBEventStore;
import poodinis;
import vibe.db.mongo.client : MongoClient;
import vibe.db.mongo.collection : MongoCollection;
import vibe.db.mongo.mongo : connectMongoDB;
class Context : ApplicationContext
{
public:
override void registerDependencies(shared(DependencyContainer) container)
{
auto mongoClient = connectMongoDB("localhost");
container.register!MongoClient.existingInstance(mongoClient);
container.register!(EventStore, MongoDBEventStore);
container.register!(Authenticator, MongoDBAuthenticator);
container.register!CalendarWebapp;
container.register!(ValueInjector!string, StringInjector);
container.register!(ValueInjector!MongoCollection, MongoCollectionInjector);
}
}
class StringInjector : ValueInjector!string class StringInjector : ValueInjector!string
{ {
@ -13,12 +36,26 @@ public:
// dfmt off // dfmt off
config = ["Database name" : "CalendarWebapp", config = ["Database name" : "CalendarWebapp",
"Users collection name": "users", "Users collection name": "users",
"Entries collection name" : "entries"]; "Events collection name" : "events"];
// dfmt on // dfmt on
} }
string get(string key) const @safe pure nothrow override string get(string key) const @safe pure nothrow
{ {
return config[key]; return config[key];
} }
} }
class MongoCollectionInjector : ValueInjector!MongoCollection
{
private:
@Autowire MongoClient mongoClient;
@Value("Database name")
string databaseName;
public:
override MongoCollection get(string key) @safe
{
return mongoClient.getCollection(databaseName ~ "." ~ key);
}
}

View file

@ -9,7 +9,7 @@ import std.typecons : Nullable;
import vibe.data.bson : Bson, BsonObjectID, deserializeBson, serializeToBson; import vibe.data.bson : Bson, BsonObjectID, deserializeBson, serializeToBson;
import vibe.data.serialization : serializationName = name; import vibe.data.serialization : serializationName = name;
import vibe.db.mongo.client : MongoClient; import vibe.db.mongo.collection : MongoCollection;
interface EventStore interface EventStore
{ {
@ -25,14 +25,12 @@ class MongoDBEventStore : EventStore
public: public:
Event getEvent(BsonObjectID id) @safe Event getEvent(BsonObjectID id) @safe
{ {
return mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName) return events.findOne(["_id" : id]).deserializeBson!Event;
.findOne(["_id" : id]).deserializeBson!Event;
} }
InputRange!Event getAllEvents() @safe InputRange!Event getAllEvents() @safe
{ {
return mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName) return events.find().map!(deserializeBson!Event).inputRangeObject;
.find().map!(deserializeBson!Event).inputRangeObject;
} }
void addEvent(Event event) @safe void addEvent(Event event) @safe
@ -40,31 +38,24 @@ public:
if (!event.id.valid) if (!event.id.valid)
event.id = BsonObjectID.generate; event.id = BsonObjectID.generate;
mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName) events.insert(event.serializeToBson);
.insert(event.serializeToBson);
} }
InputRange!Event getEventsBeginningBetween(Date begin, Date end) @safe InputRange!Event getEventsBeginningBetween(Date begin, Date end) @safe
{ {
return mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName) return events.find(["$and" : [["date" : ["$gte" : begin.serializeToBson]], ["date"
.find(["$and" : [["date" : ["$gte" : begin.serializeToBson]], ["date"
: ["$lte" : end.serializeToBson]]]]).map!(deserializeBson!Event) : ["$lte" : end.serializeToBson]]]]).map!(deserializeBson!Event)
.inputRangeObject; .inputRangeObject;
} }
void removeEvent(BsonObjectID id) @safe void removeEvent(BsonObjectID id) @safe
{ {
mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName).remove(["_id" : id]); events.remove(["_id" : id]);
} }
private: private:
@Autowire MongoClient mongoClient; @Value("events")
MongoCollection events;
@Value("Database name")
string databaseName;
@Value("Entries collection name")
string entriesCollectionName;
} }
enum EventType enum EventType
@ -82,7 +73,7 @@ struct Event
@serializationName("date") Date begin; @serializationName("date") Date begin;
@serializationName("end_date") Nullable!Date end; @serializationName("end_date") Nullable!Date end;
string name; string name;
@serializationName("desc") string[] description; @serializationName("desc") string description;
@serializationName("etype") EventType type; @serializationName("etype") EventType type;
bool shout; bool shout;
} }

View file

@ -21,15 +21,15 @@ block content
- showerror("description"); - showerror("description");
tr tr
td td
label(for="begin") Von label(for="multiday") Mehrtägig
td
input#multiday(name="multiday", type="checkbox")
tr
td
label#beginLabel(for="begin") Datum
td td
input#begin(value="", name="begin", type="date") input#begin(value="", name="begin", type="date")
- showerror("begin"); - showerror("begin");
tr
td
label(for="end") Bis
td
input#end(value="", name="end", type="date")
- showerror("end"); - showerror("end");
tr tr
td td
@ -54,4 +54,20 @@ block content
td(colspan="2") td(colspan="2")
input#submitButton(type="submit", value="Ereignis erstellen") input#submitButton(type="submit", value="Ereignis erstellen")
- if (_error.msg && _error.field == "") - if (_error.msg && _error.field == "")
p.error= _error.msg p.error= _error.msg
script(type="text/javascript").
document.getElementById('multiday').onclick = function() {
var table = document.getElementById("fieldTable");
var beginLabel = document.getElementById("beginLabel");
if ( this.checked ) {
var row = table.insertRow(4);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = "<label for='end'>Bis</label>";
cell2.innerHTML = "<input id='end' value='' name='end' type='date'>";
beginLabel.innerHTML = "Von";
} else {
table.deleteRow(4);
beginLabel.innerHTML = "Datum";
}
};

View file

@ -17,7 +17,7 @@ block content
td #{event.name} td #{event.name}
tr tr
td desc td desc
td #{event.description} td.pre #{event.description}
tr tr
td etype td etype
td #{event.type} td #{event.type}