From ad4a8a1cca1049f600ebcdce9260c1021cd821a5 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 18 Feb 2017 09:29:59 +0100 Subject: Add email to users --- client/src/app/+admin/users/shared/user.service.ts | 3 +- .../+admin/users/user-add/user-add.component.html | 11 ++++++ .../+admin/users/user-add/user-add.component.ts | 14 ++++++-- .../+admin/users/user-list/user-list.component.ts | 3 ++ client/src/app/app.component.html | 2 +- .../forms/form-validators/email.validator.ts | 13 ++++++++ .../shared/forms/form-validators/host.validator.ts | 2 +- .../src/app/shared/forms/form-validators/index.ts | 1 + .../src/app/shared/forms/form-validators/user.ts | 9 +++++ server/controllers/api/users.js | 1 + server/initializers/installer.js | 2 ++ server/middlewares/validators/users.js | 3 +- server/models/author.js | 4 ++- server/models/pod.js | 5 ++- server/models/user.js | 25 +++++++++++++- server/tests/api/check-params/pods.js | 24 ++++++++++++- server/tests/api/check-params/users.js | 39 ++++++++++++++++++++++ server/tests/api/users.js | 8 +++++ server/tests/utils/users.js | 7 +++- 19 files changed, 164 insertions(+), 12 deletions(-) create mode 100644 client/src/app/shared/forms/form-validators/email.validator.ts diff --git a/client/src/app/+admin/users/shared/user.service.ts b/client/src/app/+admin/users/shared/user.service.ts index f6d360e09..a92f9c231 100644 --- a/client/src/app/+admin/users/shared/user.service.ts +++ b/client/src/app/+admin/users/shared/user.service.ts @@ -14,9 +14,10 @@ export class UserService { private restExtractor: RestExtractor ) {} - addUser(username: string, password: string) { + addUser(username: string, password: string, email: string) { const body = { username, + email, password }; diff --git a/client/src/app/+admin/users/user-add/user-add.component.html b/client/src/app/+admin/users/user-add/user-add.component.html index 9b76c7c1b..105760f48 100644 --- a/client/src/app/+admin/users/user-add/user-add.component.html +++ b/client/src/app/+admin/users/user-add/user-add.component.html @@ -14,6 +14,17 @@ +
+ + +
+ {{ formErrors.email }} +
+
+
{ this.notificationsService.success('Success', `User ${username} created.`); this.router.navigate([ '/admin/users/list' ]); diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts index c27b96e28..69ae4353d 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/users/user-list/user-list.component.ts @@ -40,6 +40,9 @@ export class UserListComponent { username: { title: 'Username' }, + email: { + title: 'Email' + }, role: { title: 'Role', sort: false diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html index 9f2661e12..0c8e18a2f 100644 --- a/client/src/app/app.component.html +++ b/client/src/app/app.component.html @@ -26,6 +26,6 @@
diff --git a/client/src/app/shared/forms/form-validators/email.validator.ts b/client/src/app/shared/forms/form-validators/email.validator.ts new file mode 100644 index 000000000..6a2c3bdca --- /dev/null +++ b/client/src/app/shared/forms/form-validators/email.validator.ts @@ -0,0 +1,13 @@ +import { FormControl } from '@angular/forms'; + +export function validateEmail(c: FormControl) { + // Thanks to http://emailregex.com/ + /* tslint:disable */ + const EMAIL_REGEXP = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + + return EMAIL_REGEXP.test(c.value) ? null : { + email: { + valid: false + } + }; +} diff --git a/client/src/app/shared/forms/form-validators/host.validator.ts b/client/src/app/shared/forms/form-validators/host.validator.ts index ea3e43cb1..ec417e079 100644 --- a/client/src/app/shared/forms/form-validators/host.validator.ts +++ b/client/src/app/shared/forms/form-validators/host.validator.ts @@ -2,7 +2,7 @@ import { FormControl } from '@angular/forms'; export function validateHost(c: FormControl) { // Thanks to http://stackoverflow.com/a/106223 - let HOST_REGEXP = new RegExp( + const HOST_REGEXP = new RegExp( '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' ); diff --git a/client/src/app/shared/forms/form-validators/index.ts b/client/src/app/shared/forms/form-validators/index.ts index ab7c2df31..669411a54 100644 --- a/client/src/app/shared/forms/form-validators/index.ts +++ b/client/src/app/shared/forms/form-validators/index.ts @@ -1,3 +1,4 @@ +export * from './email.validator'; export * from './host.validator'; export * from './user'; export * from './video-abuse'; diff --git a/client/src/app/shared/forms/form-validators/user.ts b/client/src/app/shared/forms/form-validators/user.ts index 5b11ff265..0ad0e2a4b 100644 --- a/client/src/app/shared/forms/form-validators/user.ts +++ b/client/src/app/shared/forms/form-validators/user.ts @@ -1,5 +1,7 @@ import { Validators } from '@angular/forms'; +import { validateEmail } from './email.validator'; + export const USER_USERNAME = { VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(20) ], MESSAGES: { @@ -8,6 +10,13 @@ export const USER_USERNAME = { 'maxlength': 'Username cannot be more than 20 characters long.' } }; +export const USER_EMAIL = { + VALIDATORS: [ Validators.required, validateEmail ], + MESSAGES: { + 'required': 'Email is required.', + 'email': 'Email must be valid.', + } +}; export const USER_PASSWORD = { VALIDATORS: [ Validators.required, Validators.minLength(6) ], MESSAGES: { diff --git a/server/controllers/api/users.js b/server/controllers/api/users.js index 6cd0e84f7..324c99b4c 100644 --- a/server/controllers/api/users.js +++ b/server/controllers/api/users.js @@ -61,6 +61,7 @@ function createUser (req, res, next) { const user = db.User.build({ username: req.body.username, password: req.body.password, + email: req.body.email, role: constants.USER_ROLES.USER }) diff --git a/server/initializers/installer.js b/server/initializers/installer.js index fb63b81ac..837a987dd 100644 --- a/server/initializers/installer.js +++ b/server/initializers/installer.js @@ -96,6 +96,7 @@ function createOAuthAdminIfNotExist (callback) { const username = 'root' const role = constants.USER_ROLES.ADMIN + const email = constants.CONFIG.ADMIN.EMAIL const createOptions = {} let password = '' @@ -115,6 +116,7 @@ function createOAuthAdminIfNotExist (callback) { const userData = { username, + email, password, role } diff --git a/server/middlewares/validators/users.js b/server/middlewares/validators/users.js index 0629550bc..3089370ff 100644 --- a/server/middlewares/validators/users.js +++ b/server/middlewares/validators/users.js @@ -13,11 +13,12 @@ const validatorsUsers = { function usersAdd (req, res, next) { req.checkBody('username', 'Should have a valid username').isUserUsernameValid() req.checkBody('password', 'Should have a valid password').isUserPasswordValid() + req.checkBody('email', 'Should have a valid email').isEmail() logger.debug('Checking usersAdd parameters', { parameters: req.body }) checkErrors(req, res, function () { - db.User.loadByUsername(req.body.username, function (err, user) { + db.User.loadByUsernameOrEmail(req.body.username, req.body.email, function (err, user) { if (err) { logger.error('Error in usersAdd request validator.', { error: err }) return res.sendStatus(500) diff --git a/server/models/author.js b/server/models/author.js index f036193c8..34b013097 100644 --- a/server/models/author.js +++ b/server/models/author.js @@ -84,7 +84,9 @@ function findOrCreateAuthor (name, podId, userId, transaction, callback) { if (transaction) query.transaction = transaction this.findOrCreate(query).asCallback(function (err, result) { + if (err) return callback(err) + // [ instance, wasCreated ] - return callback(err, result[0]) + return callback(null, result[0]) }) } diff --git a/server/models/pod.js b/server/models/pod.js index 575ebbc61..79afb737a 100644 --- a/server/models/pod.js +++ b/server/models/pod.js @@ -35,7 +35,10 @@ module.exports = function (sequelize, DataTypes) { }, email: { type: DataTypes.STRING(400), - allowNull: false + allowNull: false, + validate: { + isEmail: true + } } }, { diff --git a/server/models/user.js b/server/models/user.js index 6cb9eec3f..35a98dd6b 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -32,6 +32,13 @@ module.exports = function (sequelize, DataTypes) { } } }, + email: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isEmail: true + } + }, role: { type: DataTypes.ENUM(values(constants.USER_ROLES)), allowNull: false @@ -42,6 +49,10 @@ module.exports = function (sequelize, DataTypes) { { fields: [ 'username' ], unique: true + }, + { + fields: [ 'email' ], + unique: true } ], classMethods: { @@ -52,7 +63,8 @@ module.exports = function (sequelize, DataTypes) { list, listForApi, loadById, - loadByUsername + loadByUsername, + loadByUsernameOrEmail }, instanceMethods: { isPasswordMatch, @@ -88,6 +100,7 @@ function toFormatedJSON () { return { id: this.id, username: this.username, + email: this.email, role: this.role, createdAt: this.createdAt } @@ -151,3 +164,13 @@ function loadByUsername (username, callback) { return this.findOne(query).asCallback(callback) } + +function loadByUsernameOrEmail (username, email, callback) { + const query = { + where: { + $or: [ { username }, { email } ] + } + } + + return this.findOne(query).asCallback(callback) +} diff --git a/server/tests/api/check-params/pods.js b/server/tests/api/check-params/pods.js index 8d52b69b1..22cbdb30f 100644 --- a/server/tests/api/check-params/pods.js +++ b/server/tests/api/check-params/pods.js @@ -39,7 +39,7 @@ describe('Test pods API validators', function () { ], done) }) - describe('When making friends', function () { + describe('When managing friends', function () { let userAccessToken = null before(function (done) { @@ -156,13 +156,32 @@ describe('Test pods API validators', function () { it('Should fail without public key', function (done) { const data = { + email: 'testexample.com', host: 'coucou.com' } requestsUtils.makePostBodyRequest(server.url, path, null, data, done) }) + it('Should fail without an email', function (done) { + const data = { + host: 'coucou.com', + publicKey: 'mysuperpublickey' + } + requestsUtils.makePostBodyRequest(server.url, path, null, data, done) + }) + + it('Should fail without an invalid email', function (done) { + const data = { + host: 'coucou.com', + email: 'testexample.com', + publicKey: 'mysuperpublickey' + } + requestsUtils.makePostBodyRequest(server.url, path, null, data, done) + }) + it('Should fail without an host', function (done) { const data = { + email: 'testexample.com', publicKey: 'mysuperpublickey' } requestsUtils.makePostBodyRequest(server.url, path, null, data, done) @@ -171,6 +190,7 @@ describe('Test pods API validators', function () { it('Should fail with an incorrect host', function (done) { const data = { host: 'http://coucou.com', + email: 'testexample.com', publicKey: 'mysuperpublickey' } requestsUtils.makePostBodyRequest(server.url, path, null, data, function () { @@ -185,6 +205,7 @@ describe('Test pods API validators', function () { it('Should succeed with the correct parameters', function (done) { const data = { host: 'coucou.com', + email: 'test@example.com', publicKey: 'mysuperpublickey' } requestsUtils.makePostBodyRequest(server.url, path, null, data, done, 200) @@ -193,6 +214,7 @@ describe('Test pods API validators', function () { it('Should fail with a host that already exists', function (done) { const data = { host: 'coucou.com', + email: 'test@example.com', publicKey: 'mysuperpublickey' } requestsUtils.makePostBodyRequest(server.url, path, null, data, done, 409) diff --git a/server/tests/api/check-params/users.js b/server/tests/api/check-params/users.js index c1fcf34a4..debf63cf6 100644 --- a/server/tests/api/check-params/users.js +++ b/server/tests/api/check-params/users.js @@ -92,6 +92,7 @@ describe('Test users API validators', function () { it('Should fail with a too small username', function (done) { const data = { username: 'ji', + email: 'test@example.com', password: 'mysuperpassword' } @@ -101,6 +102,7 @@ describe('Test users API validators', function () { it('Should fail with a too long username', function (done) { const data = { username: 'mysuperusernamewhichisverylong', + email: 'test@example.com', password: 'mysuperpassword' } @@ -110,6 +112,26 @@ describe('Test users API validators', function () { it('Should fail with an incorrect username', function (done) { const data = { username: 'my username', + email: 'test@example.com', + password: 'mysuperpassword' + } + + requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) + }) + + it('Should fail with a missing email', function (done) { + const data = { + username: 'ji', + password: 'mysuperpassword' + } + + requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) + }) + + it('Should fail with an invalid email', function (done) { + const data = { + username: 'mysuperusernamewhichisverylong', + email: 'testexample.com', password: 'mysuperpassword' } @@ -119,6 +141,7 @@ describe('Test users API validators', function () { it('Should fail with a too small password', function (done) { const data = { username: 'myusername', + email: 'test@example.com', password: 'bla' } @@ -128,6 +151,7 @@ describe('Test users API validators', function () { it('Should fail with a too long password', function (done) { const data = { username: 'myusername', + email: 'test@example.com', password: 'my super long password which is very very very very very very very very very very very very very very' + 'very very very very very very very very very very very very very very very veryv very very very very' + 'very very very very very very very very very very very very very very very very very very very very long' @@ -139,6 +163,7 @@ describe('Test users API validators', function () { it('Should fail with an non authenticated user', function (done) { const data = { username: 'myusername', + email: 'test@example.com', password: 'my super password' } @@ -148,6 +173,17 @@ describe('Test users API validators', function () { it('Should fail if we add a user with the same username', function (done) { const data = { username: 'user1', + email: 'test@example.com', + password: 'my super password' + } + + requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done, 409) + }) + + it('Should fail if we add a user with the same email', function (done) { + const data = { + username: 'myusername', + email: 'user1@example.com', password: 'my super password' } @@ -157,6 +193,7 @@ describe('Test users API validators', function () { it('Should succeed with the correct params', function (done) { const data = { username: 'user2', + email: 'test@example.com', password: 'my super password' } @@ -166,6 +203,7 @@ describe('Test users API validators', function () { it('Should fail with a non admin user', function (done) { server.user = { username: 'user1', + email: 'test@example.com', password: 'my super password' } @@ -176,6 +214,7 @@ describe('Test users API validators', function () { const data = { username: 'user3', + email: 'test@example.com', password: 'my super password' } diff --git a/server/tests/api/users.js b/server/tests/api/users.js index e6d937eb0..df075f48a 100644 --- a/server/tests/api/users.js +++ b/server/tests/api/users.js @@ -186,6 +186,7 @@ describe('Test users', function () { const user = res.body expect(user.username).to.equal('user_1') + expect(user.email).to.equal('user_1@example.com') expect(user.id).to.exist done() @@ -216,9 +217,11 @@ describe('Test users', function () { const user = users[0] expect(user.username).to.equal('user_1') + expect(user.email).to.equal('user_1@example.com') const rootUser = users[1] expect(rootUser.username).to.equal('root') + expect(rootUser.email).to.equal('admin1@example.com') userId = user.id done() @@ -238,6 +241,7 @@ describe('Test users', function () { const user = users[0] expect(user.username).to.equal('root') + expect(user.email).to.equal('admin1@example.com') done() }) @@ -256,6 +260,7 @@ describe('Test users', function () { const user = users[0] expect(user.username).to.equal('user_1') + expect(user.email).to.equal('user_1@example.com') done() }) @@ -274,6 +279,7 @@ describe('Test users', function () { const user = users[0] expect(user.username).to.equal('user_1') + expect(user.email).to.equal('user_1@example.com') done() }) @@ -291,7 +297,9 @@ describe('Test users', function () { expect(users.length).to.equal(2) expect(users[0].username).to.equal('root') + expect(users[0].email).to.equal('admin1@example.com') expect(users[1].username).to.equal('user_1') + expect(users[1].email).to.equal('user_1@example.com') done() }) diff --git a/server/tests/utils/users.js b/server/tests/utils/users.js index 2bf9c6e3e..a2c010f64 100644 --- a/server/tests/utils/users.js +++ b/server/tests/utils/users.js @@ -20,12 +20,17 @@ function createUser (url, accessToken, username, password, specialStatus, end) { } const path = '/api/v1/users' + const body = { + username, + password, + email: username + '@example.com' + } request(url) .post(path) .set('Accept', 'application/json') .set('Authorization', 'Bearer ' + accessToken) - .send({ username: username, password: password }) + .send(body) .expect(specialStatus) .end(end) } -- cgit v1.2.3