From 6e64ff856b122f9c230fff25dcdfe2aa8dcbf5e7 Mon Sep 17 00:00:00 2001 From: Felipe Arboleda Giraldo Date: Tue, 27 Jun 2017 10:41:09 -0500 Subject: [PATCH] Sequelizejs Breaking Changes Breaking Changes Node version: To use new ES2015 features, we now require at least Node 4. From now on, we will support all current LTS versions of Node. The counter cache plugin, and consequently the counterCache option for associations has been removed. The same behaviour can be achieved using afterCreate and afterDelete hooks. Removed MariaDB dialect. This was just a thin wrapper around MySQL, so using dialect: 'mysql' instead should work with no further changes Removed default REPEATABLE_READ transaction isolation. The isolation level now defaults to that of the database. Explicitly pass the required isolation level when initiating the transaction. Removed support for pool: false. To use a single connection, set pool.max to 1. (MySQL) BIGINT now gets converted to string when number is too big Removed support for referencesKey, use a references object references: { key: '', model: '' } classMethods and instanceMethods are removed. Previous: const Model = sequelize.define('Model', { ... }, { classMethods: { associate: function (model) {...} }, instanceMethods: { someMethod: function () { ...} } }); New: const Model = sequelize.define('Model', { ... }); // Class Method Model.associate = function (models) { ...associate the models }; // Instance Method Model.prototype.someMethod = function () {..} Model.Instance and instance.Model are removed. To access the Model from an instance, simply use instance.constructor. The Instance class (Model.Instance) is now the Model itself. Taken from: http://docs.sequelizejs.com/manual/tutorial/upgrade-to-v4.html --- .../users/server/models/user.server.model.js | 291 ++++++++++-------- 1 file changed, 156 insertions(+), 135 deletions(-) diff --git a/modules/users/server/models/user.server.model.js b/modules/users/server/models/user.server.model.js index e68413d..8188b57 100644 --- a/modules/users/server/models/user.server.model.js +++ b/modules/users/server/models/user.server.model.js @@ -1,5 +1,12 @@ 'use strict'; +//User model for MySQL, MariaDB, SQLite and MSSQL database dialects + +/** + * File Path: /modules/users/server/models/user.server.model.js + * File Version: 0.2 + */ + /** * User Model */ @@ -10,161 +17,175 @@ var crypto = require('crypto'); * A Validation function for local strategy properties */ var validateLocalStrategyProperty = function(property) { - if (((this.provider !== 'local' && !this.updated) || property.length !== 0) === false) { - throw new Error('Local strategy failed'); - } + if (((this.provider !== 'local' && !this.updated) || property.length !== 0) === false) { + throw new Error('Local strategy failed'); + } }; /** * A Validation function for local strategy password */ var validateLocalStrategyPassword = function(password) { - if ((this.provider !== 'local' || (password && password.length > 6)) === false) { - throw new Error('One field is missing'); - } + if ((this.provider !== 'local' || (password && password.length > 6)) === false) { + throw new Error('One field is missing'); + } }; module.exports = function(sequelize, DataTypes) { - var User = sequelize.define('user', { - firstName: { - type: DataTypes.STRING, - defaultValue: '', - validate: { - isValid: validateLocalStrategyProperty, - len: { - args: [1, 30], - msg: "First name title must be between 1 and 30 characters in length" + const User = sequelize.define('user', { + firstName: { + type: DataTypes.STRING, + defaultValue: '', + validate: { + isValid: validateLocalStrategyProperty, + len: { + args: [1, 30], + msg: "First name title must be between 1 and 30 characters in length" + }, + } }, - } - }, - lastName: { - type: DataTypes.STRING, - defaultValue: '', - validate: { - isValid: validateLocalStrategyProperty - } - }, - displayName: { - type: DataTypes.STRING, - defaultValue: '' - }, - username: { - type: DataTypes.STRING, - allowNull: false, - unique: true, - validate: { - isUnique: function(value, next) { - var self = this; - User.find({ - where: { - username: value - } - }) - .then(function(user) { - // reject if a different user wants to use the same email - if (user && self.id !== user.id) { - return next('Username already exists, please choose another'); - } - return next(); - }) - .catch(function(err) { - return next(err); - }); - } - } - }, - email: { - type: DataTypes.STRING, - unique: true, - validate: { - isValid: validateLocalStrategyProperty, - isEmail: { - msg: 'Please fill a valid email address' + lastName: { + type: DataTypes.STRING, + defaultValue: '', + validate: { + isValid: validateLocalStrategyProperty + } + }, + displayName: { + type: DataTypes.STRING, + defaultValue: '' + }, + username: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + validate: { + isUnique: function(value, next) { + var self = this; + User.find({ + where: { + username: value + } + }) + .then(function(user) { + // reject if a different user wants to use the same email + if (user && self.id !== user.id) { + return next('Username already exists, please choose another'); + } + return next(); + }) + .catch(function(err) { + return next(err); + }); + } + } + }, + email: { + type: DataTypes.STRING, + unique: true, + validate: { + isValid: validateLocalStrategyProperty, + isEmail: { + msg: 'Please fill a valid email address' + }, + isUnique: function(value, next) { + var self = this; + User.find({ + where: { + email: value + } + }) + .then(function(user) { + // reject if a different user wants to use the same email + if (user && self.id !== user.id) { + return next('Email already exists, please choose another'); + } + return next(); + }) + .catch(function(err) { + return next(err); + }); + } + } }, - isUnique: function(value, next) { - var self = this; - User.find({ - where: { - email: value - } - }) - .then(function(user) { - // reject if a different user wants to use the same email - if (user && self.id !== user.id) { - return next('Email already exists, please choose another'); - } - return next(); - }) - .catch(function(err) { - return next(err); - }); + profileImageURL: DataTypes.STRING, + roles: { + type: DataTypes.STRING, + defaultValue: "user", + isArray: false, + get: function() { + if (!this.isNewRecord) { + return this.dataValues.roles.split(','); + } + } + }, + hashedPassword: { + type: DataTypes.STRING, + default: '', + validate: { + isValid: validateLocalStrategyPassword + } + }, + salt: DataTypes.STRING, + resetPasswordToken: DataTypes.STRING, + resetPasswordExpires: DataTypes.BIGINT, + provider: DataTypes.STRING, + providerData: { + type: DataTypes.TEXT + }, + additionalProvidersData: { + type: DataTypes.TEXT + }, + facebookUserId: DataTypes.STRING, + twitterUserId: DataTypes.STRING, + githubUserId: DataTypes.STRING, + googleUserId: DataTypes.STRING, + linkedinUserId: DataTypes.STRING, + paypalUserId: DataTypes.STRING + }); + + //hooks + User.beforeValidate((user, options) => { + if (user.isNewRecord) { + user.roles = user.dataValues.roles.toString(); + } else { + user.roles = user.roles.toString(); } - } - }, - profileImageURL: DataTypes.STRING, - roles: { - type: DataTypes.JSON, - defaultValue: ["user"], - isArray: true - }, - hashedPassword: { - type: DataTypes.STRING, - default: '', - validate: { - isValid: validateLocalStrategyPassword - } - }, - provider: DataTypes.STRING, - providerData: { - type: DataTypes.JSON - }, - additionalProvidersData: { - type: DataTypes.JSON - }, - salt: DataTypes.STRING, - resetPasswordToken: DataTypes.STRING, - resetPasswordExpires: DataTypes.BIGINT - }, { - classMethods: { - findUniqueUsername: function(username, suffix, callback) { + }) + + // Class Method + User.findUniqueUsername = function(username, suffix, callback) { var _this = this; var possibleUsername = username + (suffix || ''); _this.find({ - where: { - username: possibleUsername - } + where: { + username: possibleUsername + } }).then(function(user) { - if (!user) { - callback(possibleUsername); - } else { - return _this.findUniqueUsername(username, (suffix || 0) + 1, callback); - } + if (!user) { + callback(possibleUsername); + } else { + return _this.findUniqueUsername(username, (suffix || 0) + 1, callback); + } }); - } - } - }); + }; - User.prototype.makeSalt = function() { - return crypto.randomBytes(16).toString('base64'); - }; + // Instance Method + User.prototype.makeSalt = function() { + return crypto.randomBytes(16).toString('base64'); + }; - User.prototype.authenticate = function(plainText) { - return this.encryptPassword(plainText, this.salt) === this.hashedPassword; - }; + User.prototype.authenticate = function(plainText) { + return this.encryptPassword(plainText, this.salt) === this.hashedPassword; + }; - User.prototype.encryptPassword = function(password, salt) { - if (!password || !salt) - return ''; - salt = new Buffer(salt, 'base64'); - return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64'); - }; - - User.associate = function(models) { - if (models.article) { - User.hasMany(models.article); - } - }; + User.prototype.encryptPassword = function(password, salt) { + if (!password || !salt) + return ''; + salt = new Buffer(salt, 'base64'); + return crypto.pbkdf2Sync(password, salt, 10000, 64, crypto.createHash('sha1')).toString('base64'); + }; - return User; + return User; };