This is an implementation for a chat the fetches chatlist and realtime one on one chat.
The purpose of the provided code is to restrict the accessing of read and write based on the condition where the logged in user could only fetch the data corresponding to his uid
provided during authentication.
rule:-
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /messages/{document=**} {
allow read: if request.auth != null && (request.auth.uid == resource.data.uid || request.auth.uid == resource.data.recipientId);
}
match /messages/{document} {
allow write: if request.auth != null && (request.auth.uid == resource.data.uid || request.auth.uid == resource.data.recipientId);
}
// Chatlist Collection
match /chatlist/{document=**} {
allow read: if request.auth != null && (request.auth.uid == resource.data.uid || request.auth.uid == resource.data.recipientId);
allow write: if request.auth != null && (request.auth.uid == resource.data.uid || request.auth.uid == resource.data.recipientId);
}
match /chatlist/{document} {
allow write: if request.auth != null && (request.auth.uid == resource.data.uid || request.auth.uid == resource.data.recipientId);
}
}
}
In the above code provided the rule has been written based on the above condition.
When trying to read or fetch the data from the collection chat list i am getting:
Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.
this the code to get the chatlist in realtime
const fetchData = async () => {
try {
const messagesQuery = query(
collection(db, "messages"),
orderBy("createdAt", "desc")
);
const messagesSnapshot = await getDocs(messagesQuery);
const messagesData = messagesSnapshot.docs.map((doc) => doc.data());
console.log(messagesData,"messagesData");
const chatlistQuery = query(collection(db, "chatlist"));
const chatlistSnapshot = await getDocs(chatlistQuery);
const chatlistData = chatlistSnapshot.docs.map((doc) => doc.data());
console.log(chatlistData,"chatlistData");
const filteredData = chatlistData.filter(
(item) =>
item.recipientId === currentUserUID || item.uid === currentUserUID
);
const uniqueUsers = new Map();
filteredData.forEach((item) => {
const existingItem = uniqueUsers.get(
item.senderName || item.userName
);
if (!existingItem || item.createdAt > existingItem.createdAt) {
if (item.recipientId === currentUserUID) {
item.senderName = item.userName;
item.recipientId = item.uid;
item.email = item.currentUserEmail;
uniqueUsers.set(item.userName, item);
} else {
uniqueUsers.set(item.senderName, item);
}
}
});
const updatedRecentChat = Array.from(uniqueUsers.values()).map(
(item) => {
const recentMessages = messagesData.filter(
(message) =>
(message.uid === currentUserUID &&
message.recipientId === item.recipientId) ||
(message.uid === item.recipientId &&
message.recipientId === currentUserUID)
);
const sortedMessages = recentMessages.sort(
(a, b) => b.createdAt - a.createdAt
);
if (sortedMessages.length > 0) {
const recentMessage = sortedMessages[0];
return {
...item,
recentMessage: recentMessage.text,
recentMessageCreatedAt: recentMessage.createdAt,
};
} else {
// If there are no recent messages, set an empty string for the recentMessage field
return {
...item,
recentMessage: "",
recentMessageCreatedAt: null,
};
}
}
);
const sortedRecentChat = updatedRecentChat.sort((a, b) => {
if (a.recentMessageCreatedAt && b.recentMessageCreatedAt) {
return b.recentMessageCreatedAt - a.recentMessageCreatedAt;
} else if (a.recentMessageCreatedAt) {
return -1;
} else if (b.recentMessageCreatedAt) {
return 1;
} else {
return 0;
}
});
setRecentchat(sortedRecentChat);
} catch (error) {
return error;
}
};
And the same error occurs when individual chat is also made the code is provided below.
const sendMessage = async () => {
const { uid, displayName, photoURL } = auth.currentUser;
const newMessage = {
text: input,
name: displayName,
avatar: photoURL,
createdAt: serverTimestamp(),
uid: uid,
userName: userName,
senderName: senderName,
recipientId: recipientId,
};
try {
await addDoc(collection(db, "messages"), newMessage);
setInput("");
const newChatListEntry = {
uid: uid,
recipientId: recipientId,
userName: userName,
senderName: senderName,
email: email,
currentUserEmail: currentUserEmail,
};
await addDoc(collection(db, "chatlist"), newChatListEntry);
// Clear the message input field
} catch (error) {
console.error("Error adding document: ", error);
// Handle the error as needed
}
};
Please let me know where i am getting this wrong?