diff --git a/lib/user.js b/lib/user.js index 114ace9ab7..b130a7c58b 100644 --- a/lib/user.js +++ b/lib/user.js @@ -4,16 +4,25 @@ const gravatarUrl = require('gravatar-url'); const Joi = require('@hapi/joi'); module.exports = class User { - constructor({ name, email, permissions, imageUrl } = {}) { - Joi.assert( - email, - Joi.string() - .email() - .required(), - 'Email', - ); - this.email = email; + constructor({ + name, + email, + username, + systemId, + imageUrl, + permissions, + } = {}) { + if (!username && !email) { + throw new TypeError('Username or Email us reuqired'); + } + Joi.assert(email, Joi.string().email(), 'Email'); + Joi.assert(username, Joi.string(), 'Username'); + Joi.assert(name, Joi.string(), 'Name'); + this.name = name; + this.username = username; + this.email = email; + this.systemId = systemId; this.permissions = permissions; this.imageUrl = imageUrl || gravatarUrl(email, { size: '42', default: 'retro' }); diff --git a/lib/user.test.js b/lib/user.test.js index 213d0f57df..0e45d30eb7 100644 --- a/lib/user.test.js +++ b/lib/user.test.js @@ -13,7 +13,24 @@ test('should create user', t => { ); }); -test('should require email', t => { +test('should create user, all fields', t => { + const user = new User({ + name: 'Admin', + username: 'admin', + email: 'some@email.com', + permissions: ['admin', 'client'], + }); + t.is(user.name, 'Admin'); + t.is(user.username, 'admin'); + t.is(user.email, 'some@email.com'); + t.deepEqual(user.permissions, ['admin', 'client']); + t.is( + user.imageUrl, + 'https://gravatar.com/avatar/d8ffeba65ee5baf57e4901690edc8e1b?size=42&default=retro', + ); +}); + +test('should require email or username', t => { const error = t.throws( () => { const user = new User(); // eslint-disable-line @@ -21,7 +38,7 @@ test('should require email', t => { { instanceOf: Error }, ); - t.is(error.message, 'Email "value" is required'); + t.is(error.message, 'Username or Email us reuqired'); }); test('Should create user with only email defined', t => { @@ -29,3 +46,14 @@ test('Should create user with only email defined', t => { t.is(user.email, 'some@email.com'); }); + +test('Should require valid email', t => { + const error = t.throws( + () => { + new User({ email: 'some@' }); // eslint-disable-line + }, + { instanceOf: Error }, + ); + + t.is(error.message, 'Email "value" must be a valid email'); +}); diff --git a/migrations/20200416201319-create-users.js b/migrations/20200416201319-create-users.js new file mode 100644 index 0000000000..9d6cbbfaa2 --- /dev/null +++ b/migrations/20200416201319-create-users.js @@ -0,0 +1,31 @@ +/* eslint camelcase: "off" */ + +'use strict'; + +exports.up = function(db, cb) { + return db.createTable( + 'users', + { + id: { + type: 'serial', + primaryKey: true, + notNull: true, + autoIncrement: true, + }, + name: { type: 'string', length: 255 }, + username: { type: 'string', length: 255, unique: true }, + system_id: { type: 'string', length: 255 }, + email: { type: 'string', length: 255, unique: true }, + image_url: { type: 'string', length: 255 }, + password_hash: { type: 'string', length: 255 }, + login_attempts: { type: 'int', defaultValue: 0 }, + created_at: { type: 'timestamp', defaultValue: 'now()' }, + seen_at: { type: 'timestamp' }, + }, + cb, + ); +}; + +exports.down = function(db, cb) { + return db.dropTable('users', cb); +};