Server: add video language attribute
[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       displayNSFW: {
43         type: DataTypes.BOOLEAN,
44         allowNull: false,
45         defaultValue: false,
46         validate: {
47           nsfwValid: function (value) {
48             const res = customUsersValidators.isUserDisplayNSFWValid(value)
49             if (res === false) throw new Error('Display NSFW is not valid.')
50           }
51         }
52       },
53       role: {
54         type: DataTypes.ENUM(values(constants.USER_ROLES)),
55         allowNull: false
56       }
57     },
58     {
59       indexes: [
60         {
61           fields: [ 'username' ],
62           unique: true
63         },
64         {
65           fields: [ 'email' ],
66           unique: true
67         }
68       ],
69       classMethods: {
70         associate,
71
72         countTotal,
73         getByUsername,
74         list,
75         listForApi,
76         loadById,
77         loadByUsername,
78         loadByUsernameOrEmail
79       },
80       instanceMethods: {
81         isPasswordMatch,
82         toFormatedJSON
83       },
84       hooks: {
85         beforeCreate: beforeCreateOrUpdate,
86         beforeUpdate: beforeCreateOrUpdate
87       }
88     }
89   )
90
91   return User
92 }
93
94 function beforeCreateOrUpdate (user, options, next) {
95   peertubeCrypto.cryptPassword(user.password, function (err, hash) {
96     if (err) return next(err)
97
98     user.password = hash
99
100     return next()
101   })
102 }
103
104 // ------------------------------ METHODS ------------------------------
105
106 function isPasswordMatch (password, callback) {
107   return peertubeCrypto.comparePassword(password, this.password, callback)
108 }
109
110 function toFormatedJSON () {
111   return {
112     id: this.id,
113     username: this.username,
114     email: this.email,
115     displayNSFW: this.displayNSFW,
116     role: this.role,
117     createdAt: this.createdAt
118   }
119 }
120 // ------------------------------ STATICS ------------------------------
121
122 function associate (models) {
123   this.hasOne(models.Author, {
124     foreignKey: 'userId',
125     onDelete: 'cascade'
126   })
127
128   this.hasMany(models.OAuthToken, {
129     foreignKey: 'userId',
130     onDelete: 'cascade'
131   })
132 }
133
134 function countTotal (callback) {
135   return this.count().asCallback(callback)
136 }
137
138 function getByUsername (username) {
139   const query = {
140     where: {
141       username: username
142     }
143   }
144
145   return this.findOne(query)
146 }
147
148 function list (callback) {
149   return this.find().asCallback(callback)
150 }
151
152 function listForApi (start, count, sort, callback) {
153   const query = {
154     offset: start,
155     limit: count,
156     order: [ modelUtils.getSort(sort) ]
157   }
158
159   return this.findAndCountAll(query).asCallback(function (err, result) {
160     if (err) return callback(err)
161
162     return callback(null, result.rows, result.count)
163   })
164 }
165
166 function loadById (id, callback) {
167   return this.findById(id).asCallback(callback)
168 }
169
170 function loadByUsername (username, callback) {
171   const query = {
172     where: {
173       username: username
174     }
175   }
176
177   return this.findOne(query).asCallback(callback)
178 }
179
180 function loadByUsernameOrEmail (username, email, callback) {
181   const query = {
182     where: {
183       $or: [ { username }, { email } ]
184     }
185   }
186
187   return this.findOne(query).asCallback(callback)
188 }