Remove unused files and improve code clarity
Deleted obsolete files, including icon.png and index.html. Refactored JavaScript code in signup.js and socket.js for better readability by adjusting indentation and format. Updated environment variables in .env and streamlined several routes and functions in index.js.
This commit is contained in:
4
.env
4
.env
@@ -5,6 +5,6 @@ PG_PASSWORD=jebanechaslo
|
||||
PG_DATABASE=webchat
|
||||
|
||||
SESSION_SECRET=changeme
|
||||
JWT_SECRET=changeme
|
||||
JWT_SECRET=jkldfsjklsdfjkl
|
||||
|
||||
APP_PORT=3000
|
||||
APP_PORT=4000
|
||||
|
||||
123
backend/db.js
123
backend/db.js
@@ -1,31 +1,30 @@
|
||||
const {Client} = require('pg');
|
||||
require('dotenv').config();
|
||||
const { Client } = require("pg");
|
||||
require("dotenv").config();
|
||||
|
||||
const db = new Client({
|
||||
user: process.env.PG_USER,
|
||||
password: process.env.PG_PASSWORD,
|
||||
database: process.env.PG_DATABASE,
|
||||
host: process.env.PG_HOST,
|
||||
port: process.env.PG_PORT
|
||||
const db = new Client({
|
||||
user: process.env.PG_USER,
|
||||
password: process.env.PG_PASSWORD,
|
||||
database: process.env.PG_DATABASE,
|
||||
host: process.env.PG_HOST,
|
||||
port: process.env.PG_PORT,
|
||||
});
|
||||
|
||||
// create connection to database
|
||||
db.connect()
|
||||
.then(() => {
|
||||
console.log('Successfully connected to database');
|
||||
// if connection is succesful create tables
|
||||
createTables()
|
||||
.catch((err) => {
|
||||
console.error('Error creating tables:', err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Error connecting to database: ', err);
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Successfully connected to database");
|
||||
// if connection is successful create tables
|
||||
createTables().catch((err) => {
|
||||
console.error("Error creating tables:", err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error connecting to database: ", err);
|
||||
});
|
||||
async function createTables() {
|
||||
try {
|
||||
// Create accounts table
|
||||
await db.query(`
|
||||
try {
|
||||
// Create accounts table
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(255) UNIQUE NOT NULL,
|
||||
@@ -33,8 +32,8 @@ async function createTables() {
|
||||
)
|
||||
`);
|
||||
|
||||
// Create messages table
|
||||
await db.query(`
|
||||
// Create messages table
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id SERIAL PRIMARY KEY,
|
||||
content TEXT NOT NULL,
|
||||
@@ -43,8 +42,8 @@ async function createTables() {
|
||||
)
|
||||
`);
|
||||
|
||||
// Create contacts table
|
||||
await db.query(`
|
||||
// Create contacts table
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS contacts (
|
||||
username TEXT NOT NULL,
|
||||
contact TEXT NOT NULL,
|
||||
@@ -52,59 +51,57 @@ async function createTables() {
|
||||
)
|
||||
`);
|
||||
|
||||
console.log('Tables created successfully');
|
||||
} catch (err) {
|
||||
console.error('Error creating tables:', err);
|
||||
throw err;
|
||||
}
|
||||
console.log("Tables created successfully");
|
||||
} catch (err) {
|
||||
console.error("Error creating tables:", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// function for checking if user exists
|
||||
async function isUserExists(username) {
|
||||
try {
|
||||
const query = 'SELECT COUNT(*) FROM accounts WHERE username = $1';
|
||||
const result = await db.query(query, [username]);
|
||||
return result.rows[0].count > 0;
|
||||
} catch (err) {
|
||||
console.error('Error checking username:', err);
|
||||
throw err;
|
||||
}
|
||||
try {
|
||||
const query = "SELECT COUNT(*) FROM accounts WHERE username = $1";
|
||||
const result = await db.query(query, [username]);
|
||||
return result.rows[0].count > 0;
|
||||
} catch (err) {
|
||||
console.error("Error checking username:", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// function for signup
|
||||
// function for putting user data to database
|
||||
async function insertUser(username, password){
|
||||
const query = `
|
||||
async function insertUser(username, password) {
|
||||
const query = `
|
||||
INSERT INTO accounts (username, password)
|
||||
VALUES ($1, $2)
|
||||
RETURNING *;
|
||||
`;
|
||||
|
||||
try {
|
||||
const signupData = await db.query(query, [username, password]);
|
||||
console.log('Account created:', signupData.rows[0].username);
|
||||
} catch (err) {
|
||||
console.error('Error inserting data:', err.stack);
|
||||
throw err;
|
||||
}
|
||||
try {
|
||||
const signupData = await db.query(query, [username, password]);
|
||||
console.log("Account created:", signupData.rows[0].username);
|
||||
} catch (err) {
|
||||
console.error("Error inserting data:", err.stack);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function changePassword(username, password) {
|
||||
try {
|
||||
await db.query(
|
||||
'UPDATE accounts SET password = $1 WHERE username = $2',
|
||||
[password, username]
|
||||
);
|
||||
} catch (err) {
|
||||
console.error('Failed to update password')
|
||||
throw err;
|
||||
}
|
||||
|
||||
try {
|
||||
await db.query("UPDATE accounts SET password = $1 WHERE username = $2", [
|
||||
password,
|
||||
username,
|
||||
]);
|
||||
} catch (err) {
|
||||
console.error("Failed to update password");
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
db ,
|
||||
insertUser,
|
||||
isUserExists,
|
||||
changePassword
|
||||
db,
|
||||
insertUser,
|
||||
isUserExists,
|
||||
changePassword,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,199 +1,220 @@
|
||||
const { Server } = require('socket.io');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const { Server } = require("socket.io");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const jwtSecret = process.env.JWT_SECRET;
|
||||
const { db } = require('./db.js');
|
||||
const {json} = require("express");
|
||||
const { db } = require("./db.js");
|
||||
const { json } = require("express");
|
||||
|
||||
function initializeSocket(server) {
|
||||
const io = new Server(server, {
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
sameSite: "strict",
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000
|
||||
const io = new Server(server, {
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
sameSite: "strict",
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000,
|
||||
},
|
||||
});
|
||||
|
||||
io.use((socket, next) => {
|
||||
// user auth
|
||||
const token = socket.handshake.auth.token;
|
||||
if (token) {
|
||||
jwt.verify(token, jwtSecret, (err, user) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return next(new Error("Authentication error"));
|
||||
}
|
||||
socket.user = user;
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next(new Error("Not logged in"));
|
||||
}
|
||||
});
|
||||
|
||||
// open main socket connection
|
||||
io.on("connection", (socket) => {
|
||||
if (!socket.user) {
|
||||
socket.emit("socket error", "User not authenticated");
|
||||
socket.disconnect();
|
||||
return;
|
||||
}
|
||||
const username = socket.user.username;
|
||||
// Join a room with the user's username
|
||||
socket.join(username);
|
||||
|
||||
io.to(username).emit("username", username);
|
||||
|
||||
// chat message event
|
||||
socket.on("chat message", async (msgData) => {
|
||||
const { content, recipient } = msgData;
|
||||
let insertedId;
|
||||
try {
|
||||
// Insert the new message into the database
|
||||
const result = await db.query(
|
||||
"INSERT INTO messages (content, username, recipient) VALUES ($1, $2, $3) RETURNING id",
|
||||
[content, username, recipient],
|
||||
);
|
||||
insertedId = result.rows[0].id;
|
||||
} catch (err) {
|
||||
console.error("Error inserting message:", err);
|
||||
socket.emit(
|
||||
"socket error",
|
||||
"Error inserting message, try refreshing the page",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch the newly inserted message from the database
|
||||
try {
|
||||
const query =
|
||||
"SELECT id, content, username, recipient FROM messages WHERE id = $1";
|
||||
const result = await db.query(query, [insertedId]);
|
||||
|
||||
if (result.rows.length > 0) {
|
||||
const newMessage = result.rows[0];
|
||||
|
||||
// Emit message to the sender's and recipient's rooms
|
||||
io.to(username).to(recipient).emit("chat message", {
|
||||
username: newMessage.username,
|
||||
recipient: newMessage.recipient,
|
||||
content: newMessage.content,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching inserted message:", err);
|
||||
socket.emit("socket error", "Failed to send message");
|
||||
}
|
||||
});
|
||||
|
||||
io.use((socket, next) => {
|
||||
// user auth
|
||||
const token = socket.handshake.auth.token;
|
||||
if(token) {
|
||||
jwt.verify(token, jwtSecret, (err, user) => {
|
||||
if(err) {
|
||||
console.log(err);
|
||||
return next(new Error('Authentication error'));
|
||||
}
|
||||
socket.user = user;
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next(new Error('Not logged in'));
|
||||
}
|
||||
});
|
||||
|
||||
// open main socket connection
|
||||
io.on('connection', (socket) => {
|
||||
if (!socket.user) {
|
||||
socket.emit('socket error', 'User not authenticated')
|
||||
socket.disconnect();
|
||||
return;
|
||||
}
|
||||
const username = socket.user.username;
|
||||
// Join a room with the user's username
|
||||
socket.join(username);
|
||||
|
||||
io.to(username).emit('username', username);
|
||||
|
||||
// chat message event
|
||||
socket.on('chat message', async (msgData) => {
|
||||
const { content, recipient } = msgData;
|
||||
let insertedId;
|
||||
try {
|
||||
// Insert the new message into the database
|
||||
const result = await db.query('INSERT INTO messages (content, username, recipient) VALUES ($1, $2, $3) RETURNING id', [content, username, recipient]);
|
||||
insertedId = result.rows[0].id;
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error inserting message:', err);
|
||||
socket.emit('socket error', "Error inserting message, try refreshing the page")
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch the newly inserted message from the database
|
||||
try {
|
||||
const query = 'SELECT id, content, username, recipient FROM messages WHERE id = $1';
|
||||
const result = await db.query(query, [insertedId]);
|
||||
|
||||
if (result.rows.length > 0) {
|
||||
const newMessage = result.rows[0];
|
||||
|
||||
// Emit message to the sender's and recipient's rooms
|
||||
io.to(username).to(recipient).emit('chat message', { username: newMessage.username, recipient: newMessage.recipient, content: newMessage.content });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching inserted message:', err);
|
||||
socket.emit('socket error', 'Failed to send message')
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('get messages', async (recipient) => {
|
||||
const username = socket.user.username;
|
||||
try {
|
||||
const query = `
|
||||
socket.on("get messages", async (recipient) => {
|
||||
const username = socket.user.username;
|
||||
try {
|
||||
const query = `
|
||||
SELECT id, content, username, recipient
|
||||
FROM messages
|
||||
WHERE (username = $1 AND recipient = $2) OR (username = $2 AND recipient = $1)
|
||||
ORDER BY id ASC
|
||||
`;
|
||||
const result = await db.query(query, [username, recipient]);
|
||||
const result = await db.query(query, [username, recipient]);
|
||||
|
||||
if (result.rows.length > 0) {
|
||||
//const { username: sender, recipient: receiver, content: content, id: id } = result.rows;
|
||||
if (result.rows.length > 0) {
|
||||
//const { username: sender, recipient: receiver, content: content, id: id } = result.rows;
|
||||
|
||||
io.to(username).emit('messages history', result.rows);
|
||||
} else {
|
||||
io.to(username).emit('no messages');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error retrieving messages:', e);
|
||||
socket.emit('socket error', 'Error retrieving messages, refresh the page (server error)')
|
||||
}
|
||||
});
|
||||
io.to(username).emit("messages history", result.rows);
|
||||
} else {
|
||||
io.to(username).emit("no messages");
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error retrieving messages:", e);
|
||||
socket.emit(
|
||||
"socket error",
|
||||
"Error retrieving messages, refresh the page (server error)",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Contacts socket
|
||||
socket.on('contacts', async (contactUsername) => {
|
||||
const username = socket.user.username;
|
||||
const status = (contactUsername.status === "read") ? "read" : "unread";
|
||||
// Contacts socket
|
||||
socket.on("contacts", async (contactUsername) => {
|
||||
const username = socket.user.username;
|
||||
const status = contactUsername.status === "read" ? "read" : "unread";
|
||||
|
||||
// Update contact list in db
|
||||
try {
|
||||
const query = `
|
||||
// Update contact list in db
|
||||
try {
|
||||
const query = `
|
||||
INSERT INTO contacts (username, contact, status)
|
||||
SELECT $1, $2, $3
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM contacts WHERE username = $1 AND contact = $2
|
||||
)
|
||||
`;
|
||||
await db.query(query, [username, contactUsername.contact, status]);
|
||||
} catch (err) {
|
||||
console.error('Failed to update contacts ', err)
|
||||
socket.emit('socket error', 'Failed to update contacts (server error)')
|
||||
}
|
||||
// Get contact list from db
|
||||
try {
|
||||
const query = (`
|
||||
await db.query(query, [username, contactUsername.contact, status]);
|
||||
} catch (err) {
|
||||
console.error("Failed to update contacts ", err);
|
||||
socket.emit("socket error", "Failed to update contacts (server error)");
|
||||
}
|
||||
// Get contact list from db
|
||||
try {
|
||||
const query = `
|
||||
SELECT contact, username, status
|
||||
FROM contacts
|
||||
WHERE username = $1
|
||||
`);
|
||||
const result = await db.query(query, [username]);
|
||||
io.to(username).emit('contacts', result.rows);
|
||||
|
||||
} catch(err) {
|
||||
console.error('Failed to get contacts from db');
|
||||
io.to(username).emit('socket error', 'Failed to get contacts (server error)');
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('get contacts', async () => {
|
||||
const username = socket.user.username;
|
||||
try {
|
||||
const query = (`
|
||||
SELECT contact, username, status
|
||||
FROM contacts
|
||||
WHERE username = $1
|
||||
`);
|
||||
const result = await db.query(query, [username]);
|
||||
io.to(username).emit('contacts', result.rows);
|
||||
|
||||
} catch(err) {
|
||||
console.error('Failed to get contacts from db');
|
||||
io.to(username).emit('socket error', 'Failed to get contacts (server error)');
|
||||
}
|
||||
})
|
||||
socket.on('delete contact', async (contactUsername) => {
|
||||
const username = socket.user.username;
|
||||
try {
|
||||
const query = ('DELETE FROM contacts WHERE (username = $1 AND contact = $2)');
|
||||
await db.query(query, [username, contactUsername]);
|
||||
|
||||
} catch(err) {
|
||||
console.error('Failed to remove contact from db');
|
||||
io.to(username).emit('socket error', 'Failed to remove contact (server error)');
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('status', async (username) => {
|
||||
const userUsername = socket.user.username;
|
||||
const status = 'unread';
|
||||
try {
|
||||
const query = (
|
||||
'UPDATE contacts SET status = $1 WHERE username = $2 AND contact = $3'
|
||||
);
|
||||
await db.query(query, [status, userUsername, username]);
|
||||
io.to(userUsername).emit('status', username);
|
||||
} catch(err) {
|
||||
console.error('Failed to update unread status:', err);
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('read', async(contactUsername) => {
|
||||
const userUsername = socket.user.username;
|
||||
const status = 'read';
|
||||
try {
|
||||
const query = ('UPDATE contacts SET status = $1 WHERE username = $2 AND contact = $3');
|
||||
await db.query(query, [status, userUsername, contactUsername]);
|
||||
io.to(userUsername).emit('status', contactUsername);
|
||||
} catch(err) {
|
||||
console.error('Failed to update unread status:', err)
|
||||
}
|
||||
})
|
||||
// disconnect event
|
||||
socket.on('disconnect', () => {
|
||||
return "Disconnected";
|
||||
});
|
||||
`;
|
||||
const result = await db.query(query, [username]);
|
||||
io.to(username).emit("contacts", result.rows);
|
||||
} catch (err) {
|
||||
console.error("Failed to get contacts from db");
|
||||
io.to(username).emit(
|
||||
"socket error",
|
||||
"Failed to get contacts (server error)",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return io;
|
||||
socket.on("get contacts", async () => {
|
||||
const username = socket.user.username;
|
||||
try {
|
||||
const query = `
|
||||
SELECT contact, username, status
|
||||
FROM contacts
|
||||
WHERE username = $1
|
||||
`;
|
||||
const result = await db.query(query, [username]);
|
||||
io.to(username).emit("contacts", result.rows);
|
||||
} catch (err) {
|
||||
console.error("Failed to get contacts from db");
|
||||
io.to(username).emit(
|
||||
"socket error",
|
||||
"Failed to get contacts (server error)",
|
||||
);
|
||||
}
|
||||
});
|
||||
socket.on("delete contact", async (contactUsername) => {
|
||||
const username = socket.user.username;
|
||||
try {
|
||||
const query =
|
||||
"DELETE FROM contacts WHERE (username = $1 AND contact = $2)";
|
||||
await db.query(query, [username, contactUsername]);
|
||||
} catch (err) {
|
||||
console.error("Failed to remove contact from db");
|
||||
io.to(username).emit(
|
||||
"socket error",
|
||||
"Failed to remove contact (server error)",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("status", async (username) => {
|
||||
const userUsername = socket.user.username;
|
||||
const status = "unread";
|
||||
try {
|
||||
const query =
|
||||
"UPDATE contacts SET status = $1 WHERE username = $2 AND contact = $3";
|
||||
await db.query(query, [status, userUsername, username]);
|
||||
io.to(userUsername).emit("status", username);
|
||||
} catch (err) {
|
||||
console.error("Failed to update unread status:", err);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("read", async (contactUsername) => {
|
||||
const userUsername = socket.user.username;
|
||||
const status = "read";
|
||||
try {
|
||||
const query =
|
||||
"UPDATE contacts SET status = $1 WHERE username = $2 AND contact = $3";
|
||||
await db.query(query, [status, userUsername, contactUsername]);
|
||||
io.to(userUsername).emit("status", contactUsername);
|
||||
} catch (err) {
|
||||
console.error("Failed to update unread status:", err);
|
||||
}
|
||||
});
|
||||
// disconnect event
|
||||
socket.on("disconnect", () => {
|
||||
console.log(socket.id, " disconnected");
|
||||
return "Disconnected";
|
||||
});
|
||||
});
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
module.exports = { initializeSocket };
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1009 B |
@@ -1,47 +1,48 @@
|
||||
window.onload = () => {
|
||||
document.getElementById('username').focus();
|
||||
}
|
||||
document.getElementById("username").focus();
|
||||
};
|
||||
|
||||
function showPasswd() {
|
||||
let x = document.getElementById("password");
|
||||
let y = document.getElementById("sPassword");
|
||||
if(x.type == "password"){
|
||||
x.type = "text";
|
||||
y.type = "text";
|
||||
} else {
|
||||
x.type = "password";
|
||||
y.type = "password";
|
||||
}
|
||||
let x = document.getElementById("password");
|
||||
let y = document.getElementById("sPassword");
|
||||
if (x.type == "password") {
|
||||
x.type = "text";
|
||||
y.type = "text";
|
||||
} else {
|
||||
x.type = "password";
|
||||
y.type = "password";
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('signupForm').addEventListener('submit',async function (event) {
|
||||
document
|
||||
.getElementById("signupForm")
|
||||
.addEventListener("submit", async function (event) {
|
||||
event.preventDefault();
|
||||
const messageBox = document.getElementById('messageBox');
|
||||
const username = document.getElementById('username').value.trim();
|
||||
const messageBox = document.getElementById("messageBox");
|
||||
const username = document.getElementById("username").value.trim();
|
||||
const password = document.getElementById("password").value.trim();
|
||||
const sPassword = document.getElementById("sPassword").value.trim();
|
||||
const jsonData = JSON.stringify({ username, password });
|
||||
|
||||
if(password !== sPassword){
|
||||
messageBox.innerText = "Passwords don't match!"
|
||||
return;
|
||||
if (password !== sPassword) {
|
||||
messageBox.innerText = "Passwords don't match!";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const response = await fetch ('/auth/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: jsonData
|
||||
const response = await fetch("/auth/signup", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: jsonData,
|
||||
});
|
||||
|
||||
console.log(jsonData);
|
||||
const result = await response.json();
|
||||
if(response.ok) {
|
||||
messageBox.innerText = result.message;
|
||||
messageBox.style.color = 'green';
|
||||
if (response.ok) {
|
||||
messageBox.innerText = result.message;
|
||||
messageBox.style.color = "green";
|
||||
} else {
|
||||
messageBox.innerText = result.message;
|
||||
messageBox.style.color = 'red';
|
||||
messageBox.innerText = result.message;
|
||||
messageBox.style.color = "red";
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LOGGED IN!!!</h1>
|
||||
</body>
|
||||
</html>
|
||||
415
index.js
415
index.js
@@ -1,274 +1,285 @@
|
||||
require('dotenv').config();
|
||||
const express = require('express');
|
||||
const session = require('express-session');
|
||||
require("dotenv").config();
|
||||
const express = require("express");
|
||||
const session = require("express-session");
|
||||
const port = process.env.APP_PORT;
|
||||
const app = express();
|
||||
const cookieParser = require('cookie-parser');
|
||||
const cookieParser = require("cookie-parser");
|
||||
|
||||
const path = require('path');
|
||||
const { insertUser, isUserExists, changePassword, db } = require('./backend/db.js');
|
||||
const { initializeSocket } = require('./backend/socket.js');
|
||||
const path = require("path");
|
||||
const {
|
||||
insertUser,
|
||||
isUserExists,
|
||||
changePassword,
|
||||
db,
|
||||
} = require("./backend/db.js");
|
||||
const { initializeSocket } = require("./backend/socket.js");
|
||||
|
||||
const bcrypt = require('bcrypt');
|
||||
const bcrypt = require("bcrypt");
|
||||
const saltRounds = 10;
|
||||
const { createServer } = require('node:http');
|
||||
const { createServer } = require("node:http");
|
||||
const server = createServer(app);
|
||||
const jwt = require('jsonwebtoken');
|
||||
const {decode} = require("jsonwebtoken");
|
||||
const {json} = require("express");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { decode } = require("jsonwebtoken");
|
||||
const { json } = require("express");
|
||||
const jwtSecret = process.env.JWT_SECRET;
|
||||
|
||||
|
||||
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({
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
app.use("/static", express.static("frontend"));
|
||||
|
||||
app.use(
|
||||
session({
|
||||
secret: process.env.SESSION_SECRET,
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
cookie: {
|
||||
secure: false,
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000 //30 days
|
||||
}
|
||||
}));
|
||||
secure: false,
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000, //30 days
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// auth login API
|
||||
app.post('/auth/login', async (req, res) => {
|
||||
await loginUser(req, res);
|
||||
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);
|
||||
app.post("/auth/signup", async (req, res) => {
|
||||
await signupUser(req, res);
|
||||
});
|
||||
|
||||
// logout API
|
||||
app.post('/auth/logout', (req, res) => {
|
||||
// clear JWT token
|
||||
res.clearCookie('token', {
|
||||
path: '/'
|
||||
});
|
||||
// clear socket.io cookie (no idea what is it for but better remove it)
|
||||
res.clearCookie('io', {
|
||||
path: '/'
|
||||
});
|
||||
res.status(200).json({ message: 'Successfully logged out' });
|
||||
app.post("/auth/logout", (req, res) => {
|
||||
// clear JWT token
|
||||
res.clearCookie("token", {
|
||||
path: "/",
|
||||
});
|
||||
// clear socket.io cookie (no idea what is it for but better remove it)
|
||||
res.clearCookie("io", {
|
||||
path: "/",
|
||||
});
|
||||
res.status(200).json({ message: "Successfully logged out" });
|
||||
});
|
||||
|
||||
// get JWT token API
|
||||
app.get('/auth/token', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
if(!token){
|
||||
res.send('Not logged in');
|
||||
}
|
||||
res.send(token);
|
||||
app.get("/auth/token", (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
if (!token) {
|
||||
res.send("Not logged in");
|
||||
}
|
||||
res.send(token);
|
||||
});
|
||||
|
||||
app.post('/auth/changePassword', async (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
const { cPassword, nPassword } = req.body;
|
||||
app.post("/auth/changePassword", async (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
const { cPassword, nPassword } = req.body;
|
||||
|
||||
if(!cPassword && nPassword) {
|
||||
return res.json({ message: 'Field is empty' })
|
||||
if (!cPassword && nPassword) {
|
||||
return res.json({ message: "Field is empty" });
|
||||
}
|
||||
if (nPassword === cPassword) {
|
||||
return res.json({ message: "Passwords are the same" });
|
||||
}
|
||||
let username;
|
||||
try {
|
||||
const decoded = jwt.verify(token, jwtSecret);
|
||||
username = decoded.username;
|
||||
} catch (err) {
|
||||
return res.status(403).json({ message: "Unauthorized" });
|
||||
}
|
||||
try {
|
||||
const result = await db.query(
|
||||
"SELECT * FROM accounts WHERE username = $1",
|
||||
[username],
|
||||
);
|
||||
// checks that passwords are matching
|
||||
const match = await bcrypt.compare(cPassword, result.rows[0].password);
|
||||
// if not return information
|
||||
if (!match) {
|
||||
return res.status(401).json({ message: "Current password is invalid" });
|
||||
}
|
||||
if(nPassword === cPassword) {
|
||||
return res.json({ message: 'Passwords are the same' })
|
||||
}
|
||||
let username;
|
||||
try {
|
||||
const decoded = jwt.verify(token, jwtSecret);
|
||||
username = username = decoded.username;
|
||||
} catch (err) {
|
||||
return res.status(403).json({ message: 'Unauthorized'});
|
||||
}
|
||||
try {
|
||||
const result = await db.query('SELECT * FROM accounts WHERE username = $1', [username]);
|
||||
// checks that passwords are matching
|
||||
const match = await bcrypt.compare(cPassword, result.rows[0].password);
|
||||
// if not return information
|
||||
if(!match){
|
||||
return res.status(401).json({ message: 'Current password is invalid' })
|
||||
}
|
||||
// hash password
|
||||
const salt = await bcrypt.genSalt(saltRounds);
|
||||
const hash = await bcrypt.hash(nPassword, salt);
|
||||
await changePassword(username, hash);
|
||||
// hash password
|
||||
const salt = await bcrypt.genSalt(saltRounds);
|
||||
const hash = await bcrypt.hash(nPassword, salt);
|
||||
await changePassword(username, hash);
|
||||
|
||||
return res.status(200).json({ message: 'Successfully changed password' });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ message: 'Failed to change password' });
|
||||
}
|
||||
return res.status(200).json({ message: "Successfully changed password" });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ message: "Failed to change password" });
|
||||
}
|
||||
});
|
||||
|
||||
// get username
|
||||
app.get('/auth/user', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
// verify 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});
|
||||
}
|
||||
});
|
||||
}
|
||||
app.get("/auth/user", (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
// verify 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 });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/contacts', async(req, res) => {
|
||||
const token = req.cookies.token;
|
||||
if(token) {
|
||||
jwt.verify(token, jwtSecret, (err, user) => {
|
||||
if(err) {
|
||||
return res.status(403).send('Unauthorized');
|
||||
}
|
||||
});
|
||||
}
|
||||
const jsonContacts = JSON.stringify(req.body.contactUsername);
|
||||
app.post("/api/contacts", async (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
if (token) {
|
||||
jwt.verify(token, jwtSecret, (err, user) => {
|
||||
if (err) {
|
||||
return res.status(403).send("Unauthorized");
|
||||
}
|
||||
});
|
||||
}
|
||||
const jsonContacts = JSON.stringify(req.body.contactUsername);
|
||||
});
|
||||
|
||||
// serving the login page
|
||||
app.get('/login', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
// verify token
|
||||
if (token) {
|
||||
res.json({ Error: 'Already logged in' });
|
||||
} else {
|
||||
res.sendFile(path.join(__dirname, '/frontend/routes/login.html'));
|
||||
}
|
||||
app.get("/login", (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
// verify 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("/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('/settings', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
app.get("/settings", (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
|
||||
if(!token) {
|
||||
res.redirect('/login');
|
||||
return;
|
||||
if (!token) {
|
||||
res.redirect("/login");
|
||||
return;
|
||||
}
|
||||
// verify token
|
||||
jwt.verify(token, jwtSecret, (err) => {
|
||||
if (err) {
|
||||
return res.status(403).send("Unauthorized");
|
||||
}
|
||||
// verify token
|
||||
jwt.verify(token, jwtSecret, (err) => {
|
||||
if (err) {
|
||||
return res.status(403).send('Unauthorized');
|
||||
}
|
||||
res.sendFile(path.join(__dirname, '/frontend/routes/settings.html'))
|
||||
});
|
||||
})
|
||||
res.sendFile(path.join(__dirname, "/frontend/routes/settings.html"));
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
app.get("/", (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
|
||||
if(!token) {
|
||||
return res.redirect('/login');
|
||||
|
||||
} else {
|
||||
return res.redirect('/chat');
|
||||
}
|
||||
})
|
||||
if (!token) {
|
||||
return res.redirect("/login");
|
||||
} else {
|
||||
return res.redirect("/chat");
|
||||
}
|
||||
});
|
||||
// serving the chat page if logged in
|
||||
app.get('/chat', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
app.get("/chat", (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
|
||||
if(!token) {
|
||||
res.redirect('/login');
|
||||
return;
|
||||
if (!token) {
|
||||
res.redirect("/login");
|
||||
return;
|
||||
}
|
||||
// verify token
|
||||
jwt.verify(token, jwtSecret, (err) => {
|
||||
if (err) {
|
||||
return res.status(403).send("Unauthorized");
|
||||
}
|
||||
// verify token
|
||||
jwt.verify(token, jwtSecret, (err) => {
|
||||
if (err) {
|
||||
return res.status(403).send('Unauthorized');
|
||||
}
|
||||
res.sendFile(path.join(__dirname, '/frontend/routes/chat.html'));
|
||||
});
|
||||
res.sendFile(path.join(__dirname, "/frontend/routes/chat.html"));
|
||||
});
|
||||
});
|
||||
initializeSocket(server)
|
||||
initializeSocket(server);
|
||||
|
||||
// run server
|
||||
server.listen(port, () => {
|
||||
console.log(`Chat app listening on port ${port}`);
|
||||
console.log(`Chat app listening on port ${port}`);
|
||||
});
|
||||
|
||||
// signup function
|
||||
async function signupUser(req, res) {
|
||||
let username = req.body.username;
|
||||
let password = req.body.password;
|
||||
let username = req.body.username;
|
||||
let password = req.body.password;
|
||||
|
||||
if(username && password){
|
||||
try {
|
||||
// Check if user exists
|
||||
const exists = await isUserExists(username);
|
||||
if (exists) {
|
||||
console.log('User already exists');
|
||||
return res.status(500).json({ message: 'User already exists!' });
|
||||
}
|
||||
if (username && password) {
|
||||
try {
|
||||
// Check if user exists
|
||||
const exists = await isUserExists(username);
|
||||
if (exists) {
|
||||
console.log("User already exists");
|
||||
return res.status(500).json({ message: "User already exists!" });
|
||||
}
|
||||
|
||||
// Hash password
|
||||
const salt = await bcrypt.genSalt(saltRounds);
|
||||
const hash = await bcrypt.hash(password, salt);
|
||||
// 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).json({ message: "Account successfully created" });
|
||||
} catch (err) {
|
||||
console.error('Error inserting data:', err);
|
||||
return res.status(500).json({ message: 'Error inserting data' });
|
||||
}
|
||||
} else {
|
||||
res.status(400).json({ message: 'Form is empty'})
|
||||
// Insert user
|
||||
await insertUser(username, hash);
|
||||
return res.status(200).json({ message: "Account successfully created" });
|
||||
} catch (err) {
|
||||
console.error("Error inserting data:", err);
|
||||
return res.status(500).json({ message: "Error inserting data" });
|
||||
}
|
||||
} else {
|
||||
res.status(400).json({ message: "Form is empty" });
|
||||
}
|
||||
}
|
||||
|
||||
// login function
|
||||
async function loginUser(req, res) {
|
||||
let username = req.body.username;
|
||||
let password = req.body.password;
|
||||
|
||||
let username = req.body.username;
|
||||
let password = req.body.password;
|
||||
if (username && password) {
|
||||
try {
|
||||
username = username.trim();
|
||||
password = password.trim();
|
||||
|
||||
if (username && password) {
|
||||
try {
|
||||
username = username.trim();
|
||||
password = password.trim();
|
||||
|
||||
const result = await db.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) {
|
||||
res.status(401).json({ message: 'Invalid password'});
|
||||
return;
|
||||
}
|
||||
const token = jwt.sign({ username }, jwtSecret, {
|
||||
expiresIn: '30d' // token expires in 30 days
|
||||
});
|
||||
res.cookie('token', token, {
|
||||
httpOnly: true,
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
|
||||
});
|
||||
req.session.loggedin = true;
|
||||
req.session.username = username;
|
||||
res.status(200).json({ message: 'Successfully logged in' });
|
||||
} else {
|
||||
return res.status(401).json({ message: 'Incorrect Username or Password!'})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error executing query', error);
|
||||
res.status(500).json({ message: 'Internal server error' });
|
||||
const result = await db.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) {
|
||||
res.status(401).json({ message: "Invalid password" });
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
res.status(400).json({ message: 'Please enter Username and Password!' });
|
||||
const token = jwt.sign({ username }, jwtSecret, {
|
||||
expiresIn: "30d", // token expires in 30 days
|
||||
});
|
||||
res.cookie("token", token, {
|
||||
httpOnly: true,
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
|
||||
});
|
||||
req.session.loggedin = true;
|
||||
req.session.username = username;
|
||||
res.status(200).json({ message: "Successfully logged in" });
|
||||
} else {
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Incorrect Username or Password!" });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error executing query", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
res.end();
|
||||
} else {
|
||||
res.status(400).json({ message: "Please enter Username and Password!" });
|
||||
}
|
||||
res.end();
|
||||
}
|
||||
Reference in New Issue
Block a user