Example Input
task_type: API Endpoint, tech_stack: Node.js + Express + PostgreSQL, task_description: Build a POST /api/users/register endpoint that accepts email and password, hashes the password with bcrypt, saves the user to the database, and returns a signed JWT on success.
Example Output
## Understanding the Task
We need a registration endpoint that securely handles user credentials: validate input, hash the password, persist the user, and return an auth token. Key concerns are input sanitization, bcrypt cost factor, duplicate email handling, and JWT expiry.
## Plan
- Validate email format and password strength before touching the DB
- Use bcrypt with cost factor 12 (balance of security vs. latency)
- Wrap DB insert in try/catch to detect unique constraint violations
- Sign JWT with HS256, include userId and email in payload, expire in 7d
- Return 201 on success, 409 on duplicate email, 400 on invalid input
```js
// routes/auth.js
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const { pool } = require('../db');
const router = express.Router();
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
router.post('/register', async (req, res) => {
const { email, password } = req.body;
if (!email || !EMAIL_REGEX.test(email)) {
return res.status(400).json({ error: 'Valid email required' });
}
if (!password || password.length < 8) {
return res.status(400).json({ error: 'Password must be at least 8 characters' });
}
try {
const hash = await bcrypt.hash(password, 12);
const result = await pool.query(
'INSERT INTO users (email, password_hash) VALUES ($1, $2) RETURNING id, email',
[email.toLowerCase(), hash]
);
const user = result.rows[0];
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
res.status(201).json({ token });
} catch (err) {
if (err.code === '23505') {
return res.status(409).json({ error: 'Email already registered' });
}
console.error('Registration error:', err);
res.status(500).json({ error: 'Internal server error' });
}
});
module.exports = router;
```
## Tests
```js
describe('POST /api/users/register', () => {
it('returns 201 and token for valid input', async () => { ... });
it('returns 409 when email already exists', async () => { ... });
it('returns 400 for missing password', async () => { ... });
it('returns 400 for malformed email', async () => { ... });
});
```
## Review Checklist
- [x] JWT_SECRET sourced from env, never hardcoded
- [x] Email normalized to lowercase before insert
- [x] bcrypt cost 12 — production-appropriate
- [x] Duplicate key error caught explicitly (pg error code 23505)
- [x] No stack traces leaked to client