fixed (I hope so) insertContact function
This commit is contained in:
@@ -15,7 +15,10 @@ function ContactProfile() {
|
|||||||
<img className="w-4 mr-2 invert" src={profile} alt="profile img" />
|
<img className="w-4 mr-2 invert" src={profile} alt="profile img" />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<p>{currentContact ? currentContact.username : null}</p>
|
<p>
|
||||||
|
{currentContact ? currentContact.username : null} user id:{' '}
|
||||||
|
{currentContact?.user_id} conv id: {currentContact?.conversation_id}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-grow"></div>
|
<div className="flex-grow"></div>
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
setUser({ username: res.data.username, id: res.data.user_id });
|
setUser({ username: res.data.username, id: res.data.user_id });
|
||||||
|
console.info('user: : ', {
|
||||||
|
username: res.data.username,
|
||||||
|
id: res.data.user_id,
|
||||||
|
});
|
||||||
setAuthorized(true);
|
setAuthorized(true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setAuthorized(false);
|
setAuthorized(false);
|
||||||
|
|||||||
301
server/db/db.js
301
server/db/db.js
@@ -474,14 +474,37 @@ async function changePassword(username, newPasswordHash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function insertContactById(senderId, conversation_id, read) {
|
async function insertContactById(senderId, conversation_id, read) {
|
||||||
const query = `
|
// First check if contact already exists
|
||||||
INSERT INTO Contacts (user_id, conversation_id, read)
|
const checkQuery = `
|
||||||
VALUES( $1, $2, $3)
|
SELECT contact_id, conversation_id, user_id, read, last_active
|
||||||
|
FROM Contacts
|
||||||
|
WHERE user_id = $1 AND conversation_id = $2
|
||||||
`;
|
`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await client.query(query, [senderId, conversation_id, read]);
|
// Check if contact already exists
|
||||||
console.log("Insertcontactbyid: ", senderId, conversation_id);
|
const existingContact = await client.query(checkQuery, [
|
||||||
|
senderId,
|
||||||
|
conversation_id,
|
||||||
|
]);
|
||||||
|
if (existingContact.rows.length > 0) {
|
||||||
|
console.log("Contact already exists:", senderId, conversation_id);
|
||||||
|
return existingContact.rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If contact doesn't exist, create new one
|
||||||
|
const insertQuery = `
|
||||||
|
INSERT INTO Contacts (user_id, conversation_id, read)
|
||||||
|
VALUES($1, $2, $3)
|
||||||
|
RETURNING contact_id, conversation_id, user_id, read, last_active
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await client.query(insertQuery, [
|
||||||
|
senderId,
|
||||||
|
conversation_id,
|
||||||
|
read,
|
||||||
|
]);
|
||||||
|
console.log("Insert contact by id:", senderId, conversation_id);
|
||||||
return result.rows[0] || null;
|
return result.rows[0] || null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to insert contact by IDs:", error);
|
console.error("Failed to insert contact by IDs:", error);
|
||||||
@@ -489,49 +512,35 @@ async function insertContactById(senderId, conversation_id, read) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function insertContact(userUsername, receiverUsername, read) {
|
async function insertContact(initiatorId, receiverId, contactUsername, read) {
|
||||||
try {
|
try {
|
||||||
// 1. Get user IDs
|
|
||||||
const getUsersQuery = `
|
|
||||||
SELECT
|
|
||||||
u1.user_id AS initiator_id,
|
|
||||||
u1.username AS initiator_username,
|
|
||||||
u2.user_id AS contact_id,
|
|
||||||
u2.username AS contact_username
|
|
||||||
FROM Accounts u1
|
|
||||||
CROSS JOIN Accounts u2
|
|
||||||
WHERE LOWER(u1.username) = LOWER($1)
|
|
||||||
AND LOWER(u2.username) = LOWER($2)
|
|
||||||
`;
|
|
||||||
const usersResult = await client.query(getUsersQuery, [
|
|
||||||
userUsername,
|
|
||||||
receiverUsername,
|
|
||||||
]);
|
|
||||||
if (!usersResult.rows[0]) {
|
|
||||||
console.error("Users not found");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const { initiator_id, contact_id, contact_username } = usersResult.rows[0];
|
|
||||||
|
|
||||||
// 2. Find existing conversation
|
|
||||||
const findConversationQuery = `
|
const findConversationQuery = `
|
||||||
SELECT c.conversation_id
|
SELECT c.conversation_id
|
||||||
FROM Conversations c
|
FROM Conversations c
|
||||||
JOIN Memberships m1 ON c.conversation_id = m1.conversation_id
|
JOIN Memberships m1 ON c.conversation_id = m1.conversation_id
|
||||||
JOIN Memberships m2 ON c.conversation_id = m2.conversation_id
|
JOIN Memberships m2 ON c.conversation_id = m2.conversation_id
|
||||||
WHERE c.conversation_type = 'direct'
|
WHERE c.conversation_type = 'direct'
|
||||||
AND m1.user_id = $1
|
AND (
|
||||||
AND m2.user_id = $2
|
(m1.user_id = $1 AND m2.user_id = $2)
|
||||||
LIMIT 1
|
OR
|
||||||
|
(m1.user_id = $2 AND m2.user_id = $1)
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
SELECT COUNT(DISTINCT user_id)
|
||||||
|
FROM Memberships
|
||||||
|
WHERE conversation_id = c.conversation_id
|
||||||
|
) = 1 -- Allow a conversation with a single user (self)
|
||||||
|
LIMIT 1
|
||||||
`;
|
`;
|
||||||
const conversationResult = await client.query(findConversationQuery, [
|
const conversationResult = await client.query(findConversationQuery, [
|
||||||
initiator_id,
|
initiatorId,
|
||||||
contact_id,
|
receiverId,
|
||||||
]);
|
]);
|
||||||
let conversation_id = conversationResult.rows[0]?.conversation_id;
|
let conversation_id = conversationResult.rows[0]?.conversation_id;
|
||||||
|
|
||||||
// 3. Create new conversation if none exists
|
// Create new conversation if none exists
|
||||||
if (!conversation_id) {
|
if (!conversation_id) {
|
||||||
|
console.error("CONVERSATION DON'T EXIST: ", conversation_id);
|
||||||
const createConversationQuery = `
|
const createConversationQuery = `
|
||||||
INSERT INTO Conversations (conversation_type)
|
INSERT INTO Conversations (conversation_type)
|
||||||
VALUES ('direct')
|
VALUES ('direct')
|
||||||
@@ -539,8 +548,8 @@ async function insertContact(userUsername, receiverUsername, read) {
|
|||||||
`;
|
`;
|
||||||
const newConversationResult = await client.query(createConversationQuery);
|
const newConversationResult = await client.query(createConversationQuery);
|
||||||
conversation_id = newConversationResult.rows[0].conversation_id;
|
conversation_id = newConversationResult.rows[0].conversation_id;
|
||||||
|
console.error("NEW CONVERSATION ID: ", conversation_id);
|
||||||
// 4. Create memberships for both users
|
// Create memberships for both users (or single user if they are the same)
|
||||||
const createMembershipsQuery = `
|
const createMembershipsQuery = `
|
||||||
INSERT INTO Memberships (conversation_id, user_id)
|
INSERT INTO Memberships (conversation_id, user_id)
|
||||||
VALUES ($1, $2), ($1, $3)
|
VALUES ($1, $2), ($1, $3)
|
||||||
@@ -548,27 +557,18 @@ async function insertContact(userUsername, receiverUsername, read) {
|
|||||||
`;
|
`;
|
||||||
await client.query(createMembershipsQuery, [
|
await client.query(createMembershipsQuery, [
|
||||||
conversation_id,
|
conversation_id,
|
||||||
initiator_id,
|
initiatorId,
|
||||||
contact_id,
|
receiverId,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Create or update contact
|
const contact = await insertContactById(initiatorId, conversation_id, read);
|
||||||
const upsertContactQuery = `
|
if (!contact.contact_id) {
|
||||||
INSERT INTO Contacts (user_id, conversation_id, read)
|
console.error("Failed to insert contact by id");
|
||||||
VALUES ($1, $2, $3)
|
return null;
|
||||||
ON CONFLICT (user_id, conversation_id)
|
}
|
||||||
DO UPDATE SET last_active = CURRENT_TIMESTAMP, read = $3
|
|
||||||
RETURNING contact_id, conversation_id, user_id, read, last_active
|
|
||||||
`;
|
|
||||||
const contactResult = await client.query(upsertContactQuery, [
|
|
||||||
initiator_id,
|
|
||||||
conversation_id,
|
|
||||||
read,
|
|
||||||
]);
|
|
||||||
const contact = contactResult.rows[0];
|
|
||||||
|
|
||||||
// 6. Retrieve the last message, last active time, and last message sender
|
// Retrieve the last message, last active time, and last message sender
|
||||||
const lastMessageQuery = `
|
const lastMessageQuery = `
|
||||||
SELECT DISTINCT ON (m.conversation_id)
|
SELECT DISTINCT ON (m.conversation_id)
|
||||||
m.content AS last_message,
|
m.content AS last_message,
|
||||||
@@ -590,18 +590,18 @@ async function insertContact(userUsername, receiverUsername, read) {
|
|||||||
lastMessageSender = lastMessageResult.rows[0].last_message_sender;
|
lastMessageSender = lastMessageResult.rows[0].last_message_sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Return formatted result with contact's user_id, last message, last active time, and last message sender
|
// Return formatted result with contact's user_id, last message, last active time, and last message sender
|
||||||
return {
|
return {
|
||||||
id: contact.contact_id,
|
id: contact.contact_id,
|
||||||
user_id: contact_id, // Now using the contact's user_id instead of the initiator's
|
user_id: receiverId, // Now using the contact's user_id instead of the initiator's
|
||||||
username: contact_username,
|
username: contactUsername,
|
||||||
last_active: contact.last_active,
|
last_active: contact.last_active,
|
||||||
conversation_id: contact.conversation_id,
|
conversation_id: contact.conversation_id,
|
||||||
type: "direct",
|
type: "direct",
|
||||||
read: contact.read,
|
read: contact.read,
|
||||||
last_message: lastMessage,
|
last_message: lastMessage || null,
|
||||||
last_message_time: lastMessageTime,
|
last_message_time: lastMessageTime || null,
|
||||||
last_message_sender: lastMessageSender,
|
last_message_sender: lastMessageSender || null,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to insert contact:", error);
|
console.error("Failed to insert contact:", error);
|
||||||
@@ -609,53 +609,158 @@ async function insertContact(userUsername, receiverUsername, read) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getLatestMessage(conversation_id) {
|
||||||
|
const latestMessageQuery = `
|
||||||
|
WITH LatestMessage AS (
|
||||||
|
SELECT
|
||||||
|
m.message_id as id,
|
||||||
|
m.user_id,
|
||||||
|
m.content as last_message,
|
||||||
|
m.sent_at as last_message_time,
|
||||||
|
a.username as last_message_sender
|
||||||
|
FROM Messages m
|
||||||
|
JOIN Accounts a ON m.user_id = a.user_id
|
||||||
|
WHERE m.conversation_id = $1
|
||||||
|
ORDER BY m.sent_at DESC
|
||||||
|
LIMIT 1
|
||||||
|
),
|
||||||
|
ConversationUsers AS (
|
||||||
|
SELECT
|
||||||
|
m.user_id,
|
||||||
|
a.username,
|
||||||
|
c.read
|
||||||
|
FROM Memberships m
|
||||||
|
JOIN Accounts a ON m.user_id = a.user_id
|
||||||
|
LEFT JOIN Contacts c ON c.user_id = m.user_id AND c.conversation_id = $1
|
||||||
|
WHERE m.conversation_id = $1
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
lm.*,
|
||||||
|
cu.user_id,
|
||||||
|
cu.username,
|
||||||
|
cu.read,
|
||||||
|
c.conversation_type as type,
|
||||||
|
c.last_active,
|
||||||
|
c.conversation_id
|
||||||
|
FROM Conversations c
|
||||||
|
LEFT JOIN LatestMessage lm ON TRUE
|
||||||
|
LEFT JOIN ConversationUsers cu ON TRUE
|
||||||
|
WHERE c.conversation_id = $1;
|
||||||
|
`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get latest message and details
|
||||||
|
const result = await client.query(latestMessageQuery, [conversation_id]);
|
||||||
|
|
||||||
|
if (result.rows.length === 0) {
|
||||||
|
console.error("No messages found in conversation:", conversation_id);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const row = result.rows[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
user_id: row.user_id,
|
||||||
|
username: row.username,
|
||||||
|
last_active: row.last_active,
|
||||||
|
conversation_id: row.conversation_id,
|
||||||
|
type: row.type,
|
||||||
|
read: row.read,
|
||||||
|
last_message: row.last_message,
|
||||||
|
last_message_time: row.last_message_time,
|
||||||
|
last_message_sender: row.last_message_sender,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get latest message:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkMembership(user_id, conversation_id) {
|
||||||
|
const query = `
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM Memberships
|
||||||
|
WHERE user_id = $1
|
||||||
|
AND conversation_id = $2
|
||||||
|
) AS is_member;
|
||||||
|
`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await client.query(query, [user_id, conversation_id]);
|
||||||
|
return result.rows[0].is_member;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error checking membership:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function getContacts(user_id) {
|
async function getContacts(user_id) {
|
||||||
const contactsQuery = `
|
const contactsQuery = `
|
||||||
WITH LastMessages AS (
|
WITH LastMessages AS (
|
||||||
SELECT DISTINCT ON (m.conversation_id)
|
SELECT DISTINCT ON (m.conversation_id)
|
||||||
m.conversation_id,
|
m.conversation_id,
|
||||||
m.content as last_message,
|
m.content AS last_message,
|
||||||
m.sent_at as last_message_time,
|
m.sent_at AS last_message_time,
|
||||||
a.username as last_message_sender
|
a.username AS last_message_sender
|
||||||
FROM Messages m
|
FROM Messages m
|
||||||
JOIN Accounts a ON m.user_id = a.user_id
|
JOIN Accounts a ON m.user_id = a.user_id
|
||||||
ORDER BY m.conversation_id, m.sent_at DESC
|
ORDER BY m.conversation_id, m.sent_at DESC
|
||||||
|
),
|
||||||
|
DirectContacts AS (
|
||||||
|
SELECT
|
||||||
|
c.contact_id AS id,
|
||||||
|
a.user_id AS user_id,
|
||||||
|
a.username AS username,
|
||||||
|
conv.last_active,
|
||||||
|
c.conversation_id,
|
||||||
|
conv.conversation_type AS type,
|
||||||
|
c.read,
|
||||||
|
lm.last_message,
|
||||||
|
lm.last_message_time,
|
||||||
|
lm.last_message_sender
|
||||||
|
FROM Contacts c
|
||||||
|
JOIN Conversations conv ON c.conversation_id = conv.conversation_id
|
||||||
|
JOIN Memberships m ON m.conversation_id = c.conversation_id
|
||||||
|
JOIN Accounts a ON a.user_id = m.user_id
|
||||||
|
LEFT JOIN LastMessages lm ON c.conversation_id = lm.conversation_id
|
||||||
|
WHERE c.user_id = $1
|
||||||
|
AND conv.conversation_type = 'direct'
|
||||||
|
AND a.user_id != $1
|
||||||
|
ORDER BY c.conversation_id, conv.last_active DESC
|
||||||
|
),
|
||||||
|
GroupContacts AS (
|
||||||
|
SELECT
|
||||||
|
c.contact_id AS id,
|
||||||
|
NULL::uuid AS user_id,
|
||||||
|
conv.name AS username,
|
||||||
|
conv.last_active,
|
||||||
|
c.conversation_id,
|
||||||
|
conv.conversation_type AS type,
|
||||||
|
c.read,
|
||||||
|
lm.last_message,
|
||||||
|
lm.last_message_time,
|
||||||
|
lm.last_message_sender
|
||||||
|
FROM Contacts c
|
||||||
|
JOIN Conversations conv ON c.conversation_id = conv.conversation_id
|
||||||
|
LEFT JOIN LastMessages lm ON c.conversation_id = lm.conversation_id
|
||||||
|
WHERE c.user_id = $1
|
||||||
|
AND conv.conversation_type = 'group'
|
||||||
|
ORDER BY c.conversation_id, conv.last_active DESC
|
||||||
)
|
)
|
||||||
SELECT DISTINCT ON (c.conversation_id)
|
SELECT * FROM DirectContacts
|
||||||
c.contact_id AS id,
|
UNION ALL
|
||||||
CASE
|
SELECT * FROM GroupContacts
|
||||||
WHEN conv.conversation_type = 'group' THEN NULL
|
ORDER BY last_active DESC;
|
||||||
ELSE a2.user_id
|
|
||||||
END AS user_id,
|
|
||||||
CASE
|
|
||||||
WHEN conv.conversation_type = 'group' THEN conv.name
|
|
||||||
ELSE a2.username
|
|
||||||
END AS username,
|
|
||||||
conv.last_active,
|
|
||||||
c.conversation_id,
|
|
||||||
conv.conversation_type AS type,
|
|
||||||
c.read,
|
|
||||||
lm.last_message,
|
|
||||||
lm.last_message_time,
|
|
||||||
lm.last_message_sender
|
|
||||||
FROM Contacts c
|
|
||||||
JOIN Conversations conv ON c.conversation_id = conv.conversation_id
|
|
||||||
JOIN Memberships m ON m.conversation_id = c.conversation_id
|
|
||||||
JOIN Accounts a2 ON a2.user_id = m.user_id
|
|
||||||
LEFT JOIN LastMessages lm ON c.conversation_id = lm.conversation_id
|
|
||||||
WHERE c.user_id = $1
|
|
||||||
AND (
|
|
||||||
conv.conversation_type = 'direct'
|
|
||||||
OR
|
|
||||||
conv.conversation_type = 'group'
|
|
||||||
)
|
|
||||||
ORDER BY c.conversation_id, conv.last_active DESC;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Execute the query with the user_id parameter
|
// Execute the query with the user_id parameter
|
||||||
const contactsResult = await client.query(contactsQuery, [user_id]);
|
const contactsResult = await client.query(contactsQuery, [user_id]);
|
||||||
console.error(contactsResult.rows);
|
console.log(contactsResult.rows); // Debugging: log the results to verify
|
||||||
|
|
||||||
// Map the results to a more friendly format
|
// Map the results to a more friendly format
|
||||||
const contacts = contactsResult.rows.map((row) => ({
|
const contacts = contactsResult.rows.map((row) => ({
|
||||||
id: row.id,
|
id: row.id,
|
||||||
|
|||||||
@@ -250,17 +250,22 @@ app.post("/api/chat/contact/:contact", authorizeUser, async (req, res) => {
|
|||||||
if (!req.params.contact) {
|
if (!req.params.contact) {
|
||||||
return res.status(400).json({ message: "Missing contact parameter" });
|
return res.status(400).json({ message: "Missing contact parameter" });
|
||||||
}
|
}
|
||||||
const usernameContact = req.params.contact;
|
const contactUsername = req.params.contact;
|
||||||
|
|
||||||
// Validate username for invalid characters, length, and type
|
// Validate username for invalid characters, length, and type
|
||||||
if (!isValidUsername(usernameContact)) {
|
if (!isValidUsername(contactUsername)) {
|
||||||
return res.status(400).json({ message: "Invalid username provided" });
|
return res.status(400).json({ message: "Invalid username provided" });
|
||||||
}
|
}
|
||||||
|
// Get contact user id and check if exist
|
||||||
|
const contact = await getUserId(contactUsername);
|
||||||
|
if (!contact) {
|
||||||
|
return res.status(400).json({ message: "User does not exist" });
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await insertContact(
|
const result = await insertContact(
|
||||||
req.user.username,
|
req.user.user_id,
|
||||||
usernameContact,
|
contact.user_id,
|
||||||
|
contactUsername,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user