diff --git a/source/app.d b/source/app.d index 5d616b6..018aa57 100644 --- a/source/app.d +++ b/source/app.d @@ -1,92 +1,6 @@ -import std.datetime.date; -import std.typecons : Nullable; - +import calendarwebapp; import vibe.vibe; -class CalendarWebapp -{ -private: - immutable fileName = Path("events.json"); - - enum EventType - { - Holiday, - Birthday, - FSI_Event, - General_University_Event, - Any - } - - struct Entry - { - @name("date") Date begin; - @name("end_date") Nullable!Date end; - Event event; - } - - struct Event - { - @(vibe.data.serialization.name("eid")) string id; - string name; - @(vibe.data.serialization.name("desc")) string[] description; - @(vibe.data.serialization.name("etype")) EventType type; - bool shout; - } - - Entry[] getEventsFromFile(in Path fileName) - { - Entry[] entries; - try - { - auto entriesString = readFileUTF8(fileName); - - try - { - deserializeJson(entries, entriesString.parseJsonString); - } - catch (std.json.JSONException) - { - } - } - catch(Exception) - {} - return entries; - } - -public: - - @method(HTTPMethod.POST) @path("/event/create") - void createEvent(Date begin, Nullable!Date end, string description, - string name, EventType type, bool shout) - { - import std.array : split, replace; - - if (!end.isNull) - enforce(end - begin >= 1.days); - - auto entry = Entry(begin, end, Event("", name, - description.replace("\r", "").split('\n'), type, shout)); - - auto entries = getEventsFromFile(fileName); - entries ~= entry; - writeFileUTF8(fileName, serializeToPrettyJson(entries)); - render!("showevents.dt", entries); - } - - @method(HTTPMethod.GET) @path("create") - void newEvent() - { - render!("create.dt"); - } - - void index() - { - auto entries = getEventsFromFile(fileName); - render!("showevents.dt", entries); - } - -} - shared static this() { auto router = new URLRouter; @@ -95,6 +9,7 @@ shared static this() auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; + settings.sessionStore = new MemorySessionStore; listenHTTP(settings, router); logInfo("Please open http://127.0.0.1:8080/ in your browser."); diff --git a/source/calendarwebapp.d b/source/calendarwebapp.d new file mode 100644 index 0000000..b773041 --- /dev/null +++ b/source/calendarwebapp.d @@ -0,0 +1,93 @@ +module calendarwebapp; + +import event; + +import std.datetime.date; +import std.typecons : Nullable; + +import vibe.vibe; + +class CalendarWebapp +{ +private: + enum auth = before!ensureAuth("userName"); + + immutable fileName = Path("events.json"); + + struct UserData + { + bool loggedIn; + string name; + string uuid; + } + + SessionVar!(UserData, "user") user; + + Entry[] getEntriesFromFile(in Path fileName) + { + Entry[] entries; + if (fileName.existsFile) + { + deserializeJson(entries, fileName.readFileUTF8.parseJsonString); + } + return entries; + } + + string ensureAuth(HTTPServerRequest req, HTTPServerResponse res) + { + if (!user.loggedIn) + redirect("/login"); + return user.name; + } + + mixin PrivateAccessProxy; + +public: + + @auth @method(HTTPMethod.POST) @path("/event/create") + void createEvent(Date begin, Nullable!Date end, string description, + string name, EventType type, bool shout, string userName) + { + import std.array : split, replace; + + if (!end.isNull) + enforce(end - begin >= 1.days); + + auto entry = Entry(begin, end, Event("", name, + description.replace("\r", "").split('\n'), type, shout)); + + auto entries = getEntriesFromFile(fileName) ~ entry; + fileName.writeFileUTF8(entries.serializeToPrettyJson); + render!("showevents.dt", entries); + } + + @auth @method(HTTPMethod.GET) @path("create") + void newEvent(string userName) + { + render!("create.dt"); + } + + @auth void index(string userName) + { + auto entries = getEntriesFromFile(fileName); + render!("showevents.dt", entries); + } + + void getLogin() + { + render!("login.dt"); + } + + void postLogin(string username, string password) + { + import std.uuid : randomUUID; + + enforce(username == "foo" && password == "bar", "Invalid username / password"); + UserData d; + d.loggedIn = true; + d.name = username; + d.uuid = randomUUID.toString; + user = d; + redirect("/"); + } +} diff --git a/source/event.d b/source/event.d new file mode 100644 index 0000000..0960686 --- /dev/null +++ b/source/event.d @@ -0,0 +1,31 @@ +module event; + +import std.datetime.date; +import std.typecons : Nullable; + +import vibe.data.serialization; + +enum EventType +{ + Holiday, + Birthday, + FSI_Event, + General_University_Event, + Any +} + +struct Entry +{ + @name("date") Date begin; + @name("end_date") Nullable!Date end; + Event event; +} + +struct Event +{ + @(vibe.data.serialization.name("eid")) string id; + string name; + @(vibe.data.serialization.name("desc")) string[] description; + @(vibe.data.serialization.name("etype")) EventType type; + bool shout; +} diff --git a/views/login.dt b/views/login.dt new file mode 100644 index 0000000..cad8666 --- /dev/null +++ b/views/login.dt @@ -0,0 +1,21 @@ +extends layout +block content + h1 Anmelden + form(action="/login", method="post") + fieldset(name="loginFields") + table + tbody#fieldTable + tr + td + label(for="username") Benutzername + td + input#username(value="", name="username", type="text") + tr + td + label(for="password") Passwort + td + input#password(value="", name="password", type="password") + tfoot + tr + td(colspan="2") + input#submitButton(type="submit", value="Anmelden")