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