diff --git a/client/src/app/core/config/config.service.ts b/client/src/app/core/config/config.service.ts
index b8cb15e84..acdc12cc6 100644
--- a/client/src/app/core/config/config.service.ts
+++ b/client/src/app/core/config/config.service.ts
@@ -10,7 +10,7 @@ export class ConfigService {
private config: ServerConfig = {
signup: {
- enabled: false
+ allowed: false
}
}
diff --git a/client/src/app/core/menu/menu.component.html b/client/src/app/core/menu/menu.component.html
index 63a1c03c5..fb4c4a6a9 100644
--- a/client/src/app/core/menu/menu.component.html
+++ b/client/src/app/core/menu/menu.component.html
@@ -14,7 +14,7 @@
-
+
Signup
diff --git a/client/src/app/core/menu/menu.component.ts b/client/src/app/core/menu/menu.component.ts
index b725f64a7..669fc6572 100644
--- a/client/src/app/core/menu/menu.component.ts
+++ b/client/src/app/core/menu/menu.component.ts
@@ -36,8 +36,8 @@ export class MenuComponent implements OnInit {
)
}
- isRegistrationEnabled () {
- return this.configService.getConfig().signup.enabled
+ isRegistrationAllowed () {
+ return this.configService.getConfig().signup.allowed
}
isUserAdmin () {
diff --git a/config/default.yaml b/config/default.yaml
index b4e7606cf..a97d3ff78 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -33,6 +33,7 @@ admin:
signup:
enabled: false
+ limit: 10 # When the limit is reached, registrations are disabled. -1 == unlimited
# If enabled, the video will be transcoded to mp4 (x264) with "faststart" flag
# Uses a lot of CPU!
diff --git a/config/test-1.yaml b/config/test-1.yaml
index e244a8797..d08a3bee6 100644
--- a/config/test-1.yaml
+++ b/config/test-1.yaml
@@ -20,3 +20,6 @@ storage:
admin:
email: 'admin1@example.com'
+
+signup:
+ limit: 4
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 3e9aa77a5..f02a2bc58 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -1,6 +1,6 @@
import * as express from 'express'
-import { CONFIG } from '../../initializers'
+import { isSignupAllowed } from '../../helpers'
import { ServerConfig } from '../../../shared'
const configRouter = express.Router()
@@ -9,12 +9,15 @@ configRouter.get('/', getConfig)
// Get the client credentials for the PeerTube front end
function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
- const json: ServerConfig = {
- signup: {
- enabled: CONFIG.SIGNUP.ENABLED
+
+ isSignupAllowed().then(allowed => {
+ const json: ServerConfig = {
+ signup: {
+ allowed
+ }
}
- }
- res.json(json)
+ res.json(json)
+ })
}
// ---------------------------------------------------------------------------
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 6c375cc5b..f50dbc9a3 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -6,7 +6,7 @@ import { logger, getFormatedObjects } from '../../helpers'
import {
authenticate,
ensureIsAdmin,
- ensureUserRegistrationEnabled,
+ ensureUserRegistrationAllowed,
usersAddValidator,
usersUpdateValidator,
usersRemoveValidator,
@@ -48,7 +48,7 @@ usersRouter.post('/',
)
usersRouter.post('/register',
- ensureUserRegistrationEnabled,
+ ensureUserRegistrationAllowed,
usersAddValidator,
createUser
)
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts
index 9c08afb71..f326210f3 100644
--- a/server/helpers/utils.ts
+++ b/server/helpers/utils.ts
@@ -1,6 +1,8 @@
import * as express from 'express'
+import * as Promise from 'bluebird'
import { pseudoRandomBytesPromise } from './core-utils'
+import { CONFIG, database as db } from '../initializers'
import { ResultList } from '../../shared'
function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) {
@@ -30,10 +32,26 @@ function getFormatedObjects (objects: T[], object
return res
}
+function isSignupAllowed () {
+ if (CONFIG.SIGNUP.ENABLED === false) {
+ return Promise.resolve(false)
+ }
+
+ // No limit and signup is enabled
+ if (CONFIG.SIGNUP.LIMIT === -1) {
+ return Promise.resolve(true)
+ }
+
+ return db.User.countTotal().then(totalUsers => {
+ return totalUsers < CONFIG.SIGNUP.LIMIT
+ })
+}
+
// ---------------------------------------------------------------------------
export {
badRequest,
generateRandomString,
- getFormatedObjects
+ getFormatedObjects,
+ isSignupAllowed
}
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 928a3f570..314a05ab7 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -76,7 +76,8 @@ const CONFIG = {
EMAIL: config.get('admin.email')
},
SIGNUP: {
- ENABLED: config.get('signup.enabled')
+ ENABLED: config.get('signup.enabled'),
+ LIMIT: config.get('signup.limit')
},
TRANSCODING: {
ENABLED: config.get('transcoding.enabled'),
diff --git a/server/middlewares/config.ts b/server/middlewares/config.ts
deleted file mode 100644
index 1481e66cc..000000000
--- a/server/middlewares/config.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'express-validator'
-import * as express from 'express'
-
-import { CONFIG } from '../initializers'
-
-function ensureUserRegistrationEnabled (req: express.Request, res: express.Response, next: express.NextFunction) {
- const registrationEnabled = CONFIG.SIGNUP.ENABLED
-
- if (registrationEnabled === true) {
- return next()
- }
-
- return res.status(400).send('User registration is not enabled.')
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- ensureUserRegistrationEnabled
-}
diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts
index 9a3f849a7..d71dd2452 100644
--- a/server/middlewares/index.ts
+++ b/server/middlewares/index.ts
@@ -1,6 +1,5 @@
export * from './validators'
export * from './admin'
-export * from './config'
export * from './oauth'
export * from './pagination'
export * from './pods'
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 38f8aed5b..71e529872 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -5,7 +5,7 @@ import * as validator from 'validator'
import { database as db } from '../../initializers/database'
import { checkErrors } from './utils'
-import { logger } from '../../helpers'
+import { isSignupAllowed, logger } from '../../helpers'
import { VideoInstance } from '../../models'
function usersAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
@@ -88,11 +88,22 @@ function usersVideoRatingValidator (req: express.Request, res: express.Response,
})
}
+function ensureUserRegistrationAllowed (req: express.Request, res: express.Response, next: express.NextFunction) {
+ isSignupAllowed().then(allowed => {
+ if (allowed === false) {
+ return res.status(403).send('User registration is not enabled or user limit is reached.')
+ }
+
+ return next()
+ })
+}
+
// ---------------------------------------------------------------------------
export {
usersAddValidator,
usersRemoveValidator,
usersUpdateValidator,
- usersVideoRatingValidator
+ usersVideoRatingValidator,
+ ensureUserRegistrationAllowed
}
diff --git a/server/tests/api/check-params/users.js b/server/tests/api/check-params/users.js
index 2c1189f7a..9e7115da1 100644
--- a/server/tests/api/check-params/users.js
+++ b/server/tests/api/check-params/users.js
@@ -513,7 +513,13 @@ describe('Test users API validators', function () {
password: 'my super password 4'
}
- requestsUtils.makePostBodyRequest(serverWithRegistrationDisabled.url, registrationPath, serverWithRegistrationDisabled.accessToken, data, done, 400)
+ requestsUtils.makePostBodyRequest(serverWithRegistrationDisabled.url, registrationPath, serverWithRegistrationDisabled.accessToken, data, done, 403)
+ })
+ })
+
+ describe('When registering multiple users on a server with users limit', function () {
+ it('Should fail when after 3 registrations', function (done) {
+ usersUtils.registerUser(server.url, 'user42', 'super password', 403, done)
})
})
diff --git a/server/tests/api/config.js b/server/tests/api/config.js
index e79e12823..f2c00f85a 100644
--- a/server/tests/api/config.js
+++ b/server/tests/api/config.js
@@ -8,6 +8,7 @@ const series = require('async/series')
const serversUtils = require('../utils/servers')
const configUtils = require('../utils/config')
+const usersUtils = require('../utils/users')
describe('Test config', function () {
let server = null
@@ -28,18 +29,51 @@ describe('Test config', function () {
], done)
})
- it('Should have a correct config', function (done) {
+ it('Should have a correct config on a server with registration enabled', function (done) {
configUtils.getConfig(server.url, function (err, res) {
if (err) throw err
const data = res.body
- expect(data.signup.enabled).to.be.truthy
+ expect(data.signup.allowed).to.be.truthy
done()
})
})
+ it('Should have a correct config on a server with registration enabled and a users limit', function (done) {
+ series([
+ function (next) {
+ usersUtils.registerUser(server.url, 'user1', 'super password', done)
+ },
+
+ function (next) {
+ usersUtils.registerUser(server.url, 'user2', 'super password', done)
+ },
+
+ function (next) {
+ usersUtils.registerUser(server.url, 'user3', 'super password', done)
+ },
+
+ function (next) {
+ usersUtils.registerUser(server.url, 'user4', 'super password', done)
+ }
+
+ ], function (err) {
+ if (err) throw err
+
+ configUtils.getConfig(server.url, function (err, res) {
+ if (err) throw err
+
+ const data = res.body
+
+ expect(data.signup.allowed).to.be.truthy
+
+ done()
+ })
+ })
+ })
+
after(function (done) {
process.kill(-server.app.pid)
diff --git a/shared/models/server-config.model.ts b/shared/models/server-config.model.ts
index a39156963..aab842905 100644
--- a/shared/models/server-config.model.ts
+++ b/shared/models/server-config.model.ts
@@ -1,5 +1,5 @@
export interface ServerConfig {
signup: {
- enabled: boolean
+ allowed: boolean
}
}