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