Initial work for support for different user roles.

This commit is contained in:
Johannes Loher 2017-10-26 20:08:16 +02:00
parent bebb5079c4
commit 4959c67e89
3 changed files with 45 additions and 14 deletions

View file

@ -2,11 +2,14 @@ module calendarwebapp.authenticator;
import poodinis;
import std.typecons : nullable, Nullable;
import vibe.data.bson : Bson, BsonObjectID, deserializeBson;
import vibe.db.mongo.collection : MongoCollection;
interface Authenticator
{
bool checkUser(string username, string password) @safe;
Nullable!AuthInfo checkUser(string username, string password) @safe;
}
class MongoDBAuthenticator(Collection = MongoCollection) : Authenticator
@ -16,21 +19,48 @@ private:
Collection users;
public:
bool checkUser(string username, string password) @safe
Nullable!AuthInfo checkUser(string username, string password) @safe
{
import botan.passhash.bcrypt : checkBcrypt;
import vibe.data.bson : Bson;
auto result = users.findOne(["username" : username]);
/* checkBcrypt should be called using vibe.core.concurrency.async to
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
blocking this */
return (result != Bson(null)) && (() @trusted => checkBcrypt(password,
result["password"].get!string))();
if (result != Bson(null))
{
auto authInfo = result.deserializeBson!AuthInfo;
if ((()@trusted => checkBcrypt(password, authInfo.passwordHash))())
{
return authInfo.nullable;
}
}
return Nullable!AuthInfo();
}
}
enum Role
{
User,
Admin
}
struct AuthInfo
{
string userName;
import vibe.data.serialization : name;
@name("_id") BsonObjectID id;
string username;
string passwordHash;
Role role;
bool isUser()
{
return role == Role.User;
}
bool isAdmin()
{
return role == Role.Admin;
}
}

View file

@ -45,9 +45,9 @@ public:
@noAuth @errorDisplay!getLogin void postLogin(string username, string password) @safe
{
enforce(authenticator.checkUser(username, password), "Benutzername oder Passwort ungültig");
immutable AuthInfo authInfo = {username};
auth = authInfo;
auto authInfo = authenticator.checkUser(username, password);
enforce(!authInfo.isNull, "Benutzername oder Passwort ungültig");
auth = authInfo.get;
redirect("/");
}

View file

@ -41,13 +41,14 @@ public:
container.register!(Authenticator, MongoDBAuthenticator!(Collection))(
RegistrationOption.doNotAddConcreteTypeRegistration);
auto userBson = Bson(["_id" : Bson(BsonObjectID.fromString("5988ef4ae6c19089a1a53b79")), "username" : Bson("foo"),
"password" : Bson("$2a$10$9LBqOZV99ARiE4Nx.2b7GeYfqk2.0A32PWGu2cRGyW2hRJ0xeDfnO")]);
auto userBson = Bson(["_id" : Bson(BsonObjectID.fromString("5988ef4ae6c19089a1a53b79")),
"username" : Bson("foo"), "passwordHash"
: Bson("$2a$10$9LBqOZV99ARiE4Nx.2b7GeYfqk2.0A32PWGu2cRGyW2hRJ0xeDfnO"), "role" : Bson(1)]);
collection.returnValue!"findOne"(Bson(null), userBson, userBson);
auto authenticator = container.resolve!(Authenticator);
authenticator.checkUser("", "").shouldBeFalse;
authenticator.checkUser("foo", "bar").shouldBeTrue;
authenticator.checkUser("foo", "baz").shouldBeFalse;
authenticator.checkUser("", "").isNull.shouldBeTrue;
authenticator.checkUser("foo", "bar").isNull.shouldBeFalse;
authenticator.checkUser("foo", "baz").isNull.shouldBeTrue;
}