Permalink
Browse files

Merge pull request #18 from mmalecki/registration

Registration
  • Loading branch information...
2 parents 0a337f3 + 1f31a36 commit 8eaa2260320bf4f12cfeb7d7dd4c4e58ee834e94 @mmalecki mmalecki committed Aug 31, 2011
Showing with 123 additions and 1 deletion.
  1. +2 −1 config/environment.js
  2. +52 −0 lib/login.js
  3. +69 −0 test/test-login.js
View
@@ -10,7 +10,8 @@ exports.common = {
}
},
loginManager: {
- hash: 'sha512'
+ hash: 'sha512',
+ saltLength: 16
}
};
View
@@ -14,6 +14,9 @@ var Login = exports.Login = function (options) {
}
util.inherits(Login, Hook);
+Login.USER_EXISTS = 1;
+Login.INVALID_EMAIL = 2;
+
Login.prototype._listeners = function () {
var self = this;
// listen for user logins from anywhere that needs them
@@ -25,6 +28,18 @@ Login.prototype._listeners = function () {
self.emit('loginSuccess', doc);
});
});
+ self.on('*::userRegister', function (data) {
+ self.userRegister(data.email, data.password, function (err, res) {
+ if (err) {
+ return self.emit('registrationFail', err);
+ }
+ self.emit('registrationSuccess', res);
+ });
+ });
+}
+
+Login.prototype.emailValidate = function(email) {
+ return /\b[a-zA-Z0-9._%+-]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}\b/.test(email);
}
Login.prototype.userLogin = function (email, password, callback) {
@@ -45,3 +60,40 @@ Login.prototype.userLogin = function (email, password, callback) {
});
}
+Login.prototype.saltGenerate = function () {
+ var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
+ var salt = '';
+ for (var i = 0; i < settings.loginManager.saltLength; i++) {
+ salt += chars.charAt(Math.floor(Math.random() * chars.length));
+ }
+ return salt;
+}
+
+Login.prototype.userRegister = function (email, password, callback) {
+ var self = this;
+
+ email = email.toLowerCase();
+ if (!this.emailValidate(email)) {
+ return callback({reason: 'invalid e-mail', code: Login.INVALID_EMAIL});
+ }
+
+ var hash = crypto.createHash(settings.loginManager.hash);
+ var salt = self.saltGenerate();
+ hash.update(salt + password);
+
+ var user = {
+ salt: salt,
+ hash: hash.digest('hex')
+ };
+ db.put('user-' + encodeURIComponent(email), user, function (err, res) {
+ if (err) {
+ if (err.error == 'conflict') {
+ return callback({reason: 'user exists', code: Login.USER_EXISTS});
+ }
+ self.emit('error::register', err);
+ return callback(err);
+ }
+ return callback(null, res);
+ });
+}
+
View
@@ -6,6 +6,21 @@ settings.__reload('test');
var db = require('../lib/db').db;
var login = require('../lib/login');
+var invalidEmails = [
+ 'invalid.email',
+ '@invalid.email',
+ 'a@invalid',
+ 'c@.pl'
+]
+
+var validEmails = [
+ 'valid@email.com',
+ 'valid+test@email.com',
+ 'v@e.pl',
+ 'CAPS@MAIL.ORG',
+ 'test@multiple.sub.domains.org'
+]
+
module.exports = testCase({
setUp: function (callback) {
var hash = crypto.createHash(settings.loginManager.hash);
@@ -57,6 +72,60 @@ module.exports = testCase({
test.done();
});
},
+ testSaltGeneration: function (test) {
+ var salt = this.login.saltGenerate();
+ test.equal(salt.length, settings.loginManager.saltLength);
+ test.done();
+ },
+ testUserRegister: function (test) {
+ // TODO: test for invalid emails
+ test.expect(3);
+ var email = 'some-email@test.com';
+ var id = 'user-' + encodeURIComponent(email);
+ var password = 'ninja';
+ this.login.userRegister(email, password, function (err, res) {
+ test.ok(!err, "shouldn't return error with valid data");
+
+ var rev = res.rev;
+
+ db.get(id, function (err, doc) {
+ test.ok(!err, 'there should be no error when getting new user from DB');
+ test.equal(
+ doc.salt.length,
+ settings.loginManager.saltLength,
+ "salt's length should be equal to one in settings"
+ );
+ db.remove(id, rev, function () {});
+ test.done();
+ });
+ });
+ },
+ testRegisterExistingUser: function (test) {
+ var self = this;
+
+ test.expect(3);
+ this.login.userRegister(this.email, 'whatever', function (err, res) {
+ test.ok(err, 'should return error when trying to register existing user');
+ test.equal(err.code, login.Login.USER_EXISTS, 'should return proper error code');
+
+ db.get(self.id, function (err, doc) {
+ test.equal(doc._rev, self.rev, 'document should not get overriden');
+ test.done();
+ });
+ });
+ },
+ testEmailValidation: function (test) {
+ var self = this;
+
+ test.expect(validEmails.length + invalidEmails.length);
+ validEmails.forEach(function (email) {
+ test.ok(self.login.emailValidate(email));
+ });
+ invalidEmails.forEach(function (email) {
+ test.ok(!self.login.emailValidate(email));
+ });
+ test.done();
+ },
tearDown: function (callback) {
db.remove(this.id, this.rev, callback);
}

0 comments on commit 8eaa226

Please sign in to comment.