From 5047d8c8901e71f7ef441287de88a28a76b0d5d6 Mon Sep 17 00:00:00 2001
From: Azar <79351619+azr-arch@users.noreply.github.com>
Date: Sat, 26 Oct 2024 21:35:04 +0530
Subject: [PATCH] implement restrictions for deleting and editing message
---
client/src/components/Chat/DropDownOption.jsx | 30 ++++++++++++++++---
constants.json | 4 ++-
server/sockets/deleteMessage.js | 8 ++++-
server/sockets/editMessage.js | 6 ++++
server/utils/lib.js | 17 ++++++++++-
5 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/client/src/components/Chat/DropDownOption.jsx b/client/src/components/Chat/DropDownOption.jsx
index 227f5ad9..95323634 100644
--- a/client/src/components/Chat/DropDownOption.jsx
+++ b/client/src/components/Chat/DropDownOption.jsx
@@ -1,7 +1,7 @@
import { BiDotsVerticalRounded } from 'react-icons/bi';
import Dropdown from 'rsuite/Dropdown';
import PropTypes from 'prop-types';
-import React from 'react';
+import React, { useMemo } from 'react';
import chatHelper from 'src/lib/chatHelper';
import { socket } from 'src/lib/socketConnection';
import { useApp } from 'src/context/AppContext';
@@ -9,6 +9,9 @@ import { useChat } from 'src/context/ChatContext';
import useChatUtils from 'src/lib/chatSocket';
import useCryptoKeys from 'src/hooks/useCryptoKeys';
+import { FIFTEEN_MINUTES } from '../../../../constants.json';
+
+
const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setReplyId }) => {
const { app } = useApp();
@@ -17,7 +20,17 @@ const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setRe
const { getMessage, messageExists, handleCopyToClipBoard } = chatHelper(state, app);
const { deleteMessage } = useChatUtils(socket);
+ const message = getMessage(id, state, app);
+
+ const isWithin15Minutes = useMemo(() => {
+ return Date.now() - new Date(message.time).getTime() <= FIFTEEN_MINUTES;
+ }, [message.time])
+
const handleEdit = (id) => {
+ if (!isWithin15Minutes) {
+ return;
+ }
+
inputRef.current.focus();
const { message } = getMessage(id, state, app);
@@ -31,7 +44,7 @@ const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setRe
};
const handleDelete = async (id) => {
- if (!messageExists(id)) {
+ if (!messageExists(id) || !isWithin15Minutes) {
return;
}
@@ -78,13 +91,22 @@ const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setRe
renderToggle={renderIconButton}
NoCaret
>
- handleEdit(id)}>Edit
+ {
+ isWithin15Minutes && (
+ handleEdit(id)}>Edit
+ )
+ }
handleCopyToClipBoard(id, importedPrivateKey)}>
Copy
setReplyId(id)}>Reply
- handleDelete(id)}>Delete
+
+ {
+ isWithin15Minutes && (
+ handleDelete(id)}>Delete
+ )
+ }
);
} else if (!isSender) {
diff --git a/constants.json b/constants.json
index 86d599a7..831af1f5 100644
--- a/constants.json
+++ b/constants.json
@@ -19,5 +19,7 @@
"NEW_EVENT_CREATE_ROOM": "createRoom",
"NEW_EVENT_READ_MESSAGE": "read_message",
"NEW_EVENT_ONLINE_STATUS": "online_status",
- "NEW_EVENT_REQUEST_PUBLIC_KEY": "requestPublicKey"
+ "NEW_EVENT_REQUEST_PUBLIC_KEY": "requestPublicKey",
+
+ "FIFTEEN_MINUTES": 900000
}
\ No newline at end of file
diff --git a/server/sockets/deleteMessage.js b/server/sockets/deleteMessage.js
index 756ecc21..b81af4c7 100644
--- a/server/sockets/deleteMessage.js
+++ b/server/sockets/deleteMessage.js
@@ -1,5 +1,5 @@
const { NEW_EVENT_DELETE_MESSAGE } = require('../../constants.json');
-const { getActiveUser, removeMessage } = require('../utils/lib');
+const { getActiveUser, removeMessage, isMessageEditableOrDeletable } = require('../utils/lib');
module.exports = (socket) => {
socket.on(
@@ -14,6 +14,12 @@ module.exports = (socket) => {
return;
}
+ // Check if message exists and is within the 15-minute editable window
+ if (!isMessageEditableOrDeletable(chatId, messageId)) {
+ messageWasDeletedSuccessfully(false);
+ return;
+ }
+
const messageDeleted = await removeMessage(chatId, messageId);
socket.broadcast
diff --git a/server/sockets/editMessage.js b/server/sockets/editMessage.js
index 8136223b..a8b94844 100644
--- a/server/sockets/editMessage.js
+++ b/server/sockets/editMessage.js
@@ -17,6 +17,12 @@ module.exports = (socket) => {
return;
}
+ // Check if message exists and is within the 15-minute editable window
+ if (!isMessageEditableOrDeletable(chatId, messageId)) {
+ messageWasEditedSuccessfully(false);
+ return;
+ }
+
const messageEdited = await editMessage(chatId, {
id: messageId,
message: newMessage,
diff --git a/server/utils/lib.js b/server/utils/lib.js
index dc679010..3a741205 100644
--- a/server/utils/lib.js
+++ b/server/utils/lib.js
@@ -8,6 +8,9 @@ const User = require('../models/UserModel');
const Message = require('../models/MessageModel');
const { generateObjectId } = require('./helper');
+const { FIFTEEN_MINUTES } = require('../../constants.json');
+
+
/**
* @typedef {{
* id: string,
@@ -532,6 +535,17 @@ async function isUserBlocked(users) {
}
}
+ function isMessageEditableOrDeletable(chatId, messageId) {
+ const chat = chats[chatId];
+ if (!chat || !chat.messages || !chat.messages[messageId]) {
+ return false; // Message doesn't exist
+ }
+
+ const message = chat.messages[messageId];
+ const timeSinceCreated = Date.now() - new Date(message.time).getTime();
+ return timeSinceCreated <= FIFTEEN_MINUTES; // Check if within 15 minutes
+}
+
module.exports = {
init,
createChat,
@@ -552,5 +566,6 @@ module.exports = {
delActiveUser,
seenMessage,
blockUser,
- isUserBlocked
+ isUserBlocked,
+ isMessageEditableOrDeletable
};