Server: little refractoring
[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       role: {
36         type: DataTypes.ENUM(values(constants.USER_ROLES)),
37         allowNull: false
38       }
39     },
40     {
41       indexes: [
42         {
43           fields: [ 'username' ]
44         }
45       ],
46       classMethods: {
47         associate,
48
49         countTotal,
50         getByUsername,
51         list,
52         listForApi,
53         loadById,
54         loadByUsername
55       },
56       instanceMethods: {
57         isPasswordMatch,
58         toFormatedJSON
59       },
60       hooks: {
61         beforeCreate: beforeCreateOrUpdate,
62         beforeUpdate: beforeCreateOrUpdate
63       }
64     }
65   )
66
67   return User
68 }
69
70 function beforeCreateOrUpdate (user, options, next) {
71   peertubeCrypto.cryptPassword(user.password, function (err, hash) {
72     if (err) return next(err)
73
74     user.password = hash
75
76     return next()
77   })
78 }
79
80 // ------------------------------ METHODS ------------------------------
81
82 function isPasswordMatch (password, callback) {
83   return peertubeCrypto.comparePassword(password, this.password, callback)
84 }
85
86 function toFormatedJSON () {
87   return {
88     id: this.id,
89     username: this.username,
90     role: this.role,
91     createdAt: this.createdAt
92   }
93 }
94 // ------------------------------ STATICS ------------------------------
95
96 function associate (models) {
97   this.hasOne(models.Author, {
98     foreignKey: 'userId',
99     onDelete: 'cascade'
100   })
101
102   this.hasMany(models.OAuthToken, {
103     foreignKey: 'userId',
104     onDelete: 'cascade'
105   })
106 }
107
108 function countTotal (callback) {
109   return this.count().asCallback(callback)
110 }
111
112 function getByUsername (username) {
113   const query = {
114     where: {
115       username: username
116     }
117   }
118
119   return this.findOne(query)
120 }
121
122 function list (callback) {
123   return this.find().asCallback(callback)
124 }
125
126 function listForApi (start, count, sort, callback) {
127   const query = {
128     offset: start,
129     limit: count,
130     order: [ modelUtils.getSort(sort) ]
131   }
132
133   return this.findAndCountAll(query).asCallback(function (err, result) {
134     if (err) return callback(err)
135
136     return callback(null, result.rows, result.count)
137   })
138 }
139
140 function loadById (id, callback) {
141   return this.findById(id).asCallback(callback)
142 }
143
144 function loadByUsername (username, callback) {
145   const query = {
146     where: {
147       username: username
148     }
149   }
150
151   return this.findOne(query).asCallback(callback)
152 }