Server: fix migration scripts
[oweals/peertube.git] / server / models / user.js
1 'use strict'
2
3 const values = require('lodash/values')
4
5 const modelUtils = require('./utils')
6 const constants = require('../initializers/constants')
7 const peertubeCrypto = require('../helpers/peertube-crypto')
8 const customUsersValidators = require('../helpers/custom-validators').users
9
10 // ---------------------------------------------------------------------------
11
12 module.exports = function (sequelize, DataTypes) {
13   const User = sequelize.define('User',
14     {
15       password: {
16         type: DataTypes.STRING,
17         allowNull: false,
18         validate: {
19           passwordValid: function (value) {
20             const res = customUsersValidators.isUserPasswordValid(value)
21             if (res === false) throw new Error('Password not valid.')
22           }
23         }
24       },
25       username: {
26         type: DataTypes.STRING,
27         allowNull: false,
28         validate: {
29           usernameValid: function (value) {
30             const res = customUsersValidators.isUserUsernameValid(value)
31             if (res === false) throw new Error('Username not valid.')
32           }
33         }
34       },
35       email: {
36         type: DataTypes.STRING(400),
37         allowNull: false,
38         validate: {
39           isEmail: true
40         }
41       },
42       role: {
43         type: DataTypes.ENUM(values(constants.USER_ROLES)),
44         allowNull: false
45       }
46     },
47     {
48       indexes: [
49         {
50           fields: [ 'username' ],
51           unique: true
52         },
53         {
54           fields: [ 'email' ],
55           unique: true
56         }
57       ],
58       classMethods: {
59         associate,
60
61         countTotal,
62         getByUsername,
63         list,
64         listForApi,
65         loadById,
66         loadByUsername,
67         loadByUsernameOrEmail
68       },
69       instanceMethods: {
70         isPasswordMatch,
71         toFormatedJSON
72       },
73       hooks: {
74         beforeCreate: beforeCreateOrUpdate,
75         beforeUpdate: beforeCreateOrUpdate
76       }
77     }
78   )
79
80   return User
81 }
82
83 function beforeCreateOrUpdate (user, options, next) {
84   peertubeCrypto.cryptPassword(user.password, function (err, hash) {
85     if (err) return next(err)
86
87     user.password = hash
88
89     return next()
90   })
91 }
92
93 // ------------------------------ METHODS ------------------------------
94
95 function isPasswordMatch (password, callback) {
96   return peertubeCrypto.comparePassword(password, this.password, callback)
97 }
98
99 function toFormatedJSON () {
100   return {
101     id: this.id,
102     username: this.username,
103     email: this.email,
104     role: this.role,
105     createdAt: this.createdAt
106   }
107 }
108 // ------------------------------ STATICS ------------------------------
109
110 function associate (models) {
111   this.hasOne(models.Author, {
112     foreignKey: 'userId',
113     onDelete: 'cascade'
114   })
115
116   this.hasMany(models.OAuthToken, {
117     foreignKey: 'userId',
118     onDelete: 'cascade'
119   })
120 }
121
122 function countTotal (callback) {
123   return this.count().asCallback(callback)
124 }
125
126 function getByUsername (username) {
127   const query = {
128     where: {
129       username: username
130     }
131   }
132
133   return this.findOne(query)
134 }
135
136 function list (callback) {
137   return this.find().asCallback(callback)
138 }
139
140 function listForApi (start, count, sort, callback) {
141   const query = {
142     offset: start,
143     limit: count,
144     order: [ modelUtils.getSort(sort) ]
145   }
146
147   return this.findAndCountAll(query).asCallback(function (err, result) {
148     if (err) return callback(err)
149
150     return callback(null, result.rows, result.count)
151   })
152 }
153
154 function loadById (id, callback) {
155   return this.findById(id).asCallback(callback)
156 }
157
158 function loadByUsername (username, callback) {
159   const query = {
160     where: {
161       username: username
162     }
163   }
164
165   return this.findOne(query).asCallback(callback)
166 }
167
168 function loadByUsernameOrEmail (username, email, callback) {
169   const query = {
170     where: {
171       $or: [ { username }, { email } ]
172     }
173   }
174
175   return this.findOne(query).asCallback(callback)
176 }