diff options
Diffstat (limited to 'server/middlewares/validators/user-email-verification.ts')
-rw-r--r-- | server/middlewares/validators/user-email-verification.ts | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/server/middlewares/validators/user-email-verification.ts b/server/middlewares/validators/user-email-verification.ts new file mode 100644 index 000000000..74702a8f5 --- /dev/null +++ b/server/middlewares/validators/user-email-verification.ts | |||
@@ -0,0 +1,94 @@ | |||
1 | import express from 'express' | ||
2 | import { body, param } from 'express-validator' | ||
3 | import { toBooleanOrNull } from '@server/helpers/custom-validators/misc' | ||
4 | import { HttpStatusCode } from '@shared/models' | ||
5 | import { logger } from '../../helpers/logger' | ||
6 | import { Redis } from '../../lib/redis' | ||
7 | import { areValidationErrors, checkUserEmailExist, checkUserIdExist } from './shared' | ||
8 | import { checkRegistrationEmailExist, checkRegistrationIdExist } from './shared/user-registrations' | ||
9 | |||
10 | const usersAskSendVerifyEmailValidator = [ | ||
11 | body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'), | ||
12 | |||
13 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
14 | if (areValidationErrors(req, res)) return | ||
15 | |||
16 | const [ userExists, registrationExists ] = await Promise.all([ | ||
17 | checkUserEmailExist(req.body.email, res, false), | ||
18 | checkRegistrationEmailExist(req.body.email, res, false) | ||
19 | ]) | ||
20 | |||
21 | if (!userExists && !registrationExists) { | ||
22 | logger.debug('User or registration with email %s does not exist (asking verify email).', req.body.email) | ||
23 | // Do not leak our emails | ||
24 | return res.status(HttpStatusCode.NO_CONTENT_204).end() | ||
25 | } | ||
26 | |||
27 | if (res.locals.user?.pluginAuth) { | ||
28 | return res.fail({ | ||
29 | status: HttpStatusCode.CONFLICT_409, | ||
30 | message: 'Cannot ask verification email of a user that uses a plugin authentication.' | ||
31 | }) | ||
32 | } | ||
33 | |||
34 | return next() | ||
35 | } | ||
36 | ] | ||
37 | |||
38 | const usersVerifyEmailValidator = [ | ||
39 | param('id') | ||
40 | .isInt().not().isEmpty().withMessage('Should have a valid id'), | ||
41 | |||
42 | body('verificationString') | ||
43 | .not().isEmpty().withMessage('Should have a valid verification string'), | ||
44 | body('isPendingEmail') | ||
45 | .optional() | ||
46 | .customSanitizer(toBooleanOrNull), | ||
47 | |||
48 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
49 | if (areValidationErrors(req, res)) return | ||
50 | if (!await checkUserIdExist(req.params.id, res)) return | ||
51 | |||
52 | const user = res.locals.user | ||
53 | const redisVerificationString = await Redis.Instance.getUserVerifyEmailLink(user.id) | ||
54 | |||
55 | if (redisVerificationString !== req.body.verificationString) { | ||
56 | return res.fail({ status: HttpStatusCode.FORBIDDEN_403, message: 'Invalid verification string.' }) | ||
57 | } | ||
58 | |||
59 | return next() | ||
60 | } | ||
61 | ] | ||
62 | |||
63 | // --------------------------------------------------------------------------- | ||
64 | |||
65 | const registrationVerifyEmailValidator = [ | ||
66 | param('registrationId') | ||
67 | .isInt().not().isEmpty().withMessage('Should have a valid registrationId'), | ||
68 | |||
69 | body('verificationString') | ||
70 | .not().isEmpty().withMessage('Should have a valid verification string'), | ||
71 | |||
72 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
73 | if (areValidationErrors(req, res)) return | ||
74 | if (!await checkRegistrationIdExist(req.params.registrationId, res)) return | ||
75 | |||
76 | const registration = res.locals.userRegistration | ||
77 | const redisVerificationString = await Redis.Instance.getRegistrationVerifyEmailLink(registration.id) | ||
78 | |||
79 | if (redisVerificationString !== req.body.verificationString) { | ||
80 | return res.fail({ status: HttpStatusCode.FORBIDDEN_403, message: 'Invalid verification string.' }) | ||
81 | } | ||
82 | |||
83 | return next() | ||
84 | } | ||
85 | ] | ||
86 | |||
87 | // --------------------------------------------------------------------------- | ||
88 | |||
89 | export { | ||
90 | usersAskSendVerifyEmailValidator, | ||
91 | usersVerifyEmailValidator, | ||
92 | |||
93 | registrationVerifyEmailValidator | ||
94 | } | ||