Skip to content

Commit

Permalink
Upgrading the user management code.
Browse files Browse the repository at this point in the history
  • Loading branch information
rikkimax committed Apr 18, 2014
1 parent 7452c50 commit 9edf726
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 79 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 72,7 @@
"stringImportPaths": ["views/test"],
"dependencies": {
"cmsed:base": "~master",
"cmsed:user": "~master"
}
}
],
Expand Down
6 changes: 5 additions & 1 deletion source/user/cmsed/user/defs.d
Original file line number Diff line number Diff line change
@@ -1,4 1,6 @@
module cmsed.user.defs;
import cmsed.user.operations : ModelAuthProvider;
import std.traits : moduleName;

/**
* A bunch of user group titles.
Expand All @@ -10,4 12,6 @@ enum UserGroup : string {
Moderator = Mod,
User = "user",
Guest = "guest"
}
}

enum BUILT_IN_DB_AUTH = moduleName!ModelAuthProvider;
47 changes: 29 additions & 18 deletions source/user/cmsed/user/operations.d
Original file line number Diff line number Diff line change
@@ -1,7 1,6 @@
module cmsed.user.operations;
import cmsed.user.models.user;
import cmsed.user.models.userauth;
import cmsed.user.models.usergroup;
import cmsed.user;
import cmsed.user.models;
import cmsed.user.registration.auth;
import cmsed.base.defs;

Expand Down Expand Up @@ -29,7 28,7 @@ UserModel getLoggedInUser() {
* password = The password given. Secret info to identifiy is the user.
*/
bool login(string userName, string password) {
UserModel um = getUserFromAuth(userName, password);
UserModel um = checker.validCredentials(userName, password);
if (um is null) return false;

session["userId"] = um.key.key;
Expand All @@ -40,7 39,7 @@ bool login(string userName, string password) {
* Check if the username exists in any of the providers.
*/
bool doesUserExist(string name) {
return getCheckUserExistsFromAuth(name);
return checker.hasIdentifier(name);
}

/**
Expand All @@ -65,15 64,23 @@ void logout() {
}

private {
shared static this() {
UserModel dbAuthProvider(string user, string pass) {
class ModelAuthProvider : AuthProvider {
bool hasIdentifier(string identifier) {
size_t uam = UserAuthModel.query()
.username_eq(identifier)
.count();

return (uam > 0);
}

UserModel validCredentials(string identifier, string validator) {
UserAuthModel[] uams = UserAuthModel.query()
.username_eq(user).find();
.username_eq(identifier).find();

foreach(uam; uams) {
if (uam.password == pass) {
if (uam.password == validator) {
if (uam.password.needsToBeUpgraded) {
uam.password = pass;
uam.password = validator;
uam.save();
}
return uam.user.getUser();
Expand All @@ -83,16 90,20 @@ private {
return null;
}

registerAuthProvider(&dbAuthProvider);
bool changeValidator(string identifier, string validator) {
return false;
}

bool dbAuthCheckProvider(string user) {
size_t uam = UserAuthModel.query()
.username_eq(user)
.count();

return (uam > 0);
@property string identifier() {
return BUILT_IN_DB_AUTH;
}

registerUserExistsProvider(&dbAuthCheckProvider);
void logLogin(string identifier) {
// this may be a good idea to do something with.
}
}

shared static this() {
registerAuthProvider!ModelAuthProvider;
}
}
4 changes: 4 additions & 0 deletions source/user/cmsed/user/package.d
Original file line number Diff line number Diff line change
@@ -0,0 1,4 @@
module cmsed.user;
public import cmsed.user.defs;
public import cmsed.user.filters;
public import cmsed.user.operations;
210 changes: 150 additions & 60 deletions source/user/cmsed/user/registration/auth.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 2,167 @@ module cmsed.user.registration.auth;
import cmsed.user.models.user;

/**
* Registers functions that provide authentication.
* Provides an authentication mechanism.
*/

private {
alias UserModel delegate(string username, string password) userDel;
alias bool delegate(string username) userExistsDel;
userDel[] funcs;
userExistsDel[] funcs2;
interface AuthProvider {

/**
* Does a check wheather or not an identifier exists in any provider.
*
* Params:
* identifier = The username or email that is to be checked against
*
* Returns:
* If the identifier exists or not.
*/
bool hasIdentifier(string identifier);

/**
* Gets a user if can be logged in.
*
* Params:
* identifier = The username or email to log the user in by
* validator = The password to log the user in by
*
* Returns:
* A UserModel given the login information. Or null if not possible.
*
* See_Also:
* UserModel
*/
UserModel validCredentials(string identifier, string validator);

/**
* Changes the validator value for an identifier
*
* Params:
* identifier = The username or email to log the user in by
* validator = The password to log the user in by
*
* Returns:
* If the change was successful.
*/
bool changeValidator(string identifier, string validator);

/**
* Identifies an auth provider
*/
@property string identifier();

/*
* Logging
*/

/**
* Upon login call this.
*
* Params:
* identifier = The username or email to log the user in by
*/
void logLogin(string identifier);
}

/**
* Register an auth provider.
* Note:
* Does not login a user.
*/
void registerAuthProvider(userDel del) {
synchronized {
funcs ~= del;
}
}
static const AuthChecker checker = new AuthChecker();

/**
* Registers an auth check against a user/pass combination.
* Registers an auth provider.
*/
void registerUserExistsProvider(userExistsDel del) {
synchronized {
funcs2 ~= del;
}
void registerAuthProvider(T : AuthProvider)(T provider = new T()) {
providers ~= provider;
}

/**
* Gets a user if can be logged in.
*
* Params:
* user = The username or email to log the user in by
* pass = The password to log the user in by
*
* Returns:
* Gets a UserModel given the login information. Or null if not possible.
*
* See_Also:
* UserModel
*/
UserModel getUserFromAuth(string user, string pass) {
synchronized {
foreach(del; funcs) {
UserModel um = del(user, pass);
if (um !is null)
return um;
private {
AuthProvider[] providers;

const class AuthChecker : AuthProvider {
bool hasIdentifier(string identifier) {
foreach(provider; providers) {
if (provider.hasIdentifier(identifier)) return true;
}
return false;
}

return null;
}
}

/**
* Does a check wheather or not a username exists in any provider.
*
* Params:
* user = The username or email that is to be checked against
*
* Returns:
* If the username/email exists or not.
*/
bool getCheckUserExistsFromAuth(string user) {
synchronized {
foreach(del; funcs2) {
if(del(user))
return true;
UserModel validCredentials(string identifier, string validator) {
foreach(provider; providers) {
UserModel returned = provider.validCredentials(identifier, validator);
if (returned !is null)
return returned;
}
return null;
}

bool changeValidator(string identifier, string validator) {
foreach(provider; providers) {
if (provider.hasIdentifier(identifier))
if (provider.changeValidator(identifier, validator))
return true;
}
return false;
}

return false;
/*
* This shouldn't actually be used
*/
@property string identifier() {
assert(0);
}

/*
* Logging
*/

/**
* Upon login call this.
*/
void logLogin(string identifier) {
foreach(provider; providers) {
if (provider.hasIdentifier(identifier)) {
provider.logLogin(identifier);
return;
}
}
}

/*
* Util related not inhertited
*/

/**
* Gets an auth provider base upoon its name
*
* Params:
* identifier = The name of the provider
*
* Return:
* The auth provider or null
*/
AuthProvider getAuthProvider(string identifier) {
foreach(provider; providers) {
if (provider.identifier == identifier)
return provider;
}

return null;
}

/**
* Gets all providers for a specific identifier
*
* Params:
* identifier = The name of the provider
*
* Return:
* A list of provider identifiers for an identifier
*/
string[] providersForIdentifier(string identifier) {
string[] ret;

foreach(provider; providers) {
if (provider.hasIdentifier(identifier))
ret ~= provider.identifier;
}

return ret;
}
}
}

0 comments on commit 9edf726

Please sign in to comment.