Add plugin hook on registration

pull/2207/head
Chocobozzz 2019-10-25 13:54:32 +02:00
parent 4586328858
commit 4ce7eb71ba
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
6 changed files with 60 additions and 10 deletions

View File

@ -17,6 +17,7 @@ import { objectConverter } from '../../helpers/core-utils'
import { CONFIG, reloadConfig } from '../../initializers/config' import { CONFIG, reloadConfig } from '../../initializers/config'
import { PluginManager } from '../../lib/plugins/plugin-manager' import { PluginManager } from '../../lib/plugins/plugin-manager'
import { getThemeOrDefault } from '../../lib/plugins/theme-utils' import { getThemeOrDefault } from '../../lib/plugins/theme-utils'
import { Hooks } from '@server/lib/plugins/hooks'
const configRouter = express.Router() const configRouter = express.Router()
@ -47,7 +48,12 @@ configRouter.delete('/custom',
let serverCommit: string let serverCommit: string
async function getConfig (req: express.Request, res: express.Response) { async function getConfig (req: express.Request, res: express.Response) {
const allowed = await isSignupAllowed() const { allowed } = await Hooks.wrapPromiseFun(
isSignupAllowed,
{},
'filter:api.user.signup.allowed.result'
)
const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip) const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip)
const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME)

View File

@ -4,19 +4,19 @@ import { CONFIG } from '../initializers/config'
const isCidr = require('is-cidr') const isCidr = require('is-cidr')
async function isSignupAllowed () { async function isSignupAllowed (): Promise<{ allowed: boolean, errorMessage?: string }> {
if (CONFIG.SIGNUP.ENABLED === false) { if (CONFIG.SIGNUP.ENABLED === false) {
return false return { allowed: false }
} }
// No limit and signup is enabled // No limit and signup is enabled
if (CONFIG.SIGNUP.LIMIT === -1) { if (CONFIG.SIGNUP.LIMIT === -1) {
return true return { allowed: true }
} }
const totalUsers = await UserModel.countTotal() const totalUsers = await UserModel.countTotal()
return totalUsers < CONFIG.SIGNUP.LIMIT return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT }
} }
function isSignupAllowedForCurrentIP (ip: string) { function isSignupAllowedForCurrentIP (ip: string) {

View File

@ -35,6 +35,8 @@ import { isThemeRegistered } from '../../lib/plugins/theme-utils'
import { doesVideoExist } from '../../helpers/middlewares' import { doesVideoExist } from '../../helpers/middlewares'
import { UserRole } from '../../../shared/models/users' import { UserRole } from '../../../shared/models/users'
import { MUserDefault } from '@server/typings/models' import { MUserDefault } from '@server/typings/models'
import { Hooks } from '@server/lib/plugins/hooks'
import { isLocalVideoAccepted } from '@server/lib/moderation'
const usersAddValidator = [ const usersAddValidator = [
body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'),
@ -280,10 +282,19 @@ const usersVideoRatingValidator = [
const ensureUserRegistrationAllowed = [ const ensureUserRegistrationAllowed = [
async (req: express.Request, res: express.Response, next: express.NextFunction) => { async (req: express.Request, res: express.Response, next: express.NextFunction) => {
const allowed = await isSignupAllowed() const allowedParams = {
if (allowed === false) { body: req.body
}
const allowedResult = await Hooks.wrapPromiseFun(
isSignupAllowed,
allowedParams,
'filter:api.user.signup.allowed.result'
)
if (allowedResult.allowed === false) {
return res.status(403) return res.status(403)
.json({ error: 'User registration is not enabled or user limit is reached.' }) .json({ error: allowedResult.errorMessage || 'User registration is not enabled or user limit is reached.' })
} }
return next() return next()

View File

@ -86,6 +86,17 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
return false return false
} }
}) })
registerHook({
target: 'filter:api.user.signup.allowed.result',
handler: (result, params) => {
if (params && params.body.email.includes('jma')) {
return { allowed: false, errorMessage: 'No jma' }
}
return result
}
})
} }
async function unregister () { async function unregister () {

View File

@ -28,11 +28,12 @@ import {
getVideoWithToken, getVideoWithToken,
setDefaultVideoChannel, setDefaultVideoChannel,
waitJobs, waitJobs,
doubleFollow doubleFollow, getConfig, registerUser
} from '../../../shared/extra-utils' } from '../../../shared/extra-utils'
import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
import { VideoDetails } from '../../../shared/models/videos' import { VideoDetails } from '../../../shared/models/videos'
import { getYoutubeVideoUrl, importVideo } from '../../../shared/extra-utils/videos/video-imports' import { getYoutubeVideoUrl, importVideo } from '../../../shared/extra-utils/videos/video-imports'
import { ServerConfig } from '@shared/models'
const expect = chai.expect const expect = chai.expect
@ -187,6 +188,24 @@ describe('Test plugin filter hooks', function () {
}) })
}) })
describe('Should run filter:api.user.signup.allowed.result', function () {
it('Should run on config endpoint', async function () {
const res = await getConfig(servers[0].url)
expect((res.body as ServerConfig).signup.allowed).to.be.true
})
it('Should allow a signup', async function () {
await registerUser(servers[0].url, 'john', 'password')
})
it('Should not allow a signup', async function () {
const res = await registerUser(servers[0].url, 'jma', 'password', 403)
expect(res.body.error).to.equal('No jma')
})
})
after(async function () { after(async function () {
await cleanupTests(servers) await cleanupTests(servers)
}) })

View File

@ -29,7 +29,10 @@ export const serverFilterHookObject = {
// Filter result used to check if we need to auto blacklist a video // Filter result used to check if we need to auto blacklist a video
// (fired when a local or remote video is created or updated) // (fired when a local or remote video is created or updated)
'filter:video.auto-blacklist.result': true 'filter:video.auto-blacklist.result': true,
// Filter result used to check if a user can register on the instance
'filter:api.user.signup.allowed.result': true
} }
export type ServerFilterHookName = keyof typeof serverFilterHookObject export type ServerFilterHookName = keyof typeof serverFilterHookObject