Created server and client
This commit is contained in:
16
server/src/db.js
Normal file
16
server/src/db.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import pgPromise from 'pg-promise';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const pgp = pgPromise();
|
||||
|
||||
const connectionConfig = {
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
port: process.env.DB_PORT || 5432,
|
||||
database: process.env.DB_NAME || 'blog',
|
||||
user: process.env.DB_USER || 'postgres',
|
||||
password: process.env.DB_PASSWORD || 'postgres'
|
||||
};
|
||||
|
||||
export const db = pgp(connectionConfig);
|
||||
@@ -1,27 +1,56 @@
|
||||
// File: src/routes/auth.js
|
||||
import bcrypt from 'bcrypt';
|
||||
import { db } from '../db.js';
|
||||
|
||||
export default async function auth(fastify, options) {
|
||||
export default async function authRoutes(fastify) {
|
||||
fastify.post('/api/auth/login', async (request, reply) => {
|
||||
const { username, password } = request.body;
|
||||
|
||||
const user = await db.oneOrNone(
|
||||
'SELECT * FROM users WHERE username = $1',
|
||||
[username]
|
||||
);
|
||||
try {
|
||||
const user = await db.oneOrNone(
|
||||
'SELECT * FROM users WHERE username = $1',
|
||||
[username]
|
||||
);
|
||||
|
||||
if (!user) {
|
||||
reply.code(401).send({ error: 'Invalid credentials' });
|
||||
return;
|
||||
if (!user) {
|
||||
return reply.code(401).send({ error: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
const valid = await bcrypt.compare(password, user.password_hash);
|
||||
if (!valid) {
|
||||
return reply.code(401).send({ error: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
const token = fastify.jwt.sign({ id: user.id });
|
||||
return { token };
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.code(500).send({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
const valid = await bcrypt.compare(password, user.password_hash);
|
||||
if (!valid) {
|
||||
reply.code(401).send({ error: 'Invalid credentials' });
|
||||
return;
|
||||
// Add a test user if none exists
|
||||
fastify.post('/api/auth/setup', async (request, reply) => {
|
||||
try {
|
||||
const userExists = await db.oneOrNone('SELECT id FROM users LIMIT 1');
|
||||
|
||||
if (!userExists) {
|
||||
const password = 'admin123'; // Default password
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
const hash = await bcrypt.hash(password, salt);
|
||||
|
||||
await db.one(
|
||||
'INSERT INTO users (username, password_hash) VALUES ($1, $2) RETURNING id',
|
||||
['admin', hash]
|
||||
);
|
||||
|
||||
return { message: 'Test user created. Username: admin, Password: admin123' };
|
||||
}
|
||||
|
||||
return { message: 'Users already exist' };
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
return reply.code(500).send({ error: 'Internal server error' });
|
||||
}
|
||||
|
||||
const token = fastify.jwt.sign({ id: user.id });
|
||||
reply.send({ token });
|
||||
});
|
||||
}
|
||||
@@ -2,35 +2,63 @@ import Fastify from 'fastify';
|
||||
import cors from '@fastify/cors';
|
||||
import jwt from '@fastify/jwt';
|
||||
import multipart from '@fastify/multipart';
|
||||
import static from '@fastify/static';
|
||||
import fastifyStatic from '@fastify/static';
|
||||
import { join } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname } from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
import authRoutes from './routes/auth.js';
|
||||
|
||||
const app = Fastify({ logger: true });
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
app.register(cors, {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const app = Fastify({
|
||||
logger: true,
|
||||
ajv: {
|
||||
customOptions: {
|
||||
removeAdditional: false,
|
||||
useDefaults: true,
|
||||
coerceTypes: true,
|
||||
allErrors: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register plugins
|
||||
await app.register(cors, {
|
||||
origin: process.env.FRONTEND_URL || 'http://localhost:3000'
|
||||
});
|
||||
|
||||
app.register(jwt, {
|
||||
secret: process.env.JWT_SECRET
|
||||
await app.register(jwt, {
|
||||
secret: process.env.JWT_SECRET || 'your-super-secret-key-change-this-in-production'
|
||||
});
|
||||
|
||||
app.register(multipart);
|
||||
await app.register(multipart);
|
||||
|
||||
app.register(static, {
|
||||
root: join(fileURLToPath(import.meta.url), '../../uploads'),
|
||||
await app.register(fastifyStatic, {
|
||||
root: join(__dirname, '../uploads'),
|
||||
prefix: '/uploads/'
|
||||
});
|
||||
|
||||
app.register(import('./routes/auth.js'));
|
||||
app.register(import('./routes/posts.js'));
|
||||
app.register(import('./routes/tags.js'));
|
||||
app.register(import('./routes/images.js'));
|
||||
// Register routes
|
||||
await app.register(authRoutes);
|
||||
|
||||
// Testing route
|
||||
app.get('/', async (request, reply) => {
|
||||
return { hello: 'world' }
|
||||
});
|
||||
|
||||
// Start the server
|
||||
const start = async () => {
|
||||
try {
|
||||
await app.listen({ port: 3001 });
|
||||
await app.listen({
|
||||
port: process.env.PORT || 3001,
|
||||
host: process.env.HOST || 'localhost'
|
||||
});
|
||||
console.log(`Server listening on ${app.server.address().port}`);
|
||||
} catch (err) {
|
||||
app.log.error(err);
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user