diff --git a/config/env/default.js b/config/env/default.js
index 4ae53fafaa..8c7f2429ee 100644
--- a/config/env/default.js
+++ b/config/env/default.js
@@ -42,6 +42,9 @@ module.exports = {
},
logo: 'modules/core/client/img/brand/logo.png',
favicon: 'modules/core/client/img/brand/favicon.ico',
+ illegalUsernames: ['meanjs', 'administrator', 'password', 'admin', 'user',
+ 'unknown', 'anonymous', 'null', 'undefined', 'api'
+ ],
uploads: {
profileUpload: {
dest: './modules/users/client/img/profile/uploads/', // Profile upload destination path
diff --git a/config/env/development.js b/config/env/development.js
index 93e2f7d743..da024eb886 100644
--- a/config/env/development.js
+++ b/config/env/development.js
@@ -75,7 +75,7 @@ module.exports = {
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
- username: process.env.MONGO_SEED_USER_USERNAME || 'user',
+ username: process.env.MONGO_SEED_USER_USERNAME || 'seeduser',
provider: 'local',
email: process.env.MONGO_SEED_USER_EMAIL || 'user@localhost.com',
firstName: 'User',
@@ -84,7 +84,7 @@ module.exports = {
roles: ['user']
},
seedAdmin: {
- username: process.env.MONGO_SEED_ADMIN_USERNAME || 'admin',
+ username: process.env.MONGO_SEED_ADMIN_USERNAME || 'seedadmin',
provider: 'local',
email: process.env.MONGO_SEED_ADMIN_EMAIL || 'admin@localhost.com',
firstName: 'Admin',
diff --git a/config/env/production.js b/config/env/production.js
index 333234c77f..f37f36b162 100644
--- a/config/env/production.js
+++ b/config/env/production.js
@@ -94,7 +94,7 @@ module.exports = {
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
- username: process.env.MONGO_SEED_USER_USERNAME || 'user',
+ username: process.env.MONGO_SEED_USER_USERNAME || 'seeduser',
provider: 'local',
email: process.env.MONGO_SEED_USER_EMAIL || 'user@localhost.com',
firstName: 'User',
@@ -103,7 +103,7 @@ module.exports = {
roles: ['user']
},
seedAdmin: {
- username: process.env.MONGO_SEED_ADMIN_USERNAME || 'admin',
+ username: process.env.MONGO_SEED_ADMIN_USERNAME || 'seedadmin',
provider: 'local',
email: process.env.MONGO_SEED_ADMIN_EMAIL || 'admin@localhost.com',
firstName: 'Admin',
diff --git a/config/env/test.js b/config/env/test.js
index c010177736..41c14ebf32 100644
--- a/config/env/test.js
+++ b/config/env/test.js
@@ -75,7 +75,7 @@ module.exports = {
options: {
logResults: process.env.MONGO_SEED_LOG_RESULTS !== 'false',
seedUser: {
- username: process.env.MONGO_SEED_USER_USERNAME || 'user',
+ username: process.env.MONGO_SEED_USER_USERNAME || 'seeduser',
provider: 'local',
email: process.env.MONGO_SEED_USER_EMAIL || 'user@localhost.com',
firstName: 'User',
@@ -84,7 +84,7 @@ module.exports = {
roles: ['user']
},
seedAdmin: {
- username: process.env.MONGO_SEED_ADMIN_USERNAME || 'admin',
+ username: process.env.MONGO_SEED_ADMIN_USERNAME || 'seedadmin',
provider: 'local',
email: process.env.MONGO_SEED_ADMIN_EMAIL || 'admin@localhost.com',
firstName: 'Admin',
diff --git a/modules/core/tests/server/core.server.config.tests.js b/modules/core/tests/server/core.server.config.tests.js
index 4e8a3882dc..b7212e0317 100644
--- a/modules/core/tests/server/core.server.config.tests.js
+++ b/modules/core/tests/server/core.server.config.tests.js
@@ -82,7 +82,7 @@ describe('Configuration Tests:', function () {
});
it('should not be an admin user to begin with', function(done) {
- User.find({ username: 'admin' }, function(err, users) {
+ User.find({ username: 'seedadmin' }, function(err, users) {
should.not.exist(err);
users.should.be.instanceof(Array).and.have.lengthOf(0);
return done();
@@ -90,7 +90,7 @@ describe('Configuration Tests:', function () {
});
it('should not be a "regular" user to begin with', function(done) {
- User.find({ username: 'user' }, function(err, users) {
+ User.find({ username: 'seeduser' }, function(err, users) {
should.not.exist(err);
users.should.be.instanceof(Array).and.have.lengthOf(0);
return done();
diff --git a/modules/users/client/controllers/authentication.client.controller.js b/modules/users/client/controllers/authentication.client.controller.js
index 34ddeffd3f..23379ce384 100644
--- a/modules/users/client/controllers/authentication.client.controller.js
+++ b/modules/users/client/controllers/authentication.client.controller.js
@@ -15,6 +15,7 @@
vm.signup = signup;
vm.signin = signin;
vm.callOauthProvider = callOauthProvider;
+ vm.usernameRegex = /^(?=[\w.-]+$)(?!.*[._-]{2})(?!\.)(?!.*\.$).{3,34}$/;
// Get an eventual error defined in the URL query string:
if ($location.search().err) {
diff --git a/modules/users/client/views/authentication/signup.client.view.html b/modules/users/client/views/authentication/signup.client.view.html
index 2c593322d9..5d57b519a2 100644
--- a/modules/users/client/views/authentication/signup.client.view.html
+++ b/modules/users/client/views/authentication/signup.client.view.html
@@ -27,9 +27,10 @@
Or sign up using your email
diff --git a/modules/users/server/models/user.server.model.js b/modules/users/server/models/user.server.model.js
index 16c3546e78..1dc4fc247f 100644
--- a/modules/users/server/models/user.server.model.js
+++ b/modules/users/server/models/user.server.model.js
@@ -29,6 +29,24 @@ var validateLocalStrategyEmail = function (email) {
return ((this.provider !== 'local' && !this.updated) || validator.isEmail(email, { require_tld: false }));
};
+/**
+ * A Validation function for username
+ * - at least 3 characters
+ * - only a-z0-9_-.
+ * - contain at least one alphanumeric character
+ * - not in list of illegal usernames
+ * - no consecutive dots: "." ok, ".." nope
+ * - not begin or end with "."
+ */
+
+var validateUsername = function(username) {
+ var usernameRegex = /^(?=[\w.-]+$)(?!.*[._-]{2})(?!\.)(?!.*\.$).{3,34}$/;
+ return (
+ this.provider !== 'local' ||
+ (username && usernameRegex.test(username) && config.illegalUsernames.indexOf(username) < 0)
+ );
+};
+
/**
* User Schema
*/
@@ -64,6 +82,7 @@ var UserSchema = new Schema({
type: String,
unique: 'Username already exists',
required: 'Please fill in a username',
+ validate: [validateUsername, 'Please enter a valid username: 3+ characters long, non restricted word, characters "_-.", no consecutive dots, does not begin or end with dots, letters a-z and numbers 0-9.'],
lowercase: true,
trim: true
},
diff --git a/modules/users/tests/e2e/users.e2e.tests.js b/modules/users/tests/e2e/users.e2e.tests.js
index 6c232bfa4f..02d27ede02 100644
--- a/modules/users/tests/e2e/users.e2e.tests.js
+++ b/modules/users/tests/e2e/users.e2e.tests.js
@@ -113,6 +113,116 @@ describe('Users E2E Tests:', function () {
expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Email address is invalid.');
});
+ it('Should report invalid username - ".login"', function () {
+ browser.get('http://localhost:3001/authentication/signup');
+ // Enter First Name
+ element(by.model('vm.credentials.firstName')).sendKeys(user1.firstName);
+ // Enter Last Name
+ element(by.model('vm.credentials.lastName')).sendKeys(user1.lastName);
+ // Enter Email
+ element(by.model('vm.credentials.email')).sendKeys(user1.email);
+ // Enter Username
+ element(by.model('vm.credentials.username')).sendKeys('.login');
+ // Enter Password
+ element(by.model('vm.credentials.password')).sendKeys(user1.password);
+ // Click Submit button
+ element(by.css('button[type=submit]')).click();
+ // Email address error
+ expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Please enter a valid username: 3+ characters long, non restricted word, characters "_-.", no consecutive dots, does not begin or end with dots, letters a-z and numbers 0-9.');
+ });
+
+ it('Should report invalid username - "login."', function () {
+ browser.get('http://localhost:3001/authentication/signup');
+ // Enter First Name
+ element(by.model('vm.credentials.firstName')).sendKeys(user1.firstName);
+ // Enter Last Name
+ element(by.model('vm.credentials.lastName')).sendKeys(user1.lastName);
+ // Enter Email
+ element(by.model('vm.credentials.email')).sendKeys(user1.email);
+ // Enter Username
+ element(by.model('vm.credentials.username')).sendKeys('login.');
+ // Enter Password
+ element(by.model('vm.credentials.password')).sendKeys(user1.password);
+ // Click Submit button
+ element(by.css('button[type=submit]')).click();
+ // Email address error
+ expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Please enter a valid username: 3+ characters long, non restricted word, characters "_-.", no consecutive dots, does not begin or end with dots, letters a-z and numbers 0-9.');
+ });
+
+ it('Should report invalid username - "log..in"', function () {
+ browser.get('http://localhost:3001/authentication/signup');
+ // Enter First Name
+ element(by.model('vm.credentials.firstName')).sendKeys(user1.firstName);
+ // Enter Last Name
+ element(by.model('vm.credentials.lastName')).sendKeys(user1.lastName);
+ // Enter Email
+ element(by.model('vm.credentials.email')).sendKeys(user1.email);
+ // Enter Username
+ element(by.model('vm.credentials.username')).sendKeys('log..in');
+ // Enter Password
+ element(by.model('vm.credentials.password')).sendKeys(user1.password);
+ // Click Submit button
+ element(by.css('button[type=submit]')).click();
+ // Email address error
+ expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Please enter a valid username: 3+ characters long, non restricted word, characters "_-.", no consecutive dots, does not begin or end with dots, letters a-z and numbers 0-9.');
+ });
+
+ it('Should report invalid username - "lo"', function () {
+ browser.get('http://localhost:3001/authentication/signup');
+ // Enter First Name
+ element(by.model('vm.credentials.firstName')).sendKeys(user1.firstName);
+ // Enter Last Name
+ element(by.model('vm.credentials.lastName')).sendKeys(user1.lastName);
+ // Enter Email
+ element(by.model('vm.credentials.email')).sendKeys(user1.email);
+ // Enter Username
+ element(by.model('vm.credentials.username')).sendKeys('lo');
+ // Enter Password
+ element(by.model('vm.credentials.password')).sendKeys(user1.password);
+ // Click Submit button
+ element(by.css('button[type=submit]')).click();
+ // Email address error
+ expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Please enter a valid username: 3+ characters long, non restricted word, characters "_-.", no consecutive dots, does not begin or end with dots, letters a-z and numbers 0-9.');
+ });
+
+ it('Should report invalid username - "log$in"', function () {
+ browser.get('http://localhost:3001/authentication/signup');
+ // Enter First Name
+ element(by.model('vm.credentials.firstName')).sendKeys(user1.firstName);
+ // Enter Last Name
+ element(by.model('vm.credentials.lastName')).sendKeys(user1.lastName);
+ // Enter Email
+ element(by.model('vm.credentials.email')).sendKeys(user1.email);
+ // Enter Username
+ element(by.model('vm.credentials.username')).sendKeys('log$in');
+ // Enter Password
+ element(by.model('vm.credentials.password')).sendKeys(user1.password);
+ // Click Submit button
+ element(by.css('button[type=submit]')).click();
+ // Email address error
+ expect(element.all(by.css('.error-text')).get(0).getText()).toBe('Please enter a valid username: 3+ characters long, non restricted word, characters "_-.", no consecutive dots, does not begin or end with dots, letters a-z and numbers 0-9.');
+ });
+
+ it('Should signup username with . - "log.in"', function () {
+ browser.get('http://localhost:3001/authentication/signup');
+ // Enter First Name
+ element(by.model('vm.credentials.firstName')).sendKeys(user2.firstName);
+ // Enter Last Name
+ element(by.model('vm.credentials.lastName')).sendKeys(user2.lastName);
+ // Enter Email
+ element(by.model('vm.credentials.email')).sendKeys('someemail@meanjs.com');
+ // Enter Username
+ element(by.model('vm.credentials.username')).sendKeys('log.in');
+ // Enter Password
+ element(by.model('vm.credentials.password')).sendKeys(user2.password);
+ // Click Submit button
+ element(by.css('button[type=submit]')).click();
+ // Signup successful with username having .
+ expect(browser.getCurrentUrl()).toEqual('http://localhost:3001/');
+
+ signout();
+ });
+
it('Should report missing username', function () {
browser.get('http://localhost:3001/authentication/signup');
// Enter First Name
diff --git a/modules/users/tests/server/user.server.model.tests.js b/modules/users/tests/server/user.server.model.tests.js
index 820389dba0..bac9e8b20a 100644
--- a/modules/users/tests/server/user.server.model.tests.js
+++ b/modules/users/tests/server/user.server.model.tests.js
@@ -5,7 +5,9 @@
*/
var should = require('should'),
mongoose = require('mongoose'),
- User = mongoose.model('User');
+ User = mongoose.model('User'),
+ path = require('path'),
+ config = require(path.resolve('./config/config'));
/**
* Globals
@@ -643,6 +645,89 @@ describe('User Model Unit Tests:', function () {
});
+ describe('Username Validation', function() {
+ it('should show error to save username beginning with .', function(done) {
+ var _user = new User(user1);
+
+ _user.username = '.login';
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should be able to show an error when try to save with not allowed username', function (done) {
+ var _user = new User(user1);
+
+ _user.username = config.illegalUsernames[Math.floor(Math.random() * config.illegalUsernames.length)];
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should show error to save username end with .', function(done) {
+ var _user = new User(user1);
+
+ _user.username = 'login.';
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should show error to save username with ..', function(done) {
+ var _user = new User(user1);
+
+ _user.username = 'log..in';
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should show error to save username shorter than 3 character', function(done) {
+ var _user = new User(user1);
+
+ _user.username = 'lo';
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should show error saving a username without at least one alphanumeric character', function(done) {
+ var _user = new User(user1);
+
+ _user.username = '-_-';
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should show error saving a username longer than 34 characters', function(done) {
+ var _user = new User(user1);
+
+ _user.username = 'l'.repeat(35);
+ _user.save(function(err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should save username with dot', function(done) {
+ var _user = new User(user1);
+
+ _user.username = 'log.in';
+ _user.save(function(err) {
+ should.not.exist(err);
+ done();
+ });
+ });
+
+ });
+
after(function (done) {
User.remove().exec(done);
});