]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/users.ts
Check admin config when loading the page
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / users.ts
CommitLineData
41fb13c3 1import express from 'express'
76314386 2import { body, param, query } from 'express-validator'
b49f22d8
C
3import { Hooks } from '@server/lib/plugins/hooks'
4import { MUserDefault } from '@server/types/models'
a37e9e74 5import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models'
978c87e7 6import { isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
b49f22d8 7import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
b60e5f38 8import {
1eddc9a7 9 isUserAdminFlagsValid,
c1e5bd23 10 isUserAutoPlayNextVideoValid,
1a12adcd
C
11 isUserAutoPlayVideoValid,
12 isUserBlockedReasonValid,
4bbfc6c6
C
13 isUserDescriptionValid,
14 isUserDisplayNameValid,
8f581725 15 isUserNoModal,
0883b324 16 isUserNSFWPolicyValid,
a9bfa85d 17 isUserP2PEnabledValid,
ecb4e35f 18 isUserPasswordValid,
45f1bd72 19 isUserPasswordValidOrEmpty,
ecb4e35f 20 isUserRoleValid,
3e753302
C
21 isUserUsernameValid,
22 isUserVideoLanguages,
1a12adcd 23 isUserVideoQuotaDailyValid,
dae86118
C
24 isUserVideoQuotaValid,
25 isUserVideosHistoryEnabledValid
3fd3ab2d 26} from '../../helpers/custom-validators/users'
27db7840 27import { isVideoChannelDisplayNameValid, isVideoChannelUsernameValid } from '../../helpers/custom-validators/video-channels'
da854ddd 28import { logger } from '../../helpers/logger'
b49f22d8 29import { isThemeRegistered } from '../../lib/plugins/theme-utils'
ecb4e35f 30import { Redis } from '../../lib/redis'
10363c74 31import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup'
7d9ba5c0 32import { ActorModel } from '../../models/actor/actor'
10363c74 33import { UserModel } from '../../models/user/user'
978c87e7 34import { areValidationErrors, doesVideoChannelIdExist, doesVideoExist, isValidVideoIdParam } from './shared'
9bd26629 35
8491293b
RK
36const usersListValidator = [
37 query('blocked')
38 .optional()
f1273314 39 .customSanitizer(toBooleanOrNull)
396f6f01 40 .isBoolean().withMessage('Should be a valid blocked boolena'),
8491293b 41
ea7337cf 42 (req: express.Request, res: express.Response, next: express.NextFunction) => {
8491293b
RK
43 if (areValidationErrors(req, res)) return
44
45 return next()
46 }
47]
48
b60e5f38 49const usersAddValidator = [
396f6f01
C
50 body('username')
51 .custom(isUserUsernameValid)
52 .withMessage('Should have a valid username (lowercase alphanumeric characters)'),
53 body('password')
54 .custom(isUserPasswordValidOrEmpty),
55 body('email')
56 .isEmail(),
27db7840 57
396f6f01
C
58 body('channelName')
59 .optional()
60 .custom(isVideoChannelUsernameValid),
27db7840 61
396f6f01
C
62 body('videoQuota')
63 .custom(isUserVideoQuotaValid),
64 body('videoQuotaDaily')
65 .custom(isUserVideoQuotaDailyValid),
27db7840 66
dea16773
C
67 body('role')
68 .customSanitizer(toIntOrNull)
396f6f01
C
69 .custom(isUserRoleValid),
70
71 body('adminFlags')
72 .optional()
73 .custom(isUserAdminFlagsValid),
9bd26629 74
a2431b7d 75 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a85d5303 76 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
77 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
78
a95a4cc8
C
79 const authUser = res.locals.oauth.token.User
80 if (authUser.role !== UserRole.ADMINISTRATOR && req.body.role !== UserRole.USER) {
76148b27
RK
81 return res.fail({
82 status: HttpStatusCode.FORBIDDEN_403,
83 message: 'You can only create users (and not administrators or moderators)'
84 })
a95a4cc8
C
85 }
86
766d13b4 87 if (req.body.channelName) {
88 if (req.body.channelName === req.body.username) {
76148b27 89 return res.fail({ message: 'Channel name cannot be the same as user username.' })
766d13b4 90 }
4e68fc86 91
766d13b4 92 const existing = await ActorModel.loadLocalByName(req.body.channelName)
93 if (existing) {
76148b27
RK
94 return res.fail({
95 status: HttpStatusCode.CONFLICT_409,
96 message: `Channel with name ${req.body.channelName} already exists.`
97 })
766d13b4 98 }
4e68fc86 99 }
100
a2431b7d 101 return next()
b60e5f38
C
102 }
103]
6fcd19ba 104
b60e5f38 105const usersRegisterValidator = [
396f6f01
C
106 body('username')
107 .custom(isUserUsernameValid),
108 body('password')
109 .custom(isUserPasswordValid),
110 body('email')
111 .isEmail(),
1f20622f
C
112 body('displayName')
113 .optional()
396f6f01 114 .custom(isUserDisplayNameValid),
1f20622f
C
115
116 body('channel.name')
117 .optional()
396f6f01 118 .custom(isVideoChannelUsernameValid),
1f20622f
C
119 body('channel.displayName')
120 .optional()
396f6f01 121 .custom(isVideoChannelDisplayNameValid),
77a5501f 122
a2431b7d 123 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a85d5303 124 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
125 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
126
e590b4a5
C
127 const body: UserRegister = req.body
128 if (body.channel) {
129 if (!body.channel.name || !body.channel.displayName) {
76148b27 130 return res.fail({ message: 'Channel is optional but if you specify it, channel.name and channel.displayName are required.' })
e590b4a5
C
131 }
132
1d5342ab 133 if (body.channel.name === body.username) {
76148b27 134 return res.fail({ message: 'Channel name cannot be the same as user username.' })
1d5342ab
C
135 }
136
e590b4a5
C
137 const existing = await ActorModel.loadLocalByName(body.channel.name)
138 if (existing) {
76148b27
RK
139 return res.fail({
140 status: HttpStatusCode.CONFLICT_409,
141 message: `Channel with name ${body.channel.name} already exists.`
142 })
e590b4a5
C
143 }
144 }
145
a2431b7d 146 return next()
b60e5f38
C
147 }
148]
9bd26629 149
b60e5f38 150const usersRemoveValidator = [
396f6f01
C
151 param('id')
152 .custom(isIdValid),
9bd26629 153
a2431b7d 154 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a2431b7d
C
155 if (areValidationErrors(req, res)) return
156 if (!await checkUserIdExist(req.params.id, res)) return
157
158 const user = res.locals.user
159 if (user.username === 'root') {
76148b27 160 return res.fail({ message: 'Cannot remove the root user' })
a2431b7d
C
161 }
162
163 return next()
b60e5f38
C
164 }
165]
8094a898 166
e6921918 167const usersBlockingValidator = [
396f6f01
C
168 param('id')
169 .custom(isIdValid),
170 body('reason')
171 .optional()
172 .custom(isUserBlockedReasonValid),
e6921918
C
173
174 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
e6921918
C
175 if (areValidationErrors(req, res)) return
176 if (!await checkUserIdExist(req.params.id, res)) return
177
178 const user = res.locals.user
179 if (user.username === 'root') {
76148b27 180 return res.fail({ message: 'Cannot block the root user' })
e6921918
C
181 }
182
183 return next()
184 }
185]
186
92b9d60c 187const deleteMeValidator = [
a1587156 188 (req: express.Request, res: express.Response, next: express.NextFunction) => {
dae86118 189 const user = res.locals.oauth.token.User
92b9d60c 190 if (user.username === 'root') {
76148b27 191 return res.fail({ message: 'You cannot delete your root account.' })
92b9d60c
C
192 }
193
194 return next()
195 }
196]
197
b60e5f38 198const usersUpdateValidator = [
396f6f01
C
199 param('id').custom(isIdValid),
200
201 body('password')
202 .optional()
203 .custom(isUserPasswordValid),
204 body('email')
205 .optional()
206 .isEmail(),
207 body('emailVerified')
208 .optional()
209 .isBoolean(),
210 body('videoQuota')
211 .optional()
212 .custom(isUserVideoQuotaValid),
213 body('videoQuotaDaily')
214 .optional()
215 .custom(isUserVideoQuotaDailyValid),
216 body('pluginAuth')
217 .optional()
218 .exists(),
dea16773
C
219 body('role')
220 .optional()
221 .customSanitizer(toIntOrNull)
396f6f01
C
222 .custom(isUserRoleValid),
223 body('adminFlags')
224 .optional()
225 .custom(isUserAdminFlagsValid),
8094a898 226
a2431b7d 227 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a85d5303 228 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
229 if (!await checkUserIdExist(req.params.id, res)) return
230
f8b8c36b
C
231 const user = res.locals.user
232 if (user.username === 'root' && req.body.role !== undefined && user.role !== req.body.role) {
76148b27 233 return res.fail({ message: 'Cannot change root role.' })
f8b8c36b
C
234 }
235
a2431b7d 236 return next()
b60e5f38
C
237 }
238]
9bd26629 239
b60e5f38 240const usersUpdateMeValidator = [
d1ab89de
C
241 body('displayName')
242 .optional()
396f6f01 243 .custom(isUserDisplayNameValid),
d1ab89de
C
244 body('description')
245 .optional()
396f6f01 246 .custom(isUserDescriptionValid),
d1ab89de
C
247 body('currentPassword')
248 .optional()
396f6f01 249 .custom(isUserPasswordValid),
d1ab89de
C
250 body('password')
251 .optional()
396f6f01 252 .custom(isUserPasswordValid),
d1ab89de
C
253 body('email')
254 .optional()
396f6f01 255 .isEmail(),
d1ab89de
C
256 body('nsfwPolicy')
257 .optional()
396f6f01 258 .custom(isUserNSFWPolicyValid),
d1ab89de
C
259 body('autoPlayVideo')
260 .optional()
396f6f01 261 .custom(isUserAutoPlayVideoValid),
a9bfa85d
C
262 body('p2pEnabled')
263 .optional()
264 .custom(isUserP2PEnabledValid).withMessage('Should have a valid p2p enabled boolean'),
3caf77d3
C
265 body('videoLanguages')
266 .optional()
396f6f01 267 .custom(isUserVideoLanguages),
1a12adcd
C
268 body('videosHistoryEnabled')
269 .optional()
396f6f01 270 .custom(isUserVideosHistoryEnabledValid).withMessage('Should have a valid videos history enabled boolean'),
7cd4d2ba
C
271 body('theme')
272 .optional()
396f6f01 273 .custom(v => isThemeNameValid(v) && isThemeRegistered(v)),
8f581725 274
43d0ea7f
C
275 body('noInstanceConfigWarningModal')
276 .optional()
8f581725 277 .custom(v => isUserNoModal(v)).withMessage('Should have a valid noInstanceConfigWarningModal boolean'),
43d0ea7f
C
278 body('noWelcomeModal')
279 .optional()
8f581725
C
280 .custom(v => isUserNoModal(v)).withMessage('Should have a valid noWelcomeModal boolean'),
281 body('noAccountSetupWarningModal')
282 .optional()
283 .custom(v => isUserNoModal(v)).withMessage('Should have a valid noAccountSetupWarningModal boolean'),
284
c1e5bd23
C
285 body('autoPlayNextVideo')
286 .optional()
287 .custom(v => isUserAutoPlayNextVideoValid(v)).withMessage('Should have a valid autoPlayNextVideo boolean'),
9bd26629 288
a890d1e0 289 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
9a7fd960
C
290 const user = res.locals.oauth.token.User
291
0ba5f5ba 292 if (req.body.password || req.body.email) {
9a7fd960 293 if (user.pluginAuth !== null) {
76148b27 294 return res.fail({ message: 'You cannot update your email or password that is associated with an external auth system.' })
9a7fd960
C
295 }
296
a890d1e0 297 if (!req.body.currentPassword) {
76148b27 298 return res.fail({ message: 'currentPassword parameter is missing.' })
a890d1e0
C
299 }
300
a890d1e0 301 if (await user.isPasswordMatch(req.body.currentPassword) !== true) {
76148b27
RK
302 return res.fail({
303 status: HttpStatusCode.UNAUTHORIZED_401,
304 message: 'currentPassword is invalid.'
305 })
a890d1e0
C
306 }
307 }
308
a85d5303 309 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
310
311 return next()
b60e5f38
C
312 }
313]
8094a898 314
b60e5f38 315const usersGetValidator = [
396f6f01
C
316 param('id')
317 .custom(isIdValid),
318 query('withStats')
319 .optional()
320 .isBoolean().withMessage('Should have a valid withStats boolean'),
d38b8281 321
a2431b7d 322 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a2431b7d 323 if (areValidationErrors(req, res)) return
76314386 324 if (!await checkUserIdExist(req.params.id, res, req.query.withStats)) return
a2431b7d
C
325
326 return next()
b60e5f38
C
327 }
328]
d38b8281 329
b60e5f38 330const usersVideoRatingValidator = [
d4a8e7a6 331 isValidVideoIdParam('videoId'),
0a6658fd 332
a2431b7d 333 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a2431b7d 334 if (areValidationErrors(req, res)) return
0f6acda1 335 if (!await doesVideoExist(req.params.videoId, res, 'id')) return
a2431b7d
C
336
337 return next()
b60e5f38
C
338 }
339]
340
978c87e7
C
341const usersVideosValidator = [
342 query('isLive')
343 .optional()
344 .customSanitizer(toBooleanOrNull)
396f6f01 345 .custom(isBooleanValid).withMessage('Should have a valid isLive boolean'),
978c87e7
C
346
347 query('channelId')
348 .optional()
349 .customSanitizer(toIntOrNull)
396f6f01 350 .custom(isIdValid),
978c87e7
C
351
352 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
978c87e7
C
353 if (areValidationErrors(req, res)) return
354
355 if (req.query.channelId && !await doesVideoChannelIdExist(req.query.channelId, res)) return
356
357 return next()
358 }
359]
360
b60e5f38 361const ensureUserRegistrationAllowed = [
a2431b7d 362 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
4ce7eb71 363 const allowedParams = {
ba7b7e57
RK
364 body: req.body,
365 ip: req.ip
4ce7eb71
C
366 }
367
368 const allowedResult = await Hooks.wrapPromiseFun(
369 isSignupAllowed,
370 allowedParams,
371 'filter:api.user.signup.allowed.result'
372 )
373
374 if (allowedResult.allowed === false) {
76148b27
RK
375 return res.fail({
376 status: HttpStatusCode.FORBIDDEN_403,
377 message: allowedResult.errorMessage || 'User registration is not enabled or user limit is reached.'
378 })
a2431b7d
C
379 }
380
381 return next()
b60e5f38
C
382 }
383]
291e8d3e 384
ff2c1fe8 385const ensureUserRegistrationAllowedForIP = [
a1587156 386 (req: express.Request, res: express.Response, next: express.NextFunction) => {
ff2c1fe8
RK
387 const allowed = isSignupAllowedForCurrentIP(req.ip)
388
389 if (allowed === false) {
76148b27
RK
390 return res.fail({
391 status: HttpStatusCode.FORBIDDEN_403,
392 message: 'You are not on a network authorized for registration.'
393 })
ff2c1fe8
RK
394 }
395
396 return next()
397 }
398]
399
ecb4e35f 400const usersAskResetPasswordValidator = [
396f6f01
C
401 body('email')
402 .isEmail(),
ecb4e35f
C
403
404 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
ecb4e35f 405 if (areValidationErrors(req, res)) return
b426edd4 406
ecb4e35f
C
407 const exists = await checkUserEmailExist(req.body.email, res, false)
408 if (!exists) {
409 logger.debug('User with email %s does not exist (asking reset password).', req.body.email)
410 // Do not leak our emails
2d53be02 411 return res.status(HttpStatusCode.NO_CONTENT_204).end()
ecb4e35f
C
412 }
413
414 return next()
415 }
416]
417
418const usersResetPasswordValidator = [
396f6f01
C
419 param('id')
420 .custom(isIdValid),
421 body('verificationString')
422 .not().isEmpty(),
423 body('password')
424 .custom(isUserPasswordValid),
ecb4e35f
C
425
426 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
ecb4e35f
C
427 if (areValidationErrors(req, res)) return
428 if (!await checkUserIdExist(req.params.id, res)) return
429
dae86118 430 const user = res.locals.user
ecb4e35f
C
431 const redisVerificationString = await Redis.Instance.getResetPasswordLink(user.id)
432
433 if (redisVerificationString !== req.body.verificationString) {
76148b27
RK
434 return res.fail({
435 status: HttpStatusCode.FORBIDDEN_403,
436 message: 'Invalid verification string.'
437 })
ecb4e35f
C
438 }
439
440 return next()
441 }
442]
443
d9eaee39
JM
444const usersAskSendVerifyEmailValidator = [
445 body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'),
446
447 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
d9eaee39 448 if (areValidationErrors(req, res)) return
a85d5303 449
d9eaee39
JM
450 const exists = await checkUserEmailExist(req.body.email, res, false)
451 if (!exists) {
452 logger.debug('User with email %s does not exist (asking verify email).', req.body.email)
453 // Do not leak our emails
2d53be02 454 return res.status(HttpStatusCode.NO_CONTENT_204).end()
d9eaee39
JM
455 }
456
457 return next()
458 }
459]
460
461const usersVerifyEmailValidator = [
d1ab89de
C
462 param('id')
463 .isInt().not().isEmpty().withMessage('Should have a valid id'),
464
465 body('verificationString')
466 .not().isEmpty().withMessage('Should have a valid verification string'),
467 body('isPendingEmail')
468 .optional()
2b65c4e5 469 .customSanitizer(toBooleanOrNull),
d9eaee39
JM
470
471 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
d9eaee39
JM
472 if (areValidationErrors(req, res)) return
473 if (!await checkUserIdExist(req.params.id, res)) return
474
dae86118 475 const user = res.locals.user
d9eaee39
JM
476 const redisVerificationString = await Redis.Instance.getVerifyEmailLink(user.id)
477
478 if (redisVerificationString !== req.body.verificationString) {
76148b27
RK
479 return res.fail({
480 status: HttpStatusCode.FORBIDDEN_403,
481 message: 'Invalid verification string.'
482 })
d9eaee39
JM
483 }
484
485 return next()
486 }
487]
488
74d63469 489const userAutocompleteValidator = [
a85d5303
C
490 param('search')
491 .isString()
492 .not().isEmpty()
74d63469
GR
493]
494
c100a614 495const ensureAuthUserOwnsAccountValidator = [
a1587156 496 (req: express.Request, res: express.Response, next: express.NextFunction) => {
c100a614
YB
497 const user = res.locals.oauth.token.User
498
499 if (res.locals.account.id !== user.Account.id) {
76148b27
RK
500 return res.fail({
501 status: HttpStatusCode.FORBIDDEN_403,
7a4fd56c 502 message: 'Only owner of this account can access this resource.'
4beda9e1
C
503 })
504 }
505
506 return next()
507 }
508]
509
a37e9e74 510const ensureCanManageChannel = [
4beda9e1 511 (req: express.Request, res: express.Response, next: express.NextFunction) => {
a37e9e74 512 const user = res.locals.oauth.token.user
513 const isUserOwner = res.locals.videoChannel.Account.userId === user.id
514
515 if (!isUserOwner && user.hasRight(UserRight.MANAGE_ANY_VIDEO_CHANNEL) === false) {
516 const message = `User ${user.username} does not have right to manage channel ${req.params.nameWithHost}.`
4beda9e1 517
4beda9e1
C
518 return res.fail({
519 status: HttpStatusCode.FORBIDDEN_403,
a37e9e74 520 message
76148b27 521 })
c100a614
YB
522 }
523
524 return next()
525 }
526]
527
a95a4cc8
C
528const ensureCanManageUser = [
529 (req: express.Request, res: express.Response, next: express.NextFunction) => {
530 const authUser = res.locals.oauth.token.User
531 const onUser = res.locals.user
532
533 if (authUser.role === UserRole.ADMINISTRATOR) return next()
534 if (authUser.role === UserRole.MODERATOR && onUser.role === UserRole.USER) return next()
535
76148b27
RK
536 return res.fail({
537 status: HttpStatusCode.FORBIDDEN_403,
538 message: 'A moderator can only manager users.'
539 })
a95a4cc8
C
540 }
541]
542
9bd26629
C
543// ---------------------------------------------------------------------------
544
65fcc311 545export {
8491293b 546 usersListValidator,
65fcc311 547 usersAddValidator,
92b9d60c 548 deleteMeValidator,
77a5501f 549 usersRegisterValidator,
e6921918 550 usersBlockingValidator,
65fcc311
C
551 usersRemoveValidator,
552 usersUpdateValidator,
8094a898 553 usersUpdateMeValidator,
291e8d3e 554 usersVideoRatingValidator,
8094a898 555 ensureUserRegistrationAllowed,
ff2c1fe8 556 ensureUserRegistrationAllowedForIP,
c5911fd3 557 usersGetValidator,
978c87e7 558 usersVideosValidator,
ecb4e35f 559 usersAskResetPasswordValidator,
d9eaee39
JM
560 usersResetPasswordValidator,
561 usersAskSendVerifyEmailValidator,
74d63469 562 usersVerifyEmailValidator,
c100a614 563 userAutocompleteValidator,
a95a4cc8 564 ensureAuthUserOwnsAccountValidator,
a37e9e74 565 ensureCanManageUser,
566 ensureCanManageChannel
8094a898
C
567}
568
569// ---------------------------------------------------------------------------
570
76314386 571function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) {
d5d9b6d7 572 const id = parseInt(idArg + '', 10)
fb719404 573 return checkUserExist(() => UserModel.loadByIdWithChannels(id, withStats), res)
ecb4e35f 574}
a2431b7d 575
ecb4e35f
C
576function checkUserEmailExist (email: string, res: express.Response, abortResponse = true) {
577 return checkUserExist(() => UserModel.loadByEmail(email), res, abortResponse)
65fcc311 578}
77a5501f 579
a2431b7d 580async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) {
3fd3ab2d 581 const user = await UserModel.loadByUsernameOrEmail(username, email)
a2431b7d
C
582
583 if (user) {
76148b27
RK
584 res.fail({
585 status: HttpStatusCode.CONFLICT_409,
586 message: 'User with this username or email already exists.'
587 })
a2431b7d
C
588 return false
589 }
590
2ef6a063
C
591 const actor = await ActorModel.loadLocalByName(username)
592 if (actor) {
76148b27
RK
593 res.fail({
594 status: HttpStatusCode.CONFLICT_409,
595 message: 'Another actor (account/channel) with this name on this instance already exists or has already existed.'
596 })
2ef6a063
C
597 return false
598 }
599
a2431b7d 600 return true
77a5501f 601}
ecb4e35f 602
b49f22d8 603async function checkUserExist (finder: () => Promise<MUserDefault>, res: express.Response, abortResponse = true) {
ecb4e35f
C
604 const user = await finder()
605
606 if (!user) {
607 if (abortResponse === true) {
76148b27
RK
608 res.fail({
609 status: HttpStatusCode.NOT_FOUND_404,
610 message: 'User not found'
611 })
ecb4e35f
C
612 }
613
614 return false
615 }
616
617 res.locals.user = user
ecb4e35f
C
618 return true
619}