aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/user.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/user.ts')
-rw-r--r--server/models/user.ts197
1 files changed, 197 insertions, 0 deletions
diff --git a/server/models/user.ts b/server/models/user.ts
new file mode 100644
index 000000000..d63a50cc4
--- /dev/null
+++ b/server/models/user.ts
@@ -0,0 +1,197 @@
1import { values } from 'lodash'
2
3import { getSort } from './utils'
4import { USER_ROLES } from '../initializers'
5import {
6 cryptPassword,
7 comparePassword,
8 isUserPasswordValid,
9 isUserUsernameValid,
10 isUserDisplayNSFWValid
11} from '../helpers'
12
13// ---------------------------------------------------------------------------
14
15module.exports = function (sequelize, DataTypes) {
16 const User = sequelize.define('User',
17 {
18 password: {
19 type: DataTypes.STRING,
20 allowNull: false,
21 validate: {
22 passwordValid: function (value) {
23 const res = isUserPasswordValid(value)
24 if (res === false) throw new Error('Password not valid.')
25 }
26 }
27 },
28 username: {
29 type: DataTypes.STRING,
30 allowNull: false,
31 validate: {
32 usernameValid: function (value) {
33 const res = isUserUsernameValid(value)
34 if (res === false) throw new Error('Username not valid.')
35 }
36 }
37 },
38 email: {
39 type: DataTypes.STRING(400),
40 allowNull: false,
41 validate: {
42 isEmail: true
43 }
44 },
45 displayNSFW: {
46 type: DataTypes.BOOLEAN,
47 allowNull: false,
48 defaultValue: false,
49 validate: {
50 nsfwValid: function (value) {
51 const res = isUserDisplayNSFWValid(value)
52 if (res === false) throw new Error('Display NSFW is not valid.')
53 }
54 }
55 },
56 role: {
57 type: DataTypes.ENUM(values(USER_ROLES)),
58 allowNull: false
59 }
60 },
61 {
62 indexes: [
63 {
64 fields: [ 'username' ],
65 unique: true
66 },
67 {
68 fields: [ 'email' ],
69 unique: true
70 }
71 ],
72 classMethods: {
73 associate,
74
75 countTotal,
76 getByUsername,
77 list,
78 listForApi,
79 loadById,
80 loadByUsername,
81 loadByUsernameOrEmail
82 },
83 instanceMethods: {
84 isPasswordMatch,
85 toFormatedJSON,
86 isAdmin
87 },
88 hooks: {
89 beforeCreate: beforeCreateOrUpdate,
90 beforeUpdate: beforeCreateOrUpdate
91 }
92 }
93 )
94
95 return User
96}
97
98function beforeCreateOrUpdate (user, options, next) {
99 cryptPassword(user.password, function (err, hash) {
100 if (err) return next(err)
101
102 user.password = hash
103
104 return next()
105 })
106}
107
108// ------------------------------ METHODS ------------------------------
109
110function isPasswordMatch (password, callback) {
111 return comparePassword(password, this.password, callback)
112}
113
114function toFormatedJSON () {
115 return {
116 id: this.id,
117 username: this.username,
118 email: this.email,
119 displayNSFW: this.displayNSFW,
120 role: this.role,
121 createdAt: this.createdAt
122 }
123}
124
125function isAdmin () {
126 return this.role === USER_ROLES.ADMIN
127}
128
129// ------------------------------ STATICS ------------------------------
130
131function associate (models) {
132 this.hasOne(models.Author, {
133 foreignKey: 'userId',
134 onDelete: 'cascade'
135 })
136
137 this.hasMany(models.OAuthToken, {
138 foreignKey: 'userId',
139 onDelete: 'cascade'
140 })
141}
142
143function countTotal (callback) {
144 return this.count().asCallback(callback)
145}
146
147function getByUsername (username) {
148 const query = {
149 where: {
150 username: username
151 }
152 }
153
154 return this.findOne(query)
155}
156
157function list (callback) {
158 return this.find().asCallback(callback)
159}
160
161function listForApi (start, count, sort, callback) {
162 const query = {
163 offset: start,
164 limit: count,
165 order: [ getSort(sort) ]
166 }
167
168 return this.findAndCountAll(query).asCallback(function (err, result) {
169 if (err) return callback(err)
170
171 return callback(null, result.rows, result.count)
172 })
173}
174
175function loadById (id, callback) {
176 return this.findById(id).asCallback(callback)
177}
178
179function loadByUsername (username, callback) {
180 const query = {
181 where: {
182 username: username
183 }
184 }
185
186 return this.findOne(query).asCallback(callback)
187}
188
189function loadByUsernameOrEmail (username, email, callback) {
190 const query = {
191 where: {
192 $or: [ { username }, { email } ]
193 }
194 }
195
196 return this.findOne(query).asCallback(callback)
197}