diff options
author | Chocobozzz <me@florianbigard.com> | 2022-10-05 15:37:15 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-10-07 10:51:16 +0200 |
commit | 56f47830758ff8e92abcfcc5f35d474ab12fe215 (patch) | |
tree | 854e57ec1b800d6ad740c8e42bee00cbd21e1724 /server/middlewares/validators/users.ts | |
parent | 7dd7ff4cebc290b09fe00d82046bb58e4e8a800d (diff) | |
download | PeerTube-56f47830758ff8e92abcfcc5f35d474ab12fe215.tar.gz PeerTube-56f47830758ff8e92abcfcc5f35d474ab12fe215.tar.zst PeerTube-56f47830758ff8e92abcfcc5f35d474ab12fe215.zip |
Support two factor authentication in backend
Diffstat (limited to 'server/middlewares/validators/users.ts')
-rw-r--r-- | server/middlewares/validators/users.ts | 87 |
1 files changed, 30 insertions, 57 deletions
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index eb693318f..046029547 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -1,9 +1,8 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { body, param, query } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { Hooks } from '@server/lib/plugins/hooks' | 3 | import { Hooks } from '@server/lib/plugins/hooks' |
4 | import { MUserDefault } from '@server/types/models' | ||
5 | import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models' | 4 | import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models' |
6 | import { isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' | 5 | import { exists, isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' |
7 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' | 6 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' |
8 | import { | 7 | import { |
9 | isUserAdminFlagsValid, | 8 | isUserAdminFlagsValid, |
@@ -30,8 +29,15 @@ import { isThemeRegistered } from '../../lib/plugins/theme-utils' | |||
30 | import { Redis } from '../../lib/redis' | 29 | import { Redis } from '../../lib/redis' |
31 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup' | 30 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup' |
32 | import { ActorModel } from '../../models/actor/actor' | 31 | import { ActorModel } from '../../models/actor/actor' |
33 | import { UserModel } from '../../models/user/user' | 32 | import { |
34 | import { areValidationErrors, doesVideoChannelIdExist, doesVideoExist, isValidVideoIdParam } from './shared' | 33 | areValidationErrors, |
34 | checkUserEmailExist, | ||
35 | checkUserIdExist, | ||
36 | checkUserNameOrEmailDoesNotAlreadyExist, | ||
37 | doesVideoChannelIdExist, | ||
38 | doesVideoExist, | ||
39 | isValidVideoIdParam | ||
40 | } from './shared' | ||
35 | 41 | ||
36 | const usersListValidator = [ | 42 | const usersListValidator = [ |
37 | query('blocked') | 43 | query('blocked') |
@@ -435,7 +441,7 @@ const usersResetPasswordValidator = [ | |||
435 | if (!await checkUserIdExist(req.params.id, res)) return | 441 | if (!await checkUserIdExist(req.params.id, res)) return |
436 | 442 | ||
437 | const user = res.locals.user | 443 | const user = res.locals.user |
438 | const redisVerificationString = await Redis.Instance.getResetPasswordLink(user.id) | 444 | const redisVerificationString = await Redis.Instance.getResetPasswordVerificationString(user.id) |
439 | 445 | ||
440 | if (redisVerificationString !== req.body.verificationString) { | 446 | if (redisVerificationString !== req.body.verificationString) { |
441 | return res.fail({ | 447 | return res.fail({ |
@@ -500,6 +506,24 @@ const usersVerifyEmailValidator = [ | |||
500 | } | 506 | } |
501 | ] | 507 | ] |
502 | 508 | ||
509 | const usersCheckCurrentPassword = [ | ||
510 | body('currentPassword').custom(exists), | ||
511 | |||
512 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
513 | if (areValidationErrors(req, res)) return | ||
514 | |||
515 | const user = res.locals.oauth.token.User | ||
516 | if (await user.isPasswordMatch(req.body.currentPassword) !== true) { | ||
517 | return res.fail({ | ||
518 | status: HttpStatusCode.FORBIDDEN_403, | ||
519 | message: 'currentPassword is invalid.' | ||
520 | }) | ||
521 | } | ||
522 | |||
523 | return next() | ||
524 | } | ||
525 | ] | ||
526 | |||
503 | const userAutocompleteValidator = [ | 527 | const userAutocompleteValidator = [ |
504 | param('search') | 528 | param('search') |
505 | .isString() | 529 | .isString() |
@@ -567,6 +591,7 @@ export { | |||
567 | usersUpdateValidator, | 591 | usersUpdateValidator, |
568 | usersUpdateMeValidator, | 592 | usersUpdateMeValidator, |
569 | usersVideoRatingValidator, | 593 | usersVideoRatingValidator, |
594 | usersCheckCurrentPassword, | ||
570 | ensureUserRegistrationAllowed, | 595 | ensureUserRegistrationAllowed, |
571 | ensureUserRegistrationAllowedForIP, | 596 | ensureUserRegistrationAllowedForIP, |
572 | usersGetValidator, | 597 | usersGetValidator, |
@@ -580,55 +605,3 @@ export { | |||
580 | ensureCanModerateUser, | 605 | ensureCanModerateUser, |
581 | ensureCanManageChannelOrAccount | 606 | ensureCanManageChannelOrAccount |
582 | } | 607 | } |
583 | |||
584 | // --------------------------------------------------------------------------- | ||
585 | |||
586 | function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) { | ||
587 | const id = parseInt(idArg + '', 10) | ||
588 | return checkUserExist(() => UserModel.loadByIdWithChannels(id, withStats), res) | ||
589 | } | ||
590 | |||
591 | function checkUserEmailExist (email: string, res: express.Response, abortResponse = true) { | ||
592 | return checkUserExist(() => UserModel.loadByEmail(email), res, abortResponse) | ||
593 | } | ||
594 | |||
595 | async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) { | ||
596 | const user = await UserModel.loadByUsernameOrEmail(username, email) | ||
597 | |||
598 | if (user) { | ||
599 | res.fail({ | ||
600 | status: HttpStatusCode.CONFLICT_409, | ||
601 | message: 'User with this username or email already exists.' | ||
602 | }) | ||
603 | return false | ||
604 | } | ||
605 | |||
606 | const actor = await ActorModel.loadLocalByName(username) | ||
607 | if (actor) { | ||
608 | res.fail({ | ||
609 | status: HttpStatusCode.CONFLICT_409, | ||
610 | message: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' | ||
611 | }) | ||
612 | return false | ||
613 | } | ||
614 | |||
615 | return true | ||
616 | } | ||
617 | |||
618 | async function checkUserExist (finder: () => Promise<MUserDefault>, res: express.Response, abortResponse = true) { | ||
619 | const user = await finder() | ||
620 | |||
621 | if (!user) { | ||
622 | if (abortResponse === true) { | ||
623 | res.fail({ | ||
624 | status: HttpStatusCode.NOT_FOUND_404, | ||
625 | message: 'User not found' | ||
626 | }) | ||
627 | } | ||
628 | |||
629 | return false | ||
630 | } | ||
631 | |||
632 | res.locals.user = user | ||
633 | return true | ||
634 | } | ||