135 lines
4.1 KiB
JavaScript
135 lines
4.1 KiB
JavaScript
if (process.stdout._handle && typeof process.stdout._handle.setBlocking === 'function') {
|
|
process.stdout._handle.setBlocking(true);
|
|
}
|
|
if (process.stderr._handle && typeof process.stderr._handle.setBlocking === 'function') {
|
|
process.stderr._handle.setBlocking(true);
|
|
}
|
|
|
|
const express = require('express');
|
|
const cors = require('cors');
|
|
const bcrypt = require('bcrypt');
|
|
const jwt = require('jsonwebtoken');
|
|
const pool = require('./db');
|
|
require('dotenv').config();
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 5000;
|
|
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
|
|
// Request logger middleware
|
|
app.use((req, res, next) => {
|
|
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
|
|
if (req.body && Object.keys(req.body).length > 0) {
|
|
const logBody = { ...req.body };
|
|
if (logBody.password) logBody.password = '[REDACTED]';
|
|
console.log(' Body:', JSON.stringify(logBody));
|
|
}
|
|
next();
|
|
});
|
|
|
|
// Middleware to verify JWT token
|
|
const authenticateToken = (req, res, next) => {
|
|
const authHeader = req.headers['authorization'];
|
|
const token = authHeader && authHeader.split(' ')[1];
|
|
|
|
if (!token) return res.status(401).json({ error: 'No token provided' });
|
|
|
|
jwt.verify(token, process.env.JWT_SECRET || 'fallback_secret', (err, user) => {
|
|
if (err) return res.status(403).json({ error: 'Invalid token' });
|
|
req.user = user;
|
|
next();
|
|
});
|
|
};
|
|
|
|
// Registration
|
|
app.post('/api/register', async (req, res) => {
|
|
try {
|
|
const { username, email, password } = req.body;
|
|
|
|
if (!username || !email || !password) {
|
|
return res.status(400).json({ error: 'All fields are required' });
|
|
}
|
|
|
|
// Check if user exists
|
|
const userExists = await pool.query('SELECT * FROM users WHERE email = $1 OR username = $2', [email, username]);
|
|
if (userExists.rows.length > 0) {
|
|
return res.status(400).json({ error: 'User already exists' });
|
|
}
|
|
|
|
// Hash password
|
|
const salt = await bcrypt.genSalt(10);
|
|
const passwordHash = await bcrypt.hash(password, salt);
|
|
|
|
// Save to DB
|
|
const newUser = await pool.query(
|
|
'INSERT INTO users (username, email, password_hash) VALUES ($1, $2, $3) RETURNING id, username, email',
|
|
[username, email, passwordHash]
|
|
);
|
|
|
|
res.status(201).json({ message: 'Registration successful', user: newUser.rows[0] });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Server error' });
|
|
}
|
|
});
|
|
|
|
// Login
|
|
app.post('/api/login', async (req, res) => {
|
|
try {
|
|
const { email, password } = req.body;
|
|
|
|
if (!email || !password) {
|
|
return res.status(400).json({ error: 'Email and password are required' });
|
|
}
|
|
|
|
// Find user
|
|
const user = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
|
|
if (user.rows.length === 0) {
|
|
return res.status(400).json({ error: 'Invalid credentials' });
|
|
}
|
|
|
|
// Check password
|
|
const validPassword = await bcrypt.compare(password, user.rows[0].password_hash);
|
|
if (!validPassword) {
|
|
return res.status(400).json({ error: 'Invalid credentials' });
|
|
}
|
|
|
|
// Create token
|
|
const token = jwt.sign(
|
|
{ id: user.rows[0].id, username: user.rows[0].username },
|
|
process.env.JWT_SECRET || 'fallback_secret',
|
|
{ expiresIn: '24h' }
|
|
);
|
|
|
|
res.json({ token, user: { id: user.rows[0].id, username: user.rows[0].username, email: user.rows[0].email } });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Server error' });
|
|
}
|
|
});
|
|
|
|
// Get user profile (protected route)
|
|
app.get('/api/profile', authenticateToken, async (req, res) => {
|
|
try {
|
|
const user = await pool.query('SELECT id, username, email, created_at FROM users WHERE id = $1', [req.user.id]);
|
|
if (user.rows.length === 0) {
|
|
return res.status(404).json({ error: 'User not found' });
|
|
}
|
|
res.json(user.rows[0]);
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Server error' });
|
|
}
|
|
});
|
|
|
|
// Verify token
|
|
app.post('/api/verify-token', authenticateToken, (req, res) => {
|
|
res.json({ valid: true, user: req.user });
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Server running on port ${PORT}`);
|
|
});
|