Add max user registration limit
- Parse MAX_USERS from env in registrationConfig - Count total users with new UserRepository.countUsers() - Enforce registration cap in the signup flow - Expose MAX_USERS in docker-compose and env example - Bump frontend version to 2.1.2
This commit is contained in:
@@ -22,6 +22,9 @@ CORS_ORIGIN=http://localhost:80
|
||||
|
||||
# User Registration
|
||||
ALLOW_REGISTRATION=true
|
||||
# Maximum number of users allowed to register (leave empty for unlimited)
|
||||
# Only applies if ALLOW_REGISTRATION is true
|
||||
MAX_USERS=50
|
||||
|
||||
# Rate Limiting (optional - default: 100 requests per 15 minutes)
|
||||
# RATE_LIMIT_WINDOW defines the time window in MINUTES
|
||||
|
||||
@@ -27,7 +27,8 @@ export const serverConfig = {
|
||||
}
|
||||
|
||||
export const registrationConfig = {
|
||||
allowRegistration: process.env.ALLOW_REGISTRATION !== 'false'
|
||||
allowRegistration: process.env.ALLOW_REGISTRATION !== 'false',
|
||||
maxUsers: process.env.MAX_USERS ? parseInt(process.env.MAX_USERS) : null
|
||||
}
|
||||
|
||||
export const rateLimitConfig = {
|
||||
|
||||
@@ -158,6 +158,20 @@ export class UserRepository extends Repository {
|
||||
return result.rowCount > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Count total users in the system
|
||||
*/
|
||||
async countUsers() {
|
||||
try {
|
||||
const result = await dbManager.query(
|
||||
`SELECT COUNT(*) as count FROM ${this.tableName}`
|
||||
)
|
||||
return parseInt(result.rows[0].count, 10) || 0
|
||||
} catch (error) {
|
||||
throw new Error('Failed to count users')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user statistics
|
||||
*/
|
||||
|
||||
@@ -126,17 +126,28 @@ export default async function authRoutes(fastify, options) {
|
||||
config: { rateLimit: { max: 3, timeWindow: '15 minutes' } }
|
||||
},
|
||||
async (request, reply) => {
|
||||
try {
|
||||
// Check if registration is allowed
|
||||
if (!registrationConfig.allowRegistration) {
|
||||
return reply.code(403).send({
|
||||
error: 'Registration Disabled',
|
||||
message: 'User registration is currently disabled'
|
||||
})
|
||||
}
|
||||
try {
|
||||
// Check if registration is allowed
|
||||
if (!registrationConfig.allowRegistration) {
|
||||
return reply.code(403).send({
|
||||
error: 'Registration Disabled',
|
||||
message: 'User registration is currently disabled'
|
||||
})
|
||||
}
|
||||
|
||||
// LAYER 1: Schema validation
|
||||
const validatedData = registerSchema.parse(request.body)
|
||||
// Check if max user limit has been reached (only if allowRegistration is true and MAX_USERS is set)
|
||||
if (registrationConfig.allowRegistration && registrationConfig.maxUsers) {
|
||||
const userCount = await userRepo.countUsers()
|
||||
if (userCount >= registrationConfig.maxUsers) {
|
||||
return reply.code(403).send({
|
||||
error: 'Registration Disabled',
|
||||
message: 'User registration limit has been reached'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// LAYER 1: Schema validation
|
||||
const validatedData = registerSchema.parse(request.body)
|
||||
|
||||
// LAYER 2: Business logic validation
|
||||
// Check username uniqueness
|
||||
|
||||
@@ -338,6 +338,7 @@ services:
|
||||
- CORS_ORIGIN=\${CORS_ORIGIN:-https://yourdomain.com}
|
||||
- LOG_LEVEL=\${LOG_LEVEL:-warn}
|
||||
- ALLOW_REGISTRATION=\${ALLOW_REGISTRATION:-false}
|
||||
- MAX_USERS=\${MAX_USERS:-}
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
|
||||
@@ -70,6 +70,7 @@ services:
|
||||
- CORS_ORIGIN=${CORS_ORIGIN:-http://localhost}
|
||||
- LOG_LEVEL=${LOG_LEVEL:-info}
|
||||
- ALLOW_REGISTRATION=${ALLOW_REGISTRATION:-true}
|
||||
- MAX_USERS=${MAX_USERS:-}
|
||||
volumes:
|
||||
- ./backend/src:/app/src
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.1.1
|
||||
2.1.2
|
||||
|
||||
Reference in New Issue
Block a user