Add plugin hook on registration
authorChocobozzz <me@florianbigard.com>
Fri, 25 Oct 2019 11:54:32 +0000 (13:54 +0200)
committerChocobozzz <me@florianbigard.com>
Fri, 25 Oct 2019 11:54:32 +0000 (13:54 +0200)
server/controllers/api/config.ts
server/helpers/signup.ts
server/middlewares/validators/users.ts
server/tests/fixtures/peertube-plugin-test/main.js
server/tests/plugins/filter-hooks.ts
shared/models/plugins/server-hook.model.ts

index 39a124fc5382dd7efa08406a00885f0c6afb10c7..113c1e9dba8f1af4d96253c5775c0524622eb397 100644 (file)
@@ -17,6 +17,7 @@ import { objectConverter } from '../../helpers/core-utils'
 import { CONFIG, reloadConfig } from '../../initializers/config'
 import { PluginManager } from '../../lib/plugins/plugin-manager'
 import { getThemeOrDefault } from '../../lib/plugins/theme-utils'
+import { Hooks } from '@server/lib/plugins/hooks'
 
 const configRouter = express.Router()
 
@@ -47,7 +48,12 @@ configRouter.delete('/custom',
 let serverCommit: string
 
 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 defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME)
 
index 5eb56b3cf6c2779e065b90edbc89aef45a360721..7c73f7c5c02efcd8358a13bcef70a670e6c80baa 100644 (file)
@@ -4,19 +4,19 @@ import { CONFIG } from '../initializers/config'
 
 const isCidr = require('is-cidr')
 
-async function isSignupAllowed () {
+async function isSignupAllowed (): Promise<{ allowed: boolean, errorMessage?: string }> {
   if (CONFIG.SIGNUP.ENABLED === false) {
-    return false
+    return { allowed: false }
   }
 
   // No limit and signup is enabled
   if (CONFIG.SIGNUP.LIMIT === -1) {
-    return true
+    return { allowed: true }
   }
 
   const totalUsers = await UserModel.countTotal()
 
-  return totalUsers < CONFIG.SIGNUP.LIMIT
+  return { allowed: totalUsers < CONFIG.SIGNUP.LIMIT }
 }
 
 function isSignupAllowedForCurrentIP (ip: string) {
index 804d1410ea10db7f23a059aa472de57bd4588645..8615de4065eb05516f7fc5174dde53aaaa4c47c8 100644 (file)
@@ -35,6 +35,8 @@ import { isThemeRegistered } from '../../lib/plugins/theme-utils'
 import { doesVideoExist } from '../../helpers/middlewares'
 import { UserRole } from '../../../shared/models/users'
 import { MUserDefault } from '@server/typings/models'
+import { Hooks } from '@server/lib/plugins/hooks'
+import { isLocalVideoAccepted } from '@server/lib/moderation'
 
 const usersAddValidator = [
   body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'),
@@ -280,10 +282,19 @@ const usersVideoRatingValidator = [
 
 const ensureUserRegistrationAllowed = [
   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
-    const allowed = await isSignupAllowed()
-    if (allowed === false) {
+    const allowedParams = {
+      body: req.body
+    }
+
+    const allowedResult = await Hooks.wrapPromiseFun(
+      isSignupAllowed,
+      allowedParams,
+      'filter:api.user.signup.allowed.result'
+    )
+
+    if (allowedResult.allowed === false) {
       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()
index 7c53f6afe49dcafb78804525d376c1e9d6d6f55a..055884d29fbb0f312b83051951b1386904e00bc3 100644 (file)
@@ -86,6 +86,17 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
       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 () {
index ec0679b04f3d1d8f607ea89610d4fa7f85e6e659..b2436fb9e47c5cc321aaed62379e16942dd31dc4 100644 (file)
@@ -28,11 +28,12 @@ import {
   getVideoWithToken,
   setDefaultVideoChannel,
   waitJobs,
-  doubleFollow
+  doubleFollow, getConfig, registerUser
 } from '../../../shared/extra-utils'
 import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
 import { VideoDetails } from '../../../shared/models/videos'
 import { getYoutubeVideoUrl, importVideo } from '../../../shared/extra-utils/videos/video-imports'
+import { ServerConfig } from '@shared/models'
 
 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 () {
     await cleanupTests(servers)
   })
index 32c7f4688906d9eca48dddc2492d2c5d4d725ec9..41ee28097f7dbd3f64bf0e3a286e31b1fbf384d7 100644 (file)
@@ -29,7 +29,10 @@ export const serverFilterHookObject = {
 
   // Filter result used to check if we need to auto blacklist a video
   // (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