77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import { FastifyInstance } from 'fastify';
|
|
import bcrypt from 'bcryptjs';
|
|
import { pool } from '../db.js';
|
|
|
|
export default async function authRoutes(app: FastifyInstance) {
|
|
app.post('/login', async (req, reply) => {
|
|
const { username, password } = req.body as { username: string; password: string };
|
|
|
|
const { rows: [user] } = await pool.query(
|
|
'SELECT * FROM users WHERE username = $1 AND is_active = TRUE', [username]
|
|
);
|
|
if (!user) return reply.status(401).send({ error: 'Неверный логин или пароль' });
|
|
|
|
const ok = await bcrypt.compare(password, user.password_hash);
|
|
if (!ok) return reply.status(401).send({ error: 'Неверный логин или пароль' });
|
|
|
|
await pool.query('UPDATE users SET last_seen = NOW() WHERE id = $1', [user.id]);
|
|
|
|
const token = app.jwt.sign({ id: user.id, isAdmin: user.is_admin }, { expiresIn: '30d' });
|
|
|
|
return {
|
|
token,
|
|
user: {
|
|
id: user.id,
|
|
username: user.username,
|
|
displayName: user.display_name,
|
|
avatarColor: user.avatar_color,
|
|
bio: user.bio,
|
|
isAdmin: user.is_admin,
|
|
}
|
|
};
|
|
});
|
|
|
|
app.get('/me', { preHandler: [app.authenticate] }, async (req) => {
|
|
const { id } = req.user as { id: string };
|
|
const { rows: [user] } = await pool.query(
|
|
'SELECT id, username, display_name, avatar_color, bio, phone, is_admin, last_seen FROM users WHERE id = $1', [id]
|
|
);
|
|
return {
|
|
id: user.id,
|
|
username: user.username,
|
|
displayName: user.display_name,
|
|
avatarColor: user.avatar_color,
|
|
bio: user.bio,
|
|
phone: user.phone,
|
|
isAdmin: user.is_admin,
|
|
lastSeen: user.last_seen,
|
|
};
|
|
});
|
|
|
|
app.put('/me', { preHandler: [app.authenticate] }, async (req, reply) => {
|
|
const { id } = req.user as { id: string };
|
|
const { displayName, bio, phone, password, newPassword } = req.body as any;
|
|
|
|
if (newPassword) {
|
|
const { rows: [user] } = await pool.query('SELECT password_hash FROM users WHERE id = $1', [id]);
|
|
const ok = await bcrypt.compare(password, user.password_hash);
|
|
if (!ok) return reply.status(400).send({ error: 'Неверный текущий пароль' });
|
|
const hash = await bcrypt.hash(newPassword, 10);
|
|
await pool.query('UPDATE users SET password_hash = $1 WHERE id = $2', [hash, id]);
|
|
}
|
|
|
|
await pool.query(
|
|
'UPDATE users SET display_name = COALESCE($1, display_name), bio = COALESCE($2, bio), phone = COALESCE($3, phone) WHERE id = $4',
|
|
[displayName, bio, phone, id]
|
|
);
|
|
|
|
const { rows: [user] } = await pool.query(
|
|
'SELECT id, username, display_name, avatar_color, bio, phone, is_admin FROM users WHERE id = $1', [id]
|
|
);
|
|
return {
|
|
id: user.id, username: user.username, displayName: user.display_name,
|
|
avatarColor: user.avatar_color, bio: user.bio, phone: user.phone, isAdmin: user.is_admin,
|
|
};
|
|
});
|
|
}
|