From feb4bdfd9b46e87aadfa7c0d5338cde887d1f58c Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sun, 11 Dec 2016 21:50:51 +0100 Subject: First version with PostgreSQL --- server/models/user.js | 132 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 80 insertions(+), 52 deletions(-) (limited to 'server/models/user.js') diff --git a/server/models/user.js b/server/models/user.js index a19de7072..e50eb96ea 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -1,60 +1,60 @@ -const mongoose = require('mongoose') - -const customUsersValidators = require('../helpers/custom-validators').users const modelUtils = require('./utils') const peertubeCrypto = require('../helpers/peertube-crypto') -const OAuthToken = mongoose.model('OAuthToken') - // --------------------------------------------------------------------------- -const UserSchema = mongoose.Schema({ - createdDate: { - type: Date, - default: Date.now - }, - password: String, - username: String, - role: String -}) - -UserSchema.path('password').required(customUsersValidators.isUserPasswordValid) -UserSchema.path('username').required(customUsersValidators.isUserUsernameValid) -UserSchema.path('role').validate(customUsersValidators.isUserRoleValid) - -UserSchema.methods = { - isPasswordMatch, - toFormatedJSON +module.exports = function (sequelize, DataTypes) { + const User = sequelize.define('User', + { + password: { + type: DataTypes.STRING + }, + username: { + type: DataTypes.STRING + }, + role: { + type: DataTypes.STRING + } + }, + { + classMethods: { + associate, + + countTotal, + getByUsername, + list, + listForApi, + loadById, + loadByUsername + }, + instanceMethods: { + isPasswordMatch, + toFormatedJSON + }, + hooks: { + beforeCreate: beforeCreateOrUpdate, + beforeUpdate: beforeCreateOrUpdate + } + } + ) + + return User } -UserSchema.statics = { - countTotal, - getByUsername, - list, - listForApi, - loadById, - loadByUsername -} +// TODO: Validation +// UserSchema.path('password').required(customUsersValidators.isUserPasswordValid) +// UserSchema.path('username').required(customUsersValidators.isUserUsernameValid) +// UserSchema.path('role').validate(customUsersValidators.isUserRoleValid) -UserSchema.pre('save', function (next) { - const user = this - - peertubeCrypto.cryptPassword(this.password, function (err, hash) { +function beforeCreateOrUpdate (user, options, next) { + peertubeCrypto.cryptPassword(user.password, function (err, hash) { if (err) return next(err) user.password = hash return next() }) -}) - -UserSchema.pre('remove', function (next) { - const user = this - - OAuthToken.removeByUserId(user._id, next) -}) - -mongoose.model('User', UserSchema) +} // ------------------------------ METHODS ------------------------------ @@ -64,35 +64,63 @@ function isPasswordMatch (password, callback) { function toFormatedJSON () { return { - id: this._id, + id: this.id, username: this.username, role: this.role, - createdDate: this.createdDate + createdAt: this.createdAt } } // ------------------------------ STATICS ------------------------------ +function associate (models) { + this.hasMany(models.OAuthToken, { + foreignKey: 'userId', + onDelete: 'cascade' + }) +} + function countTotal (callback) { - return this.count(callback) + return this.count().asCallback(callback) } function getByUsername (username) { - return this.findOne({ username: username }) + const query = { + where: { + username: username + } + } + + return this.findOne(query) } function list (callback) { - return this.find(callback) + return this.find().asCallback(callback) } function listForApi (start, count, sort, callback) { - const query = {} - return modelUtils.listForApiWithCount.call(this, query, start, count, sort, callback) + const query = { + offset: start, + limit: count, + order: [ modelUtils.getSort(sort) ] + } + + return this.findAndCountAll(query).asCallback(function (err, result) { + if (err) return callback(err) + + return callback(null, result.rows, result.count) + }) } function loadById (id, callback) { - return this.findById(id, callback) + return this.findById(id).asCallback(callback) } function loadByUsername (username, callback) { - return this.findOne({ username: username }, callback) + const query = { + where: { + username: username + } + } + + return this.findOne(query).asCallback(callback) } -- cgit v1.2.3 From 67bf9b96bbcd92b069fe86d9223fe0f8b9c6e677 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 28 Dec 2016 15:49:23 +0100 Subject: Server: add database field validations --- server/models/user.js | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'server/models/user.js') diff --git a/server/models/user.js b/server/models/user.js index e50eb96ea..944986a44 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -1,5 +1,11 @@ +'use strict' + +const values = require('lodash/values') + const modelUtils = require('./utils') +const constants = require('../initializers/constants') const peertubeCrypto = require('../helpers/peertube-crypto') +const customUsersValidators = require('../helpers/custom-validators').users // --------------------------------------------------------------------------- @@ -7,13 +13,28 @@ module.exports = function (sequelize, DataTypes) { const User = sequelize.define('User', { password: { - type: DataTypes.STRING + type: DataTypes.STRING, + allowNull: false, + validate: { + passwordValid: function (value) { + const res = customUsersValidators.isUserPasswordValid(value) + if (res === false) throw new Error('Password not valid.') + } + } }, username: { - type: DataTypes.STRING + type: DataTypes.STRING, + allowNull: false, + validate: { + usernameValid: function (value) { + const res = customUsersValidators.isUserUsernameValid(value) + if (res === false) throw new Error('Username not valid.') + } + } }, role: { - type: DataTypes.STRING + type: DataTypes.ENUM(values(constants.USER_ROLES)), + allowNull: false } }, { @@ -41,11 +62,6 @@ module.exports = function (sequelize, DataTypes) { return User } -// TODO: Validation -// UserSchema.path('password').required(customUsersValidators.isUserPasswordValid) -// UserSchema.path('username').required(customUsersValidators.isUserUsernameValid) -// UserSchema.path('role').validate(customUsersValidators.isUserRoleValid) - function beforeCreateOrUpdate (user, options, next) { peertubeCrypto.cryptPassword(user.password, function (err, hash) { if (err) return next(err) -- cgit v1.2.3 From 319d072e8eb7266cd8d33e0bb2fb5ebe76c487d1 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 29 Dec 2016 09:33:28 +0100 Subject: Server: Add postgresql indexes --- server/models/user.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'server/models/user.js') diff --git a/server/models/user.js b/server/models/user.js index 944986a44..631cd96c9 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -38,6 +38,11 @@ module.exports = function (sequelize, DataTypes) { } }, { + indexes: [ + { + fields: [ 'username' ] + } + ], classMethods: { associate, -- cgit v1.2.3 From 4712081f2a5f48749cf125d729e78b926ab28d6d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 29 Dec 2016 10:33:36 +0100 Subject: Server: add association between author and user --- server/models/user.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'server/models/user.js') diff --git a/server/models/user.js b/server/models/user.js index 631cd96c9..36ed723cc 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -94,6 +94,11 @@ function toFormatedJSON () { // ------------------------------ STATICS ------------------------------ function associate (models) { + this.hasOne(models.Author, { + foreignKey: 'userId', + onDelete: 'cascade' + }) + this.hasMany(models.OAuthToken, { foreignKey: 'userId', onDelete: 'cascade' -- cgit v1.2.3