/**
* Бізнес-логіка автентифікації користувача.
*
* Цей модуль відповідає за реєстрацію нового користувача
* та вхід у систему через email і пароль.
*
* Під час реєстрації виконується перевірка обов’язкових полів,
* унікальності email, хешування пароля та створення базового профілю.
* Під час входу перевіряються облікові дані, а після успішної
* автентифікації формується JWT-токен для подальшого доступу
* до захищених маршрутів.
*/
const pool = require('../config/db')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
/**
* Реєструє нового користувача, створює базовий профіль і повертає JWT-токен.
*
* Перевіряє обов'язкові поля, унікальність email та мінімальну довжину пароля.
* Після успішного створення користувача автоматично створює запис у таблиці
* user_profiles і генерує токен автентифікації.
* @param {object} req HTTP-запит з email, password і name у тілі запиту.
* @param {object} res HTTP-відповідь з токеном і даними користувача.
* @returns {Promise<void>}
*/
const register = async (req, res) => {
const { email, password, name } = req.body
if(!email || !password) {
return res.status(400).json({ error: 'Email та пароль обовʼязкові' })
}
if (password.length < 6) {
return res.status(400).json({ error: 'Пароль мінімум 6 символів' })
}
try {
const existing = await pool.query(
'SELECT id FROM users WHERE email = $1', [email]
)
if (existing.rows.length > 0) {
return res.status(409).json({ error: 'Email вже використовується' })
}
const hashedPassword = await bcrypt.hash(password, 10)
const result = await pool.query(
'INSERT INTO users (email, password, name) VALUES ($1, $2, $3) RETURNING id, email, name',
[email, hashedPassword, name || null]
)
const user = result.rows[0]
await pool.query(
'INSERT INTO user_profiles (user_id) VALUES ($1)', [user.id]
)
const token = jwt.sign(
{ id: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
)
res.status(201).json({token, user})
} catch(err) {
console.error(err)
res.status(500).json({ error: 'Помилка сервера' })
}
}
/**
* Автентифікує користувача за email і паролем та повертає JWT-токен.
*
* Перевіряє наявність обов'язкових полів, шукає користувача в базі даних,
* порівнює хеш пароля, у разі успіху повертає токен і базову інформацію
* про користувача.
* @param {object} req HTTP-запит з email і password у тілі запиту.
* @param {object} res HTTP-відповідь з токеном і даними користувача.
* @returns {Promise<void>}
*/
const login = async (req, res) => {
const { email, password } = req.body
if (!email || !password) {
return res.status(400).json({ error: 'Email та пароль обовʼязкові' })
}
try {
const result = await pool.query(
'SELECT * FROM users WHERE email = $1', [email]
)
if (result.rows.length == 0) {
return res.status(401).json({ error: 'Невірний email або пароль' })
}
const user = result.rows[0]
const valid = await bcrypt.compare(password, user.password)
if(!valid) {
return res.status(401).json({ error: 'Невірний email або пароль' })
}
const token = jwt.sign(
{ id: user.id, email: user.email },
process.env.JWT_SECRET,
{expiresIn: '7d'}
)
res.json({
token,
user: { id: user.id, email: user.email, name: user.name }
})
} catch (err) {
console.error('Login error:', err)
res.status(500).json({ error: 'Помилка сервера' })
}
}
module.exports = { register, login }