From c05e00cacf8cb955e55b6fc94a6dc992aeb25659 Mon Sep 17 00:00:00 2001 From: slawk0 Date: Sat, 14 Sep 2024 18:40:06 +0200 Subject: [PATCH] adding contact functionality --- backend/db.js | 4 +- backend/socket.js | 43 ++++++++++++++++- frontend/icons/icon.png | Bin 0 -> 1009 bytes frontend/js/chat.js | 99 +++++++++++++++++++++++--------------- frontend/js/settings.js | 2 +- frontend/routes/chat.html | 1 + index.js | 16 +++++- 7 files changed, 122 insertions(+), 43 deletions(-) create mode 100644 frontend/icons/icon.png diff --git a/backend/db.js b/backend/db.js index 8c71563..1273a32 100644 --- a/backend/db.js +++ b/backend/db.js @@ -70,10 +70,9 @@ async function insertUser(username, password){ VALUES ($1, $2) RETURNING *; `; - const values = [username, password]; try { - const signupData = await db.query(query, values); + 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); @@ -91,6 +90,7 @@ async function changePassword(username, password) { console.error('Failed to update password') throw err; } + } module.exports = { db , diff --git a/backend/socket.js b/backend/socket.js index aa0d236..0818876 100644 --- a/backend/socket.js +++ b/backend/socket.js @@ -2,6 +2,7 @@ const { Server } = require('socket.io'); const jwt = require('jsonwebtoken'); const jwtSecret = process.env.JWT_SECRET; const { db } = require('./db.js'); +const {json} = require("express"); function initializeSocket(server) { const io = new Server(server, { @@ -70,6 +71,7 @@ function initializeSocket(server) { } } catch (err) { console.error('Error fetching inserted message:', err); + socket.emit('socket error', 'Failed to send message') } }); @@ -94,9 +96,48 @@ function initializeSocket(server) { } } catch (e) { console.error('Error retrieving messages:', e); - socket.emit('socket error', "Error retrieving messages, refresh the page") + socket.emit('socket error', 'Error retrieving messages, refresh the page (server error)') } }); + + // Contacts socket + socket.on('contacts', async (contactUsername) => { + const username = socket.user.username; + // Update contact list in db + try { + const query = ('INSERT INTO contacts (username, contact) VALUES ($1, $2)'); + await db.query(query, [username, contactUsername]); + } catch (err) { + console.error('Failed to update contacts') + socket.emit('socket error', 'Failed to update contacts (server error)') + } + // Get contact list from db + try { + const query = (` + SELECT contact, username + FROM contacts + WHERE username = $1 + `); + const result = await db.query(query, [username]); + console.log(result.rows) + socket.emit('contacts', result.rows); + } catch(err) { + console.error('Failed to get contacts from db'); + socket.emit('socket error', 'Failed to get contacts (server error)'); + } + }) + + socket.on('delete contacts', 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]); + socket.emit('delete contacts', 'ok'); + } catch(err) { + console.error('Failed to remove contact from db'); + socket.emit('socket error', 'Failed to remove contact (server error)'); + } + }) // disconnect event socket.on('disconnect', () => { return "Disconnected"; diff --git a/frontend/icons/icon.png b/frontend/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d02d205e986ff1bb10533184442a3f390f482f GIT binary patch literal 1009 zcmV6`wzLHb z#8j6;TU#-PqBa$*rB%?>gd%O#@k(D-7AF{UA6P~Idy`htoCt458M7)_vPQe(gX zLW6{*w%SMoblEPuJ2SiU9UrQ-yWQGFx6y~5JKxK>-@W&IGbi6%U>@`MkD;Z(jQV6ecqq_k&53}v!6)uhFrHOVn-y3CC?i8!62Mu4#}eS-j{~1y z{MQ272cN71xnDsw%qDUwIPvt7?n^!8$9}wR0kx-UJ*$dK4}hu*O6hD5&LAZL;MJbM z7yF>VtOT@-wB-3M`3ykQKR-B425|KHaCApsV_$Nn9Q{Y8^2U=#2{sYA8vr{>$`-u! zcOn%4v|irarJ&x-Rpn`*kgcDr`SR0Dle*!2!y*#h0%DFrY4E_UkJhfsD4@`1ZX=|a z6wFn)V8vyhc{+Zix<7WLvOYxss5X(rT*vu^9tc@S(I;;muG%vxK)^t{d6t>Wv8|{B zD?BSx_#&eitwrs)(;GzRDR5dCj9CA`pr}^7Y8O6)ymQDXu7`Q+v&x z6|Z2mzXFZ<&3JBT=Oo`%`XbgXT#v1bw`0eZ?UVejrO)G$f+koJM`!RU*t9b^Q6Mt4 zCGd^#p+K)DIh6j*ZpK0YfKWV?!iQpGGx8)cZbgugL`EN!#M60t1;%c*<;=#N%CFy^ zs@7}yP^D_{69-`X|N74uwux%2MUa;e^G7FnNAUEoV~`Bn z+DX;3YWFWaX2Yr4CEC#M)1{9tz$8YL2P>5)`+GnN2$(j}b|r+zuZ{mnrKS*LH@v@f z0)VDv)=QZ0xM8>5jwY&3+~0qPL}Zgh { currentUsername = username; @@ -65,10 +67,10 @@ async function initializeSocket() { }) // Set for not displaying same contact multiple times - const addedContacts = new Set(); + const addedContacts = new Set(); // Main socket connection, it is displaying all messages in real time - socket.on('chat message', (msg) => { + socket.on('chat message', async (msg) => { console.log('Received message:', msg); const { username, content, recipient } = msg; @@ -82,50 +84,30 @@ async function initializeSocket() { messages.scrollTop = messages.scrollHeight; } - // Add and display contact/incoming messages + // Add and display contact if (recipient !== currentRecipient && username !== currentUsername) { // Check if the contact has already been added if (!addedContacts.has(username)) { - addContact(username, socket); - // Add the username to the Set of added contacts + try{ + socket.emit('contacts', username); + } catch (err) { + messageBox.innerHTML = 'Failed to fetch contact api'; + console.log('Failed to add contact', err); + } + // Add the username to the Set of contacts addedContacts.add(username); } } - - function addContact(username, socket) { - const contact = document.createElement('li'); - contact.className = 'contact-item'; - - const usernameSpan = document.createElement('span'); - usernameSpan.textContent = username; - usernameSpan.className = 'contact-username'; - - const removeButton = document.createElement('button'); - removeButton.textContent = 'X'; - removeButton.className = 'remove-contact'; - - contact.appendChild(usernameSpan); - contact.appendChild(removeButton); - - usernameSpan.addEventListener('click', () => { - currentRecipient = username; - recipientInput.value = username; - localStorage.setItem('currentRecipient', currentRecipient); - socket.emit('get messages', username); - }); - - removeButton.addEventListener('click', (e) => { - e.stopPropagation(); - contacts.removeChild(contact); - addedContacts.delete(username); - }); - - contacts.appendChild(contact); - console.log('Created contact:', username); - } - }); + // Contacts handler + socket.on('contacts', (contacts) => { + console.log('contactArray: ', contacts); + for(const contact in contacts) { + addContact(contact, socket); + } + }) + // If not previous messages found on backend socket.on('no messages', () => { console.log('No previous messages found'); @@ -174,7 +156,48 @@ async function initializeSocket() { } messages.scrollTop = messages.scrollHeight; }); + + function addContact(username, socket) { + const contact = document.createElement('li'); + contact.className = 'contact-item'; + + const usernameSpan = document.createElement('span'); + usernameSpan.textContent = username; + usernameSpan.className = 'contact-username'; + + const removeButton = document.createElement('button'); + removeButton.textContent = 'X'; + removeButton.className = 'remove-contact'; + + contact.appendChild(usernameSpan); + contact.appendChild(removeButton); + + usernameSpan.addEventListener('click', () => { + currentRecipient = username; + recipientInput.value = username; + localStorage.setItem('currentRecipient', currentRecipient); + socket.emit('get messages', username); + }); + + removeButton.addEventListener('click', (e) => { + e.stopPropagation(); + socket.emit('delete contact', username); + socket.on('delete contact', (res) => { + if(res === 'ok') { + contacts.removeChild(contact); + addedContacts.delete(username); + } else { + messageBox.innerHTML = 'Failed to remove contact (server error)' + } + }) + + }); + + contacts.appendChild(contact); + console.log('Created contact:', username); + } } + initializeSocket(); diff --git a/frontend/js/settings.js b/frontend/js/settings.js index ffb81cc..73e6bfc 100644 --- a/frontend/js/settings.js +++ b/frontend/js/settings.js @@ -29,7 +29,7 @@ document.getElementById('changePasswordForm').addEventListener('submit', async ( const nPassword = document.getElementById('nPassword').value.trim(); const messageBox = document.getElementById('messageBox'); const jsonData = JSON.stringify({ cPassword, nPassword }); - const response = await fetch('/auth/changepassword', { + const response = await fetch('/auth/changePassword', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/frontend/routes/chat.html b/frontend/routes/chat.html index d1f222e..084a9de 100644 --- a/frontend/routes/chat.html +++ b/frontend/routes/chat.html @@ -6,6 +6,7 @@ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> Chat + diff --git a/index.js b/index.js index 072ddb7..fe14820 100644 --- a/index.js +++ b/index.js @@ -15,6 +15,7 @@ const { createServer } = require('node:http'); const server = createServer(app); const jwt = require('jsonwebtoken'); const {decode} = require("jsonwebtoken"); +const {json} = require("express"); const jwtSecret = process.env.JWT_SECRET; @@ -66,7 +67,7 @@ app.get('/auth/token', (req, res) => { res.send(token); }); -app.post('/auth/changepassword', async (req, res) => { +app.post('/auth/changePassword', async (req, res) => { const token = req.cookies.token; const { cPassword, nPassword } = req.body; @@ -118,6 +119,18 @@ app.get('/auth/user', (req, res) => { } }); +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; @@ -153,6 +166,7 @@ app.get('/settings', (req, res) => { res.sendFile(path.join(__dirname, '/frontend/routes/settings.html')) }); }) + app.get('/', (req, res) => { const token = req.cookies.token;