From 85d7dd1489504321e57895917d4cc5777ef3bda4 Mon Sep 17 00:00:00 2001 From: Rik Smale Date: Wed, 10 Feb 2021 13:45:56 +0100 Subject: [PATCH] fix(email): restrict email change. Fixes MA-173 (#227) * fix(email): restrict email change. Fixes MA-173 * chore(email): add tests and change regex * chore(email): move validation to model --- lib/constants.js | 3 ++- models/MailChange.js | 7 ++++++- models/User.js | 8 +++----- test/unit/mail-changes.test.js | 24 ++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/lib/constants.js b/lib/constants.js index 3b63e418..6df7e082 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -79,5 +79,6 @@ module.exports = { MAIL_CHANGE: 'MyAEGEE: Email change', PASSWORD_RESET: 'MyAEGEE: password reset request', NEW_JOIN_REQUEST: 'MyAEGEE: new join request for your body' - } + }, + RESTRICTED_EMAILS: ['aegee.org', 'aegee.eu'] }; diff --git a/models/MailChange.js b/models/MailChange.js index b69f6ac5..0f49cb9f 100644 --- a/models/MailChange.js +++ b/models/MailChange.js @@ -25,7 +25,12 @@ const MailChange = sequelize.define('mail_change', { validate: { notEmpty: { msg: 'New email should be set.' }, notNull: { msg: 'New email should be set.' }, - isEmail: { msg: 'New email should be valid.' } + isEmail: { msg: 'New email should be valid.' }, + isValid(value) { + if (constants.RESTRICTED_EMAILS.some((email) => value.includes(email))) { + throw new Error('Email can not be in one of the following domains: ' + constants.RESTRICTED_EMAILS.join(', ').trim() + '.'); + } + } }, unique: true }, diff --git a/models/User.js b/models/User.js index e77e7f30..4abd93b8 100644 --- a/models/User.js +++ b/models/User.js @@ -1,14 +1,12 @@ const bcrypt = require('bcrypt'); const moment = require('moment'); +const constants = require('../lib/constants'); const { Sequelize, sequelize } = require('../lib/sequelize'); const config = require('../config'); -const RESTRICTED_EMAILS = ['aegee.org', 'aegee.eu']; const NAME_REGEX = new RegExp('^[\\p{L}. \\-\']*$', 'u'); const USERNAME_REGEX = new RegExp('^[a-zA-Z0-9._-]*$'); -// eslint-disable-next-line no-useless-escape -const EMAIL_REGEX = new RegExp('\@(' + RESTRICTED_EMAILS.join('|').trim() + ')'); const User = sequelize.define('user', { username: { @@ -33,8 +31,8 @@ const User = sequelize.define('user', { notNull: { msg: 'Email should be set.' }, isEmail: { msg: 'Email should be valid.' }, isValid(value) { - if (EMAIL_REGEX.test(value)) { - throw new Error('Email can not be in one of the following domains: ' + RESTRICTED_EMAILS.join(', ').trim() + '.'); + if (constants.RESTRICTED_EMAILS.some((email) => value.includes(email))) { + throw new Error('Email can not be in one of the following domains: ' + constants.RESTRICTED_EMAILS.join(', ').trim() + '.'); } } }, diff --git a/test/unit/mail-changes.test.js b/test/unit/mail-changes.test.js index 1303d743..13ce3dd8 100644 --- a/test/unit/mail-changes.test.js +++ b/test/unit/mail-changes.test.js @@ -52,6 +52,30 @@ describe('Mail changes', () => { } }); + test('should fail with invalid new_email (aegee.eu)', async () => { + try { + const user = await generator.createUser(); + await generator.createMailChange({ new_email: 'test@aegee.eu' }, user); + expect(1).toEqual(0); + } catch (err) { + expect(err).toHaveProperty('errors'); + expect(err.errors.length).toEqual(1); + expect(err.errors[0].path).toEqual('new_email'); + } + }); + + test('should fail with invalid new_email (aegee.org)', async () => { + try { + const user = await generator.createUser(); + await generator.createMailChange({ new_email: 'test@aegee.org' }, user); + expect(1).toEqual(0); + } catch (err) { + expect(err).toHaveProperty('errors'); + expect(err.errors.length).toEqual(1); + expect(err.errors[0].path).toEqual('new_email'); + } + }); + test('should normalize fields', async () => { const user = await generator.createUser(); const permission = await MailChange.create({