import express from 'express' import bcrypt from 'bcryptjs' import { pool } from '../../config/index.js' const router = express.Router() /** * Get all users. */ router.get('/', async (req, res) => { const { rows } = await pool.query('SELECT * FROM users') res.json(rows) }) /** * Create a new user. * * @param {string} name - The user's name * @param {string} email - The user's email address * @param {string} password - The user's password (must be hashed) * @param {string} role_name - The name of the role to assign to the user */ router.post('/', async (req, res) => { const { username, email, password, role_name } = req.body if (!password) { return res.status(400).send('Password is required') } try { // Hash the password using bcrypt const hashedPassword = await bcrypt.hash(password, 10) // Query for the UUID of the role by name const roleResult = await pool.query( 'SELECT id FROM roles WHERE name = $1', [role_name] ) if (roleResult.rows.length === 0) { throw new Error(`Role ${role_name} not found`) } const roleId = roleResult.rows[0].id // Insert the new user into the database const result = await pool.query( 'INSERT INTO users (username, email, password, role_id, created_at, updated_at) VALUES ($1, $2, $3, $4, NOW(), NOW()) RETURNING *', [username, email, hashedPassword, roleId] ) // Return the newly created user res.status(201).json(result.rows[0]) } catch (err) { res.status(500).send(err) } }) /** * Update an existing user. * * @param {number} id - The ID of the user to update * @param {string} name - The new name for the user * @param {string} email - The new email address for the user (optional) * @param {string} password - The new password for the user (optional, must be hashed) * @param {string} role_name - The name of the new role to assign to the user (optional) */ router.put('/:id', async (req, res) => { const { id } = req.params const { name, email, password, role_name } = req.body const client = await pool.connect() try { await client.query('BEGIN') // Query for the UUID of the role by name if provided let roleId = null if (role_name) { const roleResult = await client.query( 'SELECT id FROM roles WHERE name = $1', [role_name] ) if (roleResult.rows.length === 0) { throw new Error(`Role ${role_name} not found`) } roleId = roleResult.rows[0].id } // Update the user in the database let queryText = 'UPDATE users SET name = $1' const values = [name] if (email) { queryText += ', email = $2' values.push(email) } if (password) { queryText += ', password = $3' values.push(await bcrypt.hash(password, 10)) } if (roleId !== null) { queryText += ', role_id = $4' values.push(roleId) } queryText += ' , updated_at = NOW() WHERE id = $5 RETURNING *' values.push(id) const result = await client.query(queryText, values) // Return the updated user res.json(result.rows[0]) await client.query('COMMIT') } catch (err) { await client.query('ROLLBACK') res.status(500).send(err) } finally { client.release() } }) /** * Delete an existing user. * * @param {number} id - The ID of the user to delete */ router.delete('/:id', async (req, res) => { const { id } = req.params const client = await pool.connect() try { await client.query('BEGIN') // Delete the user from the database const result = await client.query( 'DELETE FROM users WHERE id = $1 RETURNING *', [id] ) // Return the deleted user res.json(result.rows[0]) await client.query('COMMIT') } catch (err) { await client.query('ROLLBACK') res.status(500).send(err) } finally { client.release() } }) export default router