register + login + mdp hash
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool
|
||||||
|
({
|
||||||
|
user: process.env.POSTGRES_USER,
|
||||||
|
host: process.env.POSTGRES_HOST,
|
||||||
|
database: process.env.POSTGRES_DB,
|
||||||
|
password: process.env.POSTGRES_PASSWORD,
|
||||||
|
port: 5432,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function waitForDb(retries = 10, delay = 2000)
|
||||||
|
{
|
||||||
|
for (let i = 0; i < retries; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await pool.query('SELECT 1');
|
||||||
|
console.log('Database is ready!');
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
catch (err)
|
||||||
|
{
|
||||||
|
await new Promise(r => setTimeout(r, delay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Could not connect to database after multiple attempts');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createTables()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await pool.query(`
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
username VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
password_hash TEXT NOT NULL,
|
||||||
|
email VARCHAR(100),
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS messages(
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
sender_id INT REFERENCES users(id),
|
||||||
|
received_id INT REFERENCES users(id),
|
||||||
|
content TEXT,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS friendship (
|
||||||
|
id_user1 INT NOT NULL,
|
||||||
|
id_user2 INT NOT NULL,
|
||||||
|
status VARCHAR(20) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
CHECK (id_user1 < id_user2),
|
||||||
|
PRIMARY KEY (id_user1, id_user2),
|
||||||
|
FOREIGN KEY (id_user1) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (id_user2) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
console.log('Tables created!');
|
||||||
|
}
|
||||||
|
catch (err)
|
||||||
|
{
|
||||||
|
console.error('Error creating tables:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function query(text, params)
|
||||||
|
{
|
||||||
|
return (pool.query(text, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports =
|
||||||
|
{
|
||||||
|
waitForDb,
|
||||||
|
createTables,
|
||||||
|
query
|
||||||
|
};
|
||||||
@@ -7,6 +7,8 @@ COPY package*.json ./
|
|||||||
RUN npm install
|
RUN npm install
|
||||||
RUN npm install dotenv
|
RUN npm install dotenv
|
||||||
RUN npm install pg
|
RUN npm install pg
|
||||||
|
RUN npm install bcrypt
|
||||||
|
RUN npm install jsonwebtoken
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
|||||||
+6
-70
@@ -1,81 +1,17 @@
|
|||||||
require('dotenv').config();
|
|
||||||
const { Pool } = require('pg');
|
|
||||||
|
|
||||||
const pool = new Pool
|
|
||||||
({
|
|
||||||
user: process.env.POSTGRES_USER,
|
|
||||||
host: process.env.POSTGRES_HOST,
|
|
||||||
database: process.env.POSTGRES_DB,
|
|
||||||
password: process.env.POSTGRES_PASSWORD,
|
|
||||||
port: 5432,
|
|
||||||
});
|
|
||||||
|
|
||||||
async function waitForDb(retries = 10, delay = 2000)
|
|
||||||
{
|
|
||||||
for (let i = 0; i < retries; i++)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await pool.query('SELECT 1');
|
|
||||||
console.log('Database is ready!');
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
catch (err)
|
|
||||||
{
|
|
||||||
await new Promise(r => setTimeout(r, delay));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('Could not connect to database after multiple attempts');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createTables()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await pool.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
username VARCHAR(50) UNIQUE NOT NULL,
|
|
||||||
email VARCHAR(100),
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS messages(
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
sender_id INT REFERENCES users(id),
|
|
||||||
received_id INT REFERENCES users(id),
|
|
||||||
content TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS friendship (
|
|
||||||
id_user1 INT NOT NULL,
|
|
||||||
id_user2 INT NOT NULL,
|
|
||||||
status VARCHAR(20) NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT NOW(),
|
|
||||||
CHECK (id_user1 < id_user2),
|
|
||||||
PRIMARY KEY (id_user1, id_user2),
|
|
||||||
FOREIGN KEY (id_user1) REFERENCES users(id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (id_user2) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
`);
|
|
||||||
console.log('Tables created!');
|
|
||||||
}
|
|
||||||
catch (err)
|
|
||||||
{
|
|
||||||
console.error('Error creating tables:', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
const authRouter = require('./routes/auth');
|
||||||
|
const {waitForDb, createTables} = require('./db');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
async function startServer()
|
async function startServer()
|
||||||
{
|
{
|
||||||
await waitForDb();
|
await waitForDb();
|
||||||
|
|
||||||
await createTables();
|
await createTables();
|
||||||
|
|
||||||
|
app.use('/api/auth', authRouter);
|
||||||
app.get('/api/', (req, res) => res.send('Backend running'));
|
app.get('/api/', (req, res) => res.send('Backend running'));
|
||||||
|
|
||||||
app.listen(3001, () =>
|
app.listen(3001, () =>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
module.exports = function authMiddleware(req, res, next)
|
||||||
|
{
|
||||||
|
const header = req.headers.authorization;
|
||||||
|
if (!header)
|
||||||
|
return (res.status(401).json({error: 'Missing token'}));
|
||||||
|
|
||||||
|
const token = header.split(' ')[1];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const payload = jwt.verify(token, process.env.JWT_SECRET);
|
||||||
|
req.user = payload;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
res.status(401).json({error: 'Invalid token'});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const authService = require('../services/auth');
|
||||||
|
|
||||||
|
router.post('/register', async(req, res) =>
|
||||||
|
{
|
||||||
|
const {username, password} = req.body;
|
||||||
|
if (!username || !password)
|
||||||
|
return (res.status(400).json({error: 'Missing fields'}));
|
||||||
|
|
||||||
|
const result = await authService.register(username, password);
|
||||||
|
res.status(result.status).json(result.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/login', async(req, res) =>
|
||||||
|
{
|
||||||
|
const {username, password} = req.body;
|
||||||
|
const result = await authService.login(username, password);
|
||||||
|
res.status(result.status).json(result.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
const {query} = require('../db');
|
||||||
|
|
||||||
|
async function login(username, password)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const result = await query
|
||||||
|
(
|
||||||
|
`SELECT id, password_hash FROM users WHERE username = $1`,
|
||||||
|
[username]
|
||||||
|
);
|
||||||
|
if (result.rows.length === 0)
|
||||||
|
return ({status: 401, data: {error: 'Invalid credentials'}});
|
||||||
|
|
||||||
|
const user = result.rows[0];
|
||||||
|
const match = await bcrypt.compare(password, user.password_hash);
|
||||||
|
if (!match)
|
||||||
|
return ({status: 401, data: {error: 'Invalid credentials'}});
|
||||||
|
|
||||||
|
const token = jwt.sign
|
||||||
|
(
|
||||||
|
{userId: user.id},
|
||||||
|
process.env.JWT_SECRET,
|
||||||
|
{expiresIn: '1h'}
|
||||||
|
);
|
||||||
|
|
||||||
|
return ({status: 200, data: {token}});
|
||||||
|
}
|
||||||
|
catch (err)
|
||||||
|
{
|
||||||
|
console.error(err);
|
||||||
|
return ({status: 500, data: {error: 'Server error'}});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function register(username, password)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const password_hash = await bcrypt.hash(password, 10);
|
||||||
|
await query
|
||||||
|
(
|
||||||
|
`INSERT INTO users (username, password_hash) VALUES ($1, $2)`,
|
||||||
|
[username, password_hash]
|
||||||
|
);
|
||||||
|
return ({status: 201, data: {message: 'User created'}});
|
||||||
|
}
|
||||||
|
catch (err)
|
||||||
|
{
|
||||||
|
if (err.code === '23505')
|
||||||
|
return ({status: 409, data: {error: 'Username already exists'}});
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
return ({status: 500, data: {error: 'Server error'}});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {register, login};
|
||||||
Reference in New Issue
Block a user