diff --git a/backend/src/routes/authRoutes.js b/backend/src/routes/authRoutes.js index 079b48a..3c48651 100644 --- a/backend/src/routes/authRoutes.js +++ b/backend/src/routes/authRoutes.js @@ -323,6 +323,76 @@ router.post('/admin/users/:userId/reset-password', authenticateToken, requireMan } }); +// Public signup endpoint +router.post('/signup', [ + body('username').isLength({ min: 3 }).withMessage('Username must be at least 3 characters'), + body('email').isEmail().withMessage('Valid email is required'), + body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters') +], async (req, res) => { + try { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + + const { username, email, password } = req.body; + + // Check if user already exists + const existingUser = await prisma.user.findFirst({ + where: { + OR: [ + { username }, + { email } + ] + } + }); + + if (existingUser) { + return res.status(409).json({ error: 'Username or email already exists' }); + } + + // Hash password + const passwordHash = await bcrypt.hash(password, 12); + + // Create user with default 'user' role + const user = await prisma.user.create({ + data: { + username, + email, + passwordHash, + role: 'user' + }, + select: { + id: true, + username: true, + email: true, + role: true, + isActive: true, + createdAt: true + } + }); + + console.log(`New user registered: ${user.username} (${user.email})`); + + // Generate token for immediate login + const token = generateToken(user.id); + + res.status(201).json({ + message: 'Account created successfully', + token, + user: { + id: user.id, + username: user.username, + email: user.email, + role: user.role + } + }); + } catch (error) { + console.error('Signup error:', error); + res.status(500).json({ error: 'Failed to create account' }); + } +}); + // Login router.post('/login', [ body('username').notEmpty().withMessage('Username is required'),