Add ability to limit user registrations
This commit is contained in:
parent
3d09cdbf90
commit
291e8d3eed
|
@ -10,7 +10,7 @@ export class ConfigService {
|
||||||
|
|
||||||
private config: ServerConfig = {
|
private config: ServerConfig = {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: false
|
allowed: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a *ngIf="!isLoggedIn && isRegistrationEnabled()" routerLink="/signup" routerLinkActive="active">
|
<a *ngIf="!isLoggedIn && isRegistrationAllowed()" routerLink="/signup" routerLinkActive="active">
|
||||||
<span class="hidden-xs glyphicon glyphicon-user"></span>
|
<span class="hidden-xs glyphicon glyphicon-user"></span>
|
||||||
Signup
|
Signup
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -36,8 +36,8 @@ export class MenuComponent implements OnInit {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
isRegistrationEnabled () {
|
isRegistrationAllowed () {
|
||||||
return this.configService.getConfig().signup.enabled
|
return this.configService.getConfig().signup.allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
isUserAdmin () {
|
isUserAdmin () {
|
||||||
|
|
|
@ -33,6 +33,7 @@ admin:
|
||||||
|
|
||||||
signup:
|
signup:
|
||||||
enabled: false
|
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
|
# If enabled, the video will be transcoded to mp4 (x264) with "faststart" flag
|
||||||
# Uses a lot of CPU!
|
# Uses a lot of CPU!
|
||||||
|
|
|
@ -20,3 +20,6 @@ storage:
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
email: 'admin1@example.com'
|
email: 'admin1@example.com'
|
||||||
|
|
||||||
|
signup:
|
||||||
|
limit: 4
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { CONFIG } from '../../initializers'
|
import { isSignupAllowed } from '../../helpers'
|
||||||
import { ServerConfig } from '../../../shared'
|
import { ServerConfig } from '../../../shared'
|
||||||
|
|
||||||
const configRouter = express.Router()
|
const configRouter = express.Router()
|
||||||
|
@ -9,12 +9,15 @@ configRouter.get('/', getConfig)
|
||||||
|
|
||||||
// Get the client credentials for the PeerTube front end
|
// Get the client credentials for the PeerTube front end
|
||||||
function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
|
function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
const json: ServerConfig = {
|
|
||||||
signup: {
|
isSignupAllowed().then(allowed => {
|
||||||
enabled: CONFIG.SIGNUP.ENABLED
|
const json: ServerConfig = {
|
||||||
|
signup: {
|
||||||
|
allowed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
res.json(json)
|
||||||
res.json(json)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { logger, getFormatedObjects } from '../../helpers'
|
||||||
import {
|
import {
|
||||||
authenticate,
|
authenticate,
|
||||||
ensureIsAdmin,
|
ensureIsAdmin,
|
||||||
ensureUserRegistrationEnabled,
|
ensureUserRegistrationAllowed,
|
||||||
usersAddValidator,
|
usersAddValidator,
|
||||||
usersUpdateValidator,
|
usersUpdateValidator,
|
||||||
usersRemoveValidator,
|
usersRemoveValidator,
|
||||||
|
@ -48,7 +48,7 @@ usersRouter.post('/',
|
||||||
)
|
)
|
||||||
|
|
||||||
usersRouter.post('/register',
|
usersRouter.post('/register',
|
||||||
ensureUserRegistrationEnabled,
|
ensureUserRegistrationAllowed,
|
||||||
usersAddValidator,
|
usersAddValidator,
|
||||||
createUser
|
createUser
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
import * as Promise from 'bluebird'
|
||||||
|
|
||||||
import { pseudoRandomBytesPromise } from './core-utils'
|
import { pseudoRandomBytesPromise } from './core-utils'
|
||||||
|
import { CONFIG, database as db } from '../initializers'
|
||||||
import { ResultList } from '../../shared'
|
import { ResultList } from '../../shared'
|
||||||
|
|
||||||
function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) {
|
function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
@ -30,10 +32,26 @@ function getFormatedObjects<U, T extends FormatableToJSON> (objects: T[], object
|
||||||
return res
|
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 {
|
export {
|
||||||
badRequest,
|
badRequest,
|
||||||
generateRandomString,
|
generateRandomString,
|
||||||
getFormatedObjects
|
getFormatedObjects,
|
||||||
|
isSignupAllowed
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,8 @@ const CONFIG = {
|
||||||
EMAIL: config.get<string>('admin.email')
|
EMAIL: config.get<string>('admin.email')
|
||||||
},
|
},
|
||||||
SIGNUP: {
|
SIGNUP: {
|
||||||
ENABLED: config.get<boolean>('signup.enabled')
|
ENABLED: config.get<boolean>('signup.enabled'),
|
||||||
|
LIMIT: config.get<number>('signup.limit')
|
||||||
},
|
},
|
||||||
TRANSCODING: {
|
TRANSCODING: {
|
||||||
ENABLED: config.get<boolean>('transcoding.enabled'),
|
ENABLED: config.get<boolean>('transcoding.enabled'),
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
export * from './validators'
|
export * from './validators'
|
||||||
export * from './admin'
|
export * from './admin'
|
||||||
export * from './config'
|
|
||||||
export * from './oauth'
|
export * from './oauth'
|
||||||
export * from './pagination'
|
export * from './pagination'
|
||||||
export * from './pods'
|
export * from './pods'
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as validator from 'validator'
|
||||||
|
|
||||||
import { database as db } from '../../initializers/database'
|
import { database as db } from '../../initializers/database'
|
||||||
import { checkErrors } from './utils'
|
import { checkErrors } from './utils'
|
||||||
import { logger } from '../../helpers'
|
import { isSignupAllowed, logger } from '../../helpers'
|
||||||
import { VideoInstance } from '../../models'
|
import { VideoInstance } from '../../models'
|
||||||
|
|
||||||
function usersAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
|
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 {
|
export {
|
||||||
usersAddValidator,
|
usersAddValidator,
|
||||||
usersRemoveValidator,
|
usersRemoveValidator,
|
||||||
usersUpdateValidator,
|
usersUpdateValidator,
|
||||||
usersVideoRatingValidator
|
usersVideoRatingValidator,
|
||||||
|
ensureUserRegistrationAllowed
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,7 +513,13 @@ describe('Test users API validators', function () {
|
||||||
password: 'my super password 4'
|
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)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ const series = require('async/series')
|
||||||
|
|
||||||
const serversUtils = require('../utils/servers')
|
const serversUtils = require('../utils/servers')
|
||||||
const configUtils = require('../utils/config')
|
const configUtils = require('../utils/config')
|
||||||
|
const usersUtils = require('../utils/users')
|
||||||
|
|
||||||
describe('Test config', function () {
|
describe('Test config', function () {
|
||||||
let server = null
|
let server = null
|
||||||
|
@ -28,18 +29,51 @@ describe('Test config', function () {
|
||||||
], done)
|
], 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) {
|
configUtils.getConfig(server.url, function (err, res) {
|
||||||
if (err) throw err
|
if (err) throw err
|
||||||
|
|
||||||
const data = res.body
|
const data = res.body
|
||||||
|
|
||||||
expect(data.signup.enabled).to.be.truthy
|
expect(data.signup.allowed).to.be.truthy
|
||||||
|
|
||||||
done()
|
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) {
|
after(function (done) {
|
||||||
process.kill(-server.app.pid)
|
process.kill(-server.app.pid)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export interface ServerConfig {
|
export interface ServerConfig {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: boolean
|
allowed: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue