Fix: Prevent race condition in user registration

This commit is contained in:
Mirza-Samad-Ahmed-Baig
2025-07-13 14:30:09 +05:00
parent ed920bb73b
commit 23e5f7ac2d

View File

@@ -1,6 +1,6 @@
import express from 'express'; import express from 'express';
import bcrypt from 'bcrypt'; import bcrypt from 'bcrypt';
import { userDb } from '../database/db.js'; import { userDb, db } from '../database/db.js';
import { generateToken, authenticateToken } from '../middleware/auth.js'; import { generateToken, authenticateToken } from '../middleware/auth.js';
const router = express.Router(); const router = express.Router();
@@ -33,31 +33,41 @@ router.post('/register', async (req, res) => {
return res.status(400).json({ error: 'Username must be at least 3 characters, password at least 6 characters' }); return res.status(400).json({ error: 'Username must be at least 3 characters, password at least 6 characters' });
} }
// Check if users already exist (only allow one user) // Use a transaction to prevent race conditions
const hasUsers = userDb.hasUsers(); db.prepare('BEGIN').run();
if (hasUsers) { try {
return res.status(403).json({ error: 'User already exists. This is a single-user system.' }); // Check if users already exist (only allow one user)
const hasUsers = userDb.hasUsers();
if (hasUsers) {
db.prepare('ROLLBACK').run();
return res.status(403).json({ error: 'User already exists. This is a single-user system.' });
}
// Hash password
const saltRounds = 12;
const passwordHash = await bcrypt.hash(password, saltRounds);
// Create user
const user = userDb.createUser(username, passwordHash);
// Generate token
const token = generateToken(user);
// Update last login
userDb.updateLastLogin(user.id);
db.prepare('COMMIT').run();
res.json({
success: true,
user: { id: user.id, username: user.username },
token
});
} catch (error) {
db.prepare('ROLLBACK').run();
throw error;
} }
// Hash password
const saltRounds = 12;
const passwordHash = await bcrypt.hash(password, saltRounds);
// Create user
const user = userDb.createUser(username, passwordHash);
// Generate token
const token = generateToken(user);
// Update last login
userDb.updateLastLogin(user.id);
res.json({
success: true,
user: { id: user.id, username: user.username },
token
});
} catch (error) { } catch (error) {
console.error('Registration error:', error); console.error('Registration error:', error);
if (error.code === 'SQLITE_CONSTRAINT_UNIQUE') { if (error.code === 'SQLITE_CONSTRAINT_UNIQUE') {