Files
web-chat/index.js
2024-08-22 17:56:32 +02:00

189 lines
5.8 KiB
JavaScript

const express = require('express');
const session = require('express-session');
const port = 3000;
const app = express();
const cookieParser = require('cookie-parser');
const path = require('path');
const { insertUser, isUserExists, client } = require('./backend/db.js');
const bcrypt = require('bcrypt');
const saltRounds = 10;
const { Server } = require('socket.io');
const { createServer } = require('node:http');
const server = createServer(app);
const io = new Server(server);
const jwt = require('jsonwebtoken');
const {decode} = require("jsonwebtoken");
const jwtSecret = process.env.JWT_SECRET;
require('dotenv').config();
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/static', express.static('frontend'));
app.use('/socket.io', express.static('node_modules/socket.io/client-dist'));
app.use(session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
maxAge: 30 * 24 * 60 * 60 * 1000 //30 days
}
}));
// auth login API
app.post('/auth/login', async (req, res) => {
await loginUser(req, res);
});
// auth signup API
app.post('/auth/signup', async (req, res) => {
await signupUser(req, res);
});
// serving the login page
app.get('/login', (req, res) => {
const token = req.cookies.token;
if (token) {
res.json({ Error: 'Already logged in' });
} else {
res.sendFile(path.join(__dirname, '/frontend/routes/login.html'));
}
});
// serving the signup page
app.get('/signup', (req, res) => {
const token = req.cookies.token;
if(token){
res.json({Error: 'Already logged in'});
} else
res.sendFile(path.join(__dirname, '/frontend/routes/signup.html'));
});
app.get('/auth/user', (req, res) => {
const token = req.cookies.token;
if(token) {
jwt.verify(token, jwtSecret, (err, user) => {
if(err) {
return res.status(403).send('Unauthorized');
} else {
const username = user.username;
res.json({username});
}
});
}
});
// serving the chat page if logged in
app.get('/', (req, res) => {
const token = req.cookies.token;
if (token) {
jwt.verify(token, jwtSecret, (err, user) => {
if (err) {
return res.status(403).send('Unauthorized');
} else {
const username = user.username;
res.sendFile(path.join(__dirname, '/frontend/routes/chat.html'));
// socket io connection
io.on('connection', (socket) => {
console.log(username + ' connected');
// disconnect event
socket.on('disconnect', () => {
console.log(username + 'have disconnected');
});
// chat message event
socket.on('chat message', (msg) => {
const message = username + ': ' + msg;
console.log(message);
io.emit('chat message', message);
});
});
}
});
} else {
res.redirect('/login');
}
});
// run server
server.listen(port, () => {
console.log(`Chat app listening on port ${port}`);
});
// signup function
async function signupUser(req, res) {
let username = req.body.username.trim();
let password = req.body.password.trim();
try {
// Check if user exists
const exists = await isUserExists(username);
if (exists) {
console.log('User already exists');
return res.status(500).send('User already exists!');
}
// Hash password
const salt = await bcrypt.genSalt(saltRounds);
const hash = await bcrypt.hash(password, salt);
// Insert user
await insertUser(username, hash);
return res.status(200).send("Account successfully created <a href=/login>Login screen</a>");
} catch (err) {
console.error('Error inserting data:', err);
return res.status(500).send('Error inserting data');
}
}
// login function
async function loginUser(req, res) {
let username = req.body.username.trim();
let password = req.body.password.trim();
if (username && password) {
try {
const result = await client.query('SELECT * FROM accounts WHERE username = $1', [username]);
// check if user exists
if (result.rows.length > 0) {
// Compare password
const match = await bcrypt.compare(password, result.rows[0].password);
if (match) {
const token = jwt.sign({ username }, jwtSecret, {
expiresIn: '30d' // token expires in 30 days
});
res.cookie('token', token, {httpOnly: true});
req.session.loggedin = true;
req.session.username = username;
res.send(`
<p>Login successful!</p>
<p>Redirecting to chat...</p>
<script>
setTimeout(() => {
window.location.href = '/';
}, 1500);
</script>
`);
} else {
res.send('Incorrect Username or Password!');
}
} else {
res.send('Incorrect Username or Password!');
}
} catch (error) {
console.error('Error executing query', error);
res.status(500).send('Error executing query');
}
} else {
res.send('Please enter Username and Password!');
}
res.end();
}