feat: plugin support to filter email addresses (#6752)
* feat: plugin support to filter email addresses Add support for plugins to filter user email addresses. * Add missing `totalNotDeletedComments` doc * Styling --------- Co-authored-by: Chocobozzz <me@florianbigard.com>
This commit is contained in:
parent
8a0f9b6af3
commit
3f30458c37
|
@ -140,7 +140,12 @@ export const serverFilterHookObject = {
|
|||
// Peertube >= 5.2
|
||||
'filter:feed.podcast.video.create-custom-tags.result': true,
|
||||
// Peertube >= 6.1
|
||||
'filter:api.user.me.get.result': true
|
||||
'filter:api.user.me.get.result': true,
|
||||
|
||||
// Peertube >= 7.1
|
||||
'filter:oauth.password-grant.get-user.params': true,
|
||||
'filter:api.email-verification.ask-send-verify-email.body': true,
|
||||
'filter:api.users.ask-reset-password.body': true
|
||||
}
|
||||
|
||||
export type ServerFilterHookName = keyof typeof serverFilterHookObject
|
||||
|
|
|
@ -17,6 +17,7 @@ import { sha1 } from '@peertube/peertube-node-utils'
|
|||
import { HttpStatusCode, ServerErrorCode, UserRegistrationState } from '@peertube/peertube-models'
|
||||
import { OTP } from '../../initializers/constants.js'
|
||||
import { BypassLogin, getAccessToken, getClient, getRefreshToken, getUser, revokeToken, saveToken } from './oauth-model.js'
|
||||
import { Hooks } from '../plugins/hooks.js'
|
||||
|
||||
class MissingTwoFactorError extends Error {
|
||||
code = HttpStatusCode.UNAUTHORIZED_401
|
||||
|
@ -135,19 +136,25 @@ async function handlePasswordGrant (options: {
|
|||
client: MOAuthClient
|
||||
bypassLogin?: BypassLogin
|
||||
}) {
|
||||
const { request, client, bypassLogin } = options
|
||||
const { client } = options
|
||||
|
||||
if (!request.body.username) {
|
||||
const { bypassLogin, usernameOrEmail, password } = await Hooks.wrapObject({
|
||||
bypassLogin: options.bypassLogin,
|
||||
usernameOrEmail: options.request.body.username,
|
||||
password: options.request.body.password
|
||||
}, 'filter:oauth.password-grant.get-user.params')
|
||||
|
||||
if (!options.request.body.username) {
|
||||
throw new InvalidRequestError('Missing parameter: `username`')
|
||||
}
|
||||
|
||||
if (!bypassLogin && !request.body.password) {
|
||||
if (!bypassLogin && !options.request.body.password) {
|
||||
throw new InvalidRequestError('Missing parameter: `password`')
|
||||
}
|
||||
|
||||
const user = await getUser(request.body.username, request.body.password, bypassLogin)
|
||||
const user = await getUser(usernameOrEmail, password, bypassLogin)
|
||||
if (!user) {
|
||||
const registration = await UserRegistrationModel.loadByEmailOrUsername(request.body.username)
|
||||
const registration = await UserRegistrationModel.loadByEmailOrUsername(usernameOrEmail)
|
||||
|
||||
if (registration?.state === UserRegistrationState.REJECTED) {
|
||||
throw new RegistrationApprovalRejected('Registration approval for this account has been rejected')
|
||||
|
@ -159,11 +166,11 @@ async function handlePasswordGrant (options: {
|
|||
}
|
||||
|
||||
if (user.otpSecret) {
|
||||
if (!request.headers[OTP.HEADER_NAME]) {
|
||||
if (!options.request.headers[OTP.HEADER_NAME]) {
|
||||
throw new MissingTwoFactorError('Missing two factor header')
|
||||
}
|
||||
|
||||
if (await isOTPValid({ encryptedSecret: user.otpSecret, token: request.headers[OTP.HEADER_NAME] }) !== true) {
|
||||
if (await isOTPValid({ encryptedSecret: user.otpSecret, token: options.request.headers[OTP.HEADER_NAME] }) !== true) {
|
||||
throw new InvalidTwoFactorError('Invalid two factor header')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { logger } from '../../../helpers/logger.js'
|
|||
import { Redis } from '../../../lib/redis.js'
|
||||
import { areValidationErrors, checkUserEmailExist, checkUserIdExist } from '../shared/index.js'
|
||||
import { checkRegistrationEmailExist, checkRegistrationIdExist } from './shared/user-registrations.js'
|
||||
import { Hooks } from '@server/lib/plugins/hooks.js'
|
||||
|
||||
const usersAskSendVerifyEmailValidator = [
|
||||
body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'),
|
||||
|
@ -13,13 +14,17 @@ const usersAskSendVerifyEmailValidator = [
|
|||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
const { email } = await Hooks.wrapObject({
|
||||
email: req.body.email
|
||||
}, 'filter:api.email-verification.ask-send-verify-email.body')
|
||||
|
||||
const [ userExists, registrationExists ] = await Promise.all([
|
||||
checkUserEmailExist(req.body.email, res, false),
|
||||
checkRegistrationEmailExist(req.body.email, res, false)
|
||||
checkUserEmailExist(email, res, false),
|
||||
checkRegistrationEmailExist(email, res, false)
|
||||
])
|
||||
|
||||
if (!userExists && !registrationExists) {
|
||||
logger.debug('User or registration with email %s does not exist (asking verify email).', req.body.email)
|
||||
logger.debug('User or registration with email %s does not exist (asking verify email).', email)
|
||||
// Do not leak our emails
|
||||
return res.status(HttpStatusCode.NO_CONTENT_204).end()
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import {
|
|||
doesVideoExist,
|
||||
isValidVideoIdParam
|
||||
} from '../shared/index.js'
|
||||
import { Hooks } from '@server/lib/plugins/hooks.js'
|
||||
|
||||
export const usersListValidator = [
|
||||
query('blocked')
|
||||
|
@ -334,9 +335,13 @@ export const usersAskResetPasswordValidator = [
|
|||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
const exists = await checkUserEmailExist(req.body.email, res, false)
|
||||
const { email } = await Hooks.wrapObject({
|
||||
email: req.body.email
|
||||
}, 'filter:api.users.ask-reset-password.body')
|
||||
|
||||
const exists = await checkUserEmailExist(email, res, false)
|
||||
if (!exists) {
|
||||
logger.debug('User with email %s does not exist (asking reset password).', req.body.email)
|
||||
logger.debug('User with email %s does not exist (asking reset password).', email)
|
||||
// Do not leak our emails
|
||||
return res.status(HttpStatusCode.NO_CONTENT_204).end()
|
||||
}
|
||||
|
|
|
@ -9933,7 +9933,10 @@ components:
|
|||
properties:
|
||||
total:
|
||||
type: integer
|
||||
example: 1
|
||||
description: Total threads (included deleted ones) on this video
|
||||
totalNotDeletedComments:
|
||||
type: integer
|
||||
description: Total not-deleted threads (included deleted ones) on this video
|
||||
data:
|
||||
type: array
|
||||
maxItems: 100
|
||||
|
|
Loading…
Reference in New Issue