]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/user.ts
Better models define typing
[github/Chocobozzz/PeerTube.git] / server / models / user.ts
CommitLineData
65fcc311 1import { values } from 'lodash'
e02643f3 2import * as Sequelize from 'sequelize'
65fcc311
C
3
4import { getSort } from './utils'
5import { USER_ROLES } from '../initializers'
6import {
7 cryptPassword,
8 comparePassword,
9 isUserPasswordValid,
10 isUserUsernameValid,
11 isUserDisplayNSFWValid
12} from '../helpers'
9bd26629 13
e02643f3
C
14import { addMethodsToModel } from './utils'
15import {
16 UserClass,
17 UserInstance,
18 UserAttributes,
19
20 UserMethods
21} from './user-interface'
22
23let User: Sequelize.Model<UserInstance, UserAttributes>
24let isPasswordMatch: UserMethods.IsPasswordMatch
25let toFormatedJSON: UserMethods.ToFormatedJSON
26let isAdmin: UserMethods.IsAdmin
27let countTotal: UserMethods.CountTotal
28let getByUsername: UserMethods.GetByUsername
29let list: UserMethods.List
30let listForApi: UserMethods.ListForApi
31let loadById: UserMethods.LoadById
32let loadByUsername: UserMethods.LoadByUsername
33let loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
34
127944aa
C
35export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
36 User = sequelize.define<UserInstance, UserAttributes>('User',
feb4bdfd
C
37 {
38 password: {
67bf9b96
C
39 type: DataTypes.STRING,
40 allowNull: false,
41 validate: {
42 passwordValid: function (value) {
65fcc311 43 const res = isUserPasswordValid(value)
67bf9b96
C
44 if (res === false) throw new Error('Password not valid.')
45 }
46 }
feb4bdfd
C
47 },
48 username: {
67bf9b96
C
49 type: DataTypes.STRING,
50 allowNull: false,
51 validate: {
52 usernameValid: function (value) {
65fcc311 53 const res = isUserUsernameValid(value)
67bf9b96
C
54 if (res === false) throw new Error('Username not valid.')
55 }
56 }
feb4bdfd 57 },
ad4a8a1c 58 email: {
5804c0db 59 type: DataTypes.STRING(400),
ad4a8a1c
C
60 allowNull: false,
61 validate: {
62 isEmail: true
63 }
64 },
1d49e1e2
C
65 displayNSFW: {
66 type: DataTypes.BOOLEAN,
67 allowNull: false,
68 defaultValue: false,
69 validate: {
70 nsfwValid: function (value) {
65fcc311 71 const res = isUserDisplayNSFWValid(value)
1d49e1e2
C
72 if (res === false) throw new Error('Display NSFW is not valid.')
73 }
74 }
75 },
feb4bdfd 76 role: {
65fcc311 77 type: DataTypes.ENUM(values(USER_ROLES)),
67bf9b96 78 allowNull: false
feb4bdfd
C
79 }
80 },
81 {
319d072e
C
82 indexes: [
83 {
5d67f289
C
84 fields: [ 'username' ],
85 unique: true
ad4a8a1c
C
86 },
87 {
88 fields: [ 'email' ],
89 unique: true
319d072e
C
90 }
91 ],
feb4bdfd
C
92 hooks: {
93 beforeCreate: beforeCreateOrUpdate,
94 beforeUpdate: beforeCreateOrUpdate
95 }
96 }
97 )
98
e02643f3
C
99 const classMethods = [
100 associate,
101
102 countTotal,
103 getByUsername,
104 list,
105 listForApi,
106 loadById,
107 loadByUsername,
108 loadByUsernameOrEmail
109 ]
110 const instanceMethods = [
111 isPasswordMatch,
112 toFormatedJSON,
113 isAdmin
114 ]
115 addMethodsToModel(User, classMethods, instanceMethods)
116
feb4bdfd 117 return User
9bd26629 118}
69b0a27c 119
69818c93 120function beforeCreateOrUpdate (user: UserInstance) {
e02643f3
C
121 return new Promise(function (resolve, reject) {
122 cryptPassword(user.password, function (err, hash) {
123 if (err) return reject(err)
26d7d31b 124
e02643f3 125 user.password = hash
26d7d31b 126
e02643f3
C
127 return resolve()
128 })
26d7d31b 129 })
feb4bdfd 130}
69b0a27c 131
26d7d31b
C
132// ------------------------------ METHODS ------------------------------
133
69818c93 134isPasswordMatch = function (password: string, callback: UserMethods.IsPasswordMatchCallback) {
65fcc311 135 return comparePassword(password, this.password, callback)
26d7d31b
C
136}
137
69f616ab 138toFormatedJSON = function (this: UserInstance) {
26d7d31b 139 return {
feb4bdfd 140 id: this.id,
26d7d31b 141 username: this.username,
ad4a8a1c 142 email: this.email,
1d49e1e2 143 displayNSFW: this.displayNSFW,
d74a0680 144 role: this.role,
feb4bdfd 145 createdAt: this.createdAt
26d7d31b
C
146 }
147}
198b205c 148
e02643f3 149isAdmin = function () {
65fcc311 150 return this.role === USER_ROLES.ADMIN
198b205c
GS
151}
152
26d7d31b 153// ------------------------------ STATICS ------------------------------
69b0a27c 154
feb4bdfd 155function associate (models) {
e02643f3 156 User.hasOne(models.Author, {
4712081f
C
157 foreignKey: 'userId',
158 onDelete: 'cascade'
159 })
160
e02643f3 161 User.hasMany(models.OAuthToken, {
feb4bdfd
C
162 foreignKey: 'userId',
163 onDelete: 'cascade'
164 })
165}
166
69818c93 167countTotal = function (callback: UserMethods.CountTotalCallback) {
feb4bdfd 168 return this.count().asCallback(callback)
089ff2f2
C
169}
170
69818c93 171getByUsername = function (username: string) {
feb4bdfd
C
172 const query = {
173 where: {
174 username: username
175 }
176 }
177
e02643f3 178 return User.findOne(query)
9bd26629
C
179}
180
69818c93 181list = function (callback: UserMethods.ListCallback) {
e02643f3 182 return User.find().asCallback(callback)
00d6b0dd
C
183}
184
69818c93 185listForApi = function (start: number, count: number, sort: string, callback: UserMethods.ListForApiCallback) {
feb4bdfd
C
186 const query = {
187 offset: start,
188 limit: count,
65fcc311 189 order: [ getSort(sort) ]
feb4bdfd
C
190 }
191
e02643f3 192 return User.findAndCountAll(query).asCallback(function (err, result) {
feb4bdfd
C
193 if (err) return callback(err)
194
195 return callback(null, result.rows, result.count)
196 })
69b0a27c
C
197}
198
69818c93 199loadById = function (id: number, callback: UserMethods.LoadByIdCallback) {
e02643f3 200 return User.findById(id).asCallback(callback)
68a3b9f2
C
201}
202
69818c93 203loadByUsername = function (username: string, callback: UserMethods.LoadByUsernameCallback) {
feb4bdfd
C
204 const query = {
205 where: {
206 username: username
207 }
208 }
209
e02643f3 210 return User.findOne(query).asCallback(callback)
9bd26629 211}
ad4a8a1c 212
69818c93 213loadByUsernameOrEmail = function (username: string, email: string, callback: UserMethods.LoadByUsernameOrEmailCallback) {
ad4a8a1c
C
214 const query = {
215 where: {
216 $or: [ { username }, { email } ]
217 }
218 }
219
e02643f3 220 return User.findOne(query).asCallback(callback)
ad4a8a1c 221}