Initial work for support for different user roles.
This commit is contained in:
parent
bebb5079c4
commit
4959c67e89
3 changed files with 45 additions and 14 deletions
|
@ -2,11 +2,14 @@ module calendarwebapp.authenticator;
|
||||||
|
|
||||||
import poodinis;
|
import poodinis;
|
||||||
|
|
||||||
|
import std.typecons : nullable, Nullable;
|
||||||
|
|
||||||
|
import vibe.data.bson : Bson, BsonObjectID, deserializeBson;
|
||||||
import vibe.db.mongo.collection : MongoCollection;
|
import vibe.db.mongo.collection : MongoCollection;
|
||||||
|
|
||||||
interface Authenticator
|
interface Authenticator
|
||||||
{
|
{
|
||||||
bool checkUser(string username, string password) @safe;
|
Nullable!AuthInfo checkUser(string username, string password) @safe;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MongoDBAuthenticator(Collection = MongoCollection) : Authenticator
|
class MongoDBAuthenticator(Collection = MongoCollection) : Authenticator
|
||||||
|
@ -16,21 +19,48 @@ private:
|
||||||
Collection users;
|
Collection users;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool checkUser(string username, string password) @safe
|
Nullable!AuthInfo checkUser(string username, string password) @safe
|
||||||
{
|
{
|
||||||
import botan.passhash.bcrypt : checkBcrypt;
|
import botan.passhash.bcrypt : checkBcrypt;
|
||||||
import vibe.data.bson : Bson;
|
|
||||||
|
|
||||||
auto result = users.findOne(["username" : username]);
|
auto result = users.findOne(["username" : username]);
|
||||||
/* checkBcrypt should be called using vibe.core.concurrency.async to
|
/* checkBcrypt should be called using vibe.core.concurrency.async to
|
||||||
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
|
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
|
||||||
blocking this */
|
blocking this */
|
||||||
return (result != Bson(null)) && (() @trusted => checkBcrypt(password,
|
if (result != Bson(null))
|
||||||
result["password"].get!string))();
|
{
|
||||||
|
auto authInfo = result.deserializeBson!AuthInfo;
|
||||||
|
if ((()@trusted => checkBcrypt(password, authInfo.passwordHash))())
|
||||||
|
{
|
||||||
|
return authInfo.nullable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Nullable!AuthInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Role
|
||||||
|
{
|
||||||
|
User,
|
||||||
|
Admin
|
||||||
|
}
|
||||||
|
|
||||||
struct AuthInfo
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,9 @@ public:
|
||||||
|
|
||||||
@noAuth @errorDisplay!getLogin void postLogin(string username, string password) @safe
|
@noAuth @errorDisplay!getLogin void postLogin(string username, string password) @safe
|
||||||
{
|
{
|
||||||
enforce(authenticator.checkUser(username, password), "Benutzername oder Passwort ungültig");
|
auto authInfo = authenticator.checkUser(username, password);
|
||||||
immutable AuthInfo authInfo = {username};
|
enforce(!authInfo.isNull, "Benutzername oder Passwort ungültig");
|
||||||
auth = authInfo;
|
auth = authInfo.get;
|
||||||
redirect("/");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,14 @@ public:
|
||||||
container.register!(Authenticator, MongoDBAuthenticator!(Collection))(
|
container.register!(Authenticator, MongoDBAuthenticator!(Collection))(
|
||||||
RegistrationOption.doNotAddConcreteTypeRegistration);
|
RegistrationOption.doNotAddConcreteTypeRegistration);
|
||||||
|
|
||||||
auto userBson = Bson(["_id" : Bson(BsonObjectID.fromString("5988ef4ae6c19089a1a53b79")), "username" : Bson("foo"),
|
auto userBson = Bson(["_id" : Bson(BsonObjectID.fromString("5988ef4ae6c19089a1a53b79")),
|
||||||
"password" : Bson("$2a$10$9LBqOZV99ARiE4Nx.2b7GeYfqk2.0A32PWGu2cRGyW2hRJ0xeDfnO")]);
|
"username" : Bson("foo"), "passwordHash"
|
||||||
|
: Bson("$2a$10$9LBqOZV99ARiE4Nx.2b7GeYfqk2.0A32PWGu2cRGyW2hRJ0xeDfnO"), "role" : Bson(1)]);
|
||||||
|
|
||||||
collection.returnValue!"findOne"(Bson(null), userBson, userBson);
|
collection.returnValue!"findOne"(Bson(null), userBson, userBson);
|
||||||
|
|
||||||
auto authenticator = container.resolve!(Authenticator);
|
auto authenticator = container.resolve!(Authenticator);
|
||||||
authenticator.checkUser("", "").shouldBeFalse;
|
authenticator.checkUser("", "").isNull.shouldBeTrue;
|
||||||
authenticator.checkUser("foo", "bar").shouldBeTrue;
|
authenticator.checkUser("foo", "bar").isNull.shouldBeFalse;
|
||||||
authenticator.checkUser("foo", "baz").shouldBeFalse;
|
authenticator.checkUser("foo", "baz").isNull.shouldBeTrue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue