added ability to remove and add administrators

This commit is contained in:
slawk0
2024-12-21 13:23:24 +01:00
parent 9c98a88027
commit cab65b558b
5 changed files with 380 additions and 137 deletions

View File

@@ -122,7 +122,7 @@ function ContactForm({ InitializeContact, setContactsList }: ContactFormProps) {
<input <input
className="text-black bg-green-50 pl-2 shadow-lg rounded-md h-8 mb-2 mt-2" className="text-black bg-green-50 pl-2 shadow-lg rounded-md h-8 mb-2 mt-2"
type="text" type="text"
placeholder="Enter contact" placeholder="Search for user"
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
{...register('contact', { {...register('contact', {
minLength: 4, minLength: 4,

View File

@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import { axiosClient } from '@/App.tsx'; import { axiosClient } from '@/App.tsx';
import { ContactsProps } from '@/pages/Chat.tsx'; import { ContactsProps } from '@/pages/Chat.tsx';
import { socket } from '@/socket/socket.tsx'; import { socket } from '@/socket/socket.tsx';
import { Sword } from 'lucide-react'; import { Crown, Sword } from 'lucide-react';
import { import {
ContextMenu, ContextMenu,
ContextMenuContent, ContextMenuContent,
@@ -11,38 +11,35 @@ import {
} from '@/components/ui/context-menu'; } from '@/components/ui/context-menu';
import { UsernameType } from '@/utils/ProtectedRoutes.tsx'; import { UsernameType } from '@/utils/ProtectedRoutes.tsx';
import { useOutletContext } from 'react-router-dom'; import { useOutletContext } from 'react-router-dom';
import LoadingWheel from '@/components/chat/LoadingWheel.tsx';
type ParticipantsProps = { type ParticipantsProps = {
user_id: string; user_id: string;
username: string; username: string;
isadmin: boolean; isadmin: boolean;
isowner: boolean;
}; };
type ParticipantsBarProps = { type ParticipantsBarProps = {
contact: ContactsProps | null;
initializeContact: (contact: ContactsProps) => void; initializeContact: (contact: ContactsProps) => void;
currentContact: ContactsProps | null; currentContact: ContactsProps | null;
}; };
function ParticipantsBar({ function ParticipantsBar({
contact,
initializeContact, initializeContact,
currentContact, currentContact,
}: ParticipantsBarProps) { }: ParticipantsBarProps) {
const [participants, setParticipants] = useState<ParticipantsProps[]>([]); const [participants, setParticipants] = useState<ParticipantsProps[]>([]);
const [isGroupAdmin, setIsGroupAdmin] = useState<boolean>(false); const [isGroupAdmin, setIsGroupAdmin] = useState<boolean>(false);
const user: UsernameType = useOutletContext(); const user: UsernameType = useOutletContext();
const [isLoading, setIsLoading] = useState<boolean>(false);
const getParticipants = async () => { const getParticipants = async () => {
try { try {
const response = await axiosClient.get( const response = await axiosClient.get(
`/api/chat/groups/getMembers/${contact?.conversation_id}`, `/api/chat/groups/getMembers/${currentContact?.conversation_id}`,
); );
console.log( console.log(
'getParticipants for: ', 'getParticipants for: ',
contact?.conversation_id, currentContact?.conversation_id,
'response: ', 'response: ',
response.data, response.data,
); );
@@ -52,6 +49,60 @@ function ParticipantsBar({
} }
}; };
const handleRemoveUser = async (userId: string) => {
socket?.emit(
'remove user from group',
{
group_id: currentContact?.conversation_id,
user_id: userId,
},
(response: { status: 'ok' | 'error'; message: string }) => {
if (response.status == 'ok') {
console.log(response.message);
} else {
console.error('Failed to remove user from group: ', response.message);
}
},
);
// setParticipants((prevMembers) =>
// prevMembers.filter((member) => member.user_id !== userId),
// );
};
const handleAddToAdministrators = async (userId: string) => {
socket?.emit(
'added administrator',
{ group_id: currentContact?.conversation_id, user_id: userId },
(response: { status: 'ok' | 'error'; message: string }) => {
if (response.status == 'ok') {
console.log(response.message);
} else {
console.error(
'Failed to add user to administrators: ',
response.message,
);
}
},
);
};
const handleRemoveFromAdministrators = async (userId: string) => {
socket?.emit(
'removed administrator',
{ group_id: currentContact?.conversation_id, user_id: userId },
(response: { status: 'ok' | 'error'; message: string }) => {
if (response.status == 'ok') {
console.log(response.message);
} else {
console.error(
'Failed to remove user from administrators: ',
response.message,
);
}
},
);
};
useEffect(() => { useEffect(() => {
if (participants.length > 0 && user?.user_id) { if (participants.length > 0 && user?.user_id) {
const userIsAdmin = participants.some( const userIsAdmin = participants.some(
@@ -63,19 +114,20 @@ function ParticipantsBar({
}, [participants, user?.user_id]); }, [participants, user?.user_id]);
useEffect(() => { useEffect(() => {
if (contact) { if (currentContact) {
getParticipants(); getParticipants();
} }
}, [contact]); }, [currentContact]);
useEffect(() => { useEffect(() => {
if (!socket || !contact) return; if (!socket || !currentContact) return;
const handleAddedToGroup = (msg: { const handleAddedToGroup = (msg: {
username: string; username: string;
user_id: string; user_id: string;
group_id: string; group_id: string;
isadmin: false; isadmin: boolean;
isowner: boolean;
}) => { }) => {
const { group_id } = msg; const { group_id } = msg;
if ( if (
@@ -93,7 +145,7 @@ function ParticipantsBar({
}); });
} }
if (group_id === contact.conversation_id) { if (group_id === currentContact.conversation_id) {
setParticipants((prevMembers) => { setParticipants((prevMembers) => {
const existingMember = prevMembers.some( const existingMember = prevMembers.some(
(m) => m.user_id === msg.user_id, (m) => m.user_id === msg.user_id,
@@ -111,6 +163,7 @@ function ParticipantsBar({
msg.group_id == currentContact?.conversation_id && msg.group_id == currentContact?.conversation_id &&
msg.user_id == user?.user_id msg.user_id == user?.user_id
) { ) {
setParticipants([]);
initializeContact(currentContact); initializeContact(currentContact);
} }
setParticipants((prevMembers) => setParticipants((prevMembers) =>
@@ -118,6 +171,36 @@ function ParticipantsBar({
); );
}; };
const handleAddToAdmins = (msg: { user_id: string; group_id: string }) => {
if (msg.group_id === currentContact.conversation_id) {
setParticipants((prevMembers) =>
prevMembers.map((member) =>
member.user_id === msg.user_id
? { ...member, isadmin: true }
: member,
),
);
}
};
const handleRemoveFromAdmins = (msg: {
user_id: string;
group_id: string;
}) => {
console.log('(socket) removed administrator: ', msg);
if (msg.group_id === currentContact.conversation_id) {
setParticipants((prevMembers) =>
prevMembers.map((member) =>
member.user_id === msg.user_id
? { ...member, isadmin: false }
: member,
),
);
}
};
socket.on('added administrator', handleAddToAdmins);
socket.on('removed administrator', handleRemoveFromAdmins);
socket.on('added to group', handleAddedToGroup); socket.on('added to group', handleAddedToGroup);
socket.on('left group', handleLeftGroup); socket.on('left group', handleLeftGroup);
@@ -125,36 +208,7 @@ function ParticipantsBar({
socket?.off('added to group', handleAddedToGroup); socket?.off('added to group', handleAddedToGroup);
socket?.off('left group', handleLeftGroup); socket?.off('left group', handleLeftGroup);
}; };
}, [socket, contact, currentContact, user?.user_id]); }, [socket, currentContact, currentContact, user?.user_id]);
const handleRemoveUser = async (userId: string) => {
try {
setIsLoading(true);
socket?.emit(
'remove user from group',
{
group_id: contact?.conversation_id,
user_id: userId,
},
(response: { status: 'ok' | 'error'; message: string }) => {
if (response.status == 'ok') {
setIsLoading(false);
} else {
setIsLoading(false);
console.error(
'Failed to remove user from group: ',
response.message,
);
}
},
);
// setParticipants((prevMembers) =>
// prevMembers.filter((member) => member.user_id !== userId),
// );
} catch (error) {
console.error('Failed to remove user:', error);
}
};
const ParticipantsList = participants?.map( const ParticipantsList = participants?.map(
(participant: ParticipantsProps) => ( (participant: ParticipantsProps) => (
@@ -163,6 +217,11 @@ function ParticipantsBar({
<li className="p-2 hover:bg-gray-700 rounded-md flex items-center justify-between group"> <li className="p-2 hover:bg-gray-700 rounded-md flex items-center justify-between group">
<span className="flex items-center gap-2"> <span className="flex items-center gap-2">
{participant.username} {participant.username}
{participant.isowner ? (
<span className="flex items-center text-yellow-400 text-xs">
<Crown className="h-3 w-3" />
</span>
) : null}
{participant.isadmin && ( {participant.isadmin && (
<span className="flex items-center text-green-300 text-xs"> <span className="flex items-center text-green-300 text-xs">
<Sword className="h-3 w-3" /> <Sword className="h-3 w-3" />
@@ -174,21 +233,39 @@ function ParticipantsBar({
</span> </span>
</li> </li>
</ContextMenuTrigger> </ContextMenuTrigger>
{isGroupAdmin && user.user_id !== participant.user_id && ( {user.user_id !== participant.user_id && isGroupAdmin ? (
<ContextMenuContent className="p-0"> <ContextMenuContent className="p-0">
<ContextMenuItem <ContextMenuItem
className="bg-zinc-900 text-white outline-1 hover:bg-zinc-800 hover:cursor-pointer" className="bg-zinc-900 text-white outline-1 hover:bg-zinc-800 hover:cursor-pointer"
onClick={() => handleRemoveUser(participant.user_id)} onClick={() => handleRemoveUser(participant.user_id)}
> >
{isLoading ? <LoadingWheel /> : <p>Remove from group</p>} <p>Remove from group</p>
</ContextMenuItem> </ContextMenuItem>
{!participant.isadmin ? (
<ContextMenuItem
className="bg-zinc-900 text-white outline-1 hover:bg-zinc-800 hover:cursor-pointer"
onClick={() => handleAddToAdministrators(participant.user_id)}
>
<p>Add to group administrator</p>
</ContextMenuItem>
) : null}
{participant.isadmin ? (
<ContextMenuItem
className="bg-zinc-900 text-white outline-1 hover:bg-zinc-800 hover:cursor-pointer"
onClick={() =>
handleRemoveFromAdministrators(participant.user_id)
}
>
<p>Remove from administrator</p>
</ContextMenuItem>
) : null}
</ContextMenuContent> </ContextMenuContent>
)} ) : null}
</ContextMenu> </ContextMenu>
), ),
); );
if (!contact) { if (!currentContact) {
return null; return null;
} }

View File

@@ -238,7 +238,6 @@ function Chat() {
{currentContact?.type == 'group' ? ( {currentContact?.type == 'group' ? (
<div className="w-80 bg-[#1E1E1E] flex-shrink-0"> <div className="w-80 bg-[#1E1E1E] flex-shrink-0">
<ParticipantsBar <ParticipantsBar
contact={currentContact}
initializeContact={initializeContact} initializeContact={initializeContact}
currentContact={currentContact} currentContact={currentContact}
/> />

View File

@@ -112,54 +112,53 @@ async function createTables() {
// Create GroupAdmins Table with Trigger, referencing UUID // Create GroupAdmins Table with Trigger, referencing UUID
await client.query(` await client.query(`
-- Create the base table -- Create the GroupAdmins table with owner flag
CREATE TABLE IF NOT EXISTS GroupAdmins ( CREATE TABLE IF NOT EXISTS GroupAdmins (
conversation_id UUID NOT NULL REFERENCES Conversations(conversation_id) ON DELETE CASCADE, conversation_id UUID NOT NULL REFERENCES Conversations(conversation_id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES Accounts(user_id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES Accounts(user_id) ON DELETE CASCADE,
granted_by UUID NOT NULL REFERENCES Accounts(user_id) ON DELETE CASCADE, granted_by UUID NOT NULL REFERENCES Accounts(user_id) ON DELETE CASCADE,
granted_at TIMESTAMPTZ DEFAULT NOW(), granted_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (conversation_id, user_id) is_owner BOOLEAN DEFAULT FALSE,
); PRIMARY KEY (conversation_id, user_id),
-- Ensure only one owner per group
CONSTRAINT single_owner EXCLUDE USING btree (conversation_id WITH =)
WHERE (is_owner = true)
);
-- Create indexes -- Create indexes
CREATE INDEX IF NOT EXISTS idx_group_admins_conversation_id ON GroupAdmins (conversation_id); CREATE INDEX IF NOT EXISTS idx_group_admins_conversation_id ON GroupAdmins (conversation_id);
CREATE INDEX IF NOT EXISTS idx_group_admins_user_id ON GroupAdmins (user_id); CREATE INDEX IF NOT EXISTS idx_group_admins_user_id ON GroupAdmins (user_id);
CREATE INDEX IF NOT EXISTS idx_group_admins_owner ON GroupAdmins (conversation_id) WHERE is_owner = true;
-- Create the validation function -- Create the validation function
CREATE OR REPLACE FUNCTION validate_admin_grant() CREATE OR REPLACE FUNCTION validate_admin_grant()
RETURNS TRIGGER AS $$ RETURNS TRIGGER AS $$
BEGIN BEGIN
-- Allow self-grant for the first admin of a conversation -- Check if this is the first admin (owner) of the group
IF EXISTS ( IF NOT EXISTS (
SELECT 1 FROM GroupAdmins SELECT 1 FROM GroupAdmins
WHERE conversation_id = NEW.conversation_id WHERE conversation_id = NEW.conversation_id
) THEN ) THEN
-- For subsequent admins, verify that the granter is an admin -- First admin must be self-granted and marked as owner
IF NOT EXISTS ( IF NEW.granted_by != NEW.user_id THEN
SELECT 1 FROM GroupAdmins RAISE EXCEPTION 'First admin must be self-granted';
WHERE conversation_id = NEW.conversation_id END IF;
AND user_id = NEW.granted_by NEW.is_owner := true;
) THEN ELSE
RAISE EXCEPTION 'Only existing admins can grant admin privileges'; -- For non-owner admins, verify that the granter is an admin
END IF; IF NOT EXISTS (
ELSE SELECT 1 FROM GroupAdmins
-- For the first admin, only allow self-grant WHERE conversation_id = NEW.conversation_id
IF NEW.granted_by != NEW.user_id THEN AND user_id = NEW.granted_by
RAISE EXCEPTION 'First admin must be self-granted'; ) THEN
END IF; RAISE EXCEPTION 'Only existing admins can grant admin privileges';
END IF; END IF;
END IF;
RETURN NEW;
END; RETURN NEW;
$$ LANGUAGE plpgsql; END;
$$ LANGUAGE plpgsql;
-- Create the trigger `);
DROP TRIGGER IF EXISTS validate_admin_grant_trigger ON GroupAdmins;
CREATE TRIGGER validate_admin_grant_trigger
BEFORE INSERT OR UPDATE ON GroupAdmins
FOR EACH ROW
EXECUTE FUNCTION validate_admin_grant();
`);
console.log("Successfully created GroupAdmins table with trigger"); console.log("Successfully created GroupAdmins table with trigger");
} catch (e) { } catch (e) {
console.error("Failed to create tables: ", e); console.error("Failed to create tables: ", e);
@@ -252,8 +251,8 @@ async function createGroup(user_id, groupName) {
`; `;
const insertGroupAdminQuery = ` const insertGroupAdminQuery = `
INSERT INTO GroupAdmins (conversation_id, user_id, granted_by, granted_at) INSERT INTO GroupAdmins (conversation_id, user_id, granted_by, is_owner)
VALUES ($1, $2, $3, NOW()) VALUES ($1, $2, $3, true)
RETURNING granted_at; RETURNING granted_at;
`; `;
@@ -263,6 +262,7 @@ async function createGroup(user_id, groupName) {
]); ]);
const group_id = createConversation.rows[0].group_id; const group_id = createConversation.rows[0].group_id;
// Make the creator the owner and first admin
const insertGroupAdmin = await client.query(insertGroupAdminQuery, [ const insertGroupAdmin = await client.query(insertGroupAdminQuery, [
group_id, group_id,
user_id, user_id,
@@ -271,11 +271,6 @@ async function createGroup(user_id, groupName) {
if (insertGroupAdmin.rowCount > 0) { if (insertGroupAdmin.rowCount > 0) {
const contact_user_id = await addMemberToGroupById(group_id, user_id); const contact_user_id = await addMemberToGroupById(group_id, user_id);
// if (errorMessage) {
// console.error("You are not an admin of the conversation");
// return errorMessage;
// }
console.log("create group: ", group_id, contact_user_id);
insertContactById(user_id, group_id, true); insertContactById(user_id, group_id, true);
return { group_id, contact_user_id }; return { group_id, contact_user_id };
} }
@@ -857,7 +852,8 @@ async function getMembers(conversation_id) {
CASE CASE
WHEN ga.user_id IS NOT NULL THEN TRUE WHEN ga.user_id IS NOT NULL THEN TRUE
ELSE FALSE ELSE FALSE
END AS isAdmin END AS isAdmin,
COALESCE(ga.is_owner, FALSE) AS isOwner
FROM Memberships m FROM Memberships m
JOIN Accounts a ON m.user_id = a.user_id JOIN Accounts a ON m.user_id = a.user_id
LEFT JOIN GroupAdmins ga ON m.user_id = ga.user_id AND m.conversation_id = ga.conversation_id LEFT JOIN GroupAdmins ga ON m.user_id = ga.user_id AND m.conversation_id = ga.conversation_id
@@ -925,45 +921,34 @@ async function removeUserFromGroupById(conversation_id, user_id) {
WHERE conversation_id = $1 AND user_id = $2; WHERE conversation_id = $1 AND user_id = $2;
`; `;
// const removeConversationContactQuery = `
// DELETE FROM Contacts
// WHERE conversation_id = $1 AND user_id = $2;
// `;
try { try {
// First, remove the user from the Memberships table // Check if the user being removed is the owner
const isOwner = await isGroupOwner(user_id, conversation_id);
if (isOwner) {
return { message: "Cannot remove the group owner" };
}
const removeMembershipResult = await client.query( const removeMembershipResult = await client.query(
removeUserFromGroupQuery, removeUserFromGroupQuery,
[conversation_id, user_id], [conversation_id, user_id],
); );
if (removeMembershipResult.rowCount === 0) { if (removeMembershipResult.rowCount === 0) {
console.log(
`No membership found for user_id: ${user_id} in conversation_id: ${conversation_id}`,
);
return { return {
message: `No membership found for user_id: ${user_id} in conversation_id: ${conversation_id}`, message: `No membership found for user_id: ${user_id} in conversation_id: ${conversation_id}`,
}; };
} }
// Then, remove the user from the Contacts table // Also remove from GroupAdmins if they were an admin
// const removeContactResult = await client.query(removeConversationContactQuery, [ await client.query(
// conversation_id, `
// user_id, DELETE FROM GroupAdmins
// ]); WHERE conversation_id = $1 AND user_id = $2;
// `,
// if (removeContactResult.rowCount === 0) { [conversation_id, user_id],
// console.log(
// `No contact found for user_id: ${user_id} in conversation_id: ${conversation_id}`,
// );
// return {
// message: `No contact found for user_id: ${user_id} in conversation_id: ${conversation_id}`,
// };
// }
console.log(
`Successfully removed user_id: ${user_id} from conversation_id: ${conversation_id}`,
); );
return null;
} catch (e) { } catch (e) {
console.error("Failed to remove user from group ", e); console.error("Failed to remove user from group ", e);
return { return {
@@ -995,6 +980,114 @@ async function isConversationMember(user_id, conversation_id) {
} }
} }
async function addAdministrator(conversation_id, user_id, granted_by) {
const checkMembershipQuery = `
SELECT 1 FROM Memberships
WHERE conversation_id = $1 AND user_id = $2
LIMIT 1;
`;
const addAdminQuery = `
INSERT INTO GroupAdmins (conversation_id, user_id, granted_by, is_owner)
VALUES ($1, $2, $3, false)
RETURNING granted_at;
`;
try {
// Check if the granter is the owner
const isOwner = await isGroupOwner(granted_by, conversation_id);
if (!isOwner) {
console.error("Only the group owner can add administrators");
return { message: "Only the group owner can add administrators" };
}
// Check if user is a member
const membershipCheck = await client.query(checkMembershipQuery, [
conversation_id,
user_id,
]);
if (membershipCheck.rows.length === 0) {
console.error("User is not a member of the conversation");
return { message: "User is not a member of this conversation" };
}
const result = await client.query(addAdminQuery, [
conversation_id,
user_id,
granted_by,
]);
console.log("User added as admin successfully");
return result.rows[0].granted_at;
} catch (e) {
console.error("Failed to add administrator ", e);
return { message: "Failed to add administrator" };
}
}
async function removeAdministrator(conversation_id, user_id, removed_by) {
const removeAdminQuery = `
DELETE FROM GroupAdmins
WHERE conversation_id = $1
AND user_id = $2
RETURNING user_id;
`;
const checkMembershipQuery = `
SELECT 1 FROM Memberships
WHERE conversation_id = $1 AND user_id = $2
LIMIT 1;
`;
try {
const isOwner = await isGroupOwner(removed_by, conversation_id);
if (!isOwner) {
console.error("Only the group owner can remove administrators");
return { message: "Only the group owner can remove administrators" };
}
const membershipCheck = await client.query(checkMembershipQuery, [
conversation_id,
user_id,
]);
if (membershipCheck.rows.length === 0) {
console.error("User is not a member of the conversation");
return { message: "User is not a member of this group" };
}
const removeAdminResult = await client.query(removeAdminQuery, [
conversation_id,
user_id,
]);
if (removeAdminResult.rows.length > 0) {
return null;
} else {
return { message: "User is not an administrator of this group" };
}
} catch (e) {
console.error("Failed to remove administrator ", e);
return { message: "Failed to remove administrator" };
}
}
async function isGroupOwner(user_id, conversation_id) {
const query = `
SELECT EXISTS (
SELECT 1 FROM GroupAdmins
WHERE conversation_id = $1
AND user_id = $2
AND is_owner = true
) AS is_owner;
`;
try {
const result = await client.query(query, [conversation_id, user_id]);
return result.rows[0].is_owner;
} catch (e) {
console.error("Failed to check owner status", e);
return false;
}
}
module.exports = { module.exports = {
client, client,
insertUser, insertUser,
@@ -1017,4 +1110,6 @@ module.exports = {
removeUserFromGroupById, removeUserFromGroupById,
isConversationMember, isConversationMember,
isAdmin, isAdmin,
addAdministrator,
removeAdministrator,
}; };

View File

@@ -5,11 +5,12 @@ const {
deleteMessage, deleteMessage,
removeUserFromGroupById, removeUserFromGroupById,
isConversationMember, isConversationMember,
isAdmin,
addAdministrator,
removeAdministrator,
} = require("../db/db"); } = require("../db/db");
const { isValidUsername } = require("../utils/filter"); const { isValidUsername } = require("../utils/filter");
const { verifyJwtToken } = require("../auth/jwt"); const { verifyJwtToken } = require("../auth/jwt");
const console = require("node:console");
const { call } = require("express");
function initializeSocket(io) { function initializeSocket(io) {
io.use((socket, next) => { io.use((socket, next) => {
@@ -226,11 +227,11 @@ function initializeSocket(io) {
socket.on("remove user from group", async (msg, callback) => { socket.on("remove user from group", async (msg, callback) => {
const { group_id, user_id } = msg; const { group_id, user_id } = msg;
if (!group_id || !user_id) { if (!group_id) {
return callback({ return callback({ status: "error", message: "No group id provided" });
status: "error", }
message: "Missing required parameters", if (!user_id) {
}); return callback({ status: "error", message: "No user id provided" });
} }
try { try {
@@ -242,7 +243,7 @@ function initializeSocket(io) {
// Get all sockets in the room // Get all sockets in the room
const socketsInRoom = await io.in(group_id).fetchSockets(); const socketsInRoom = await io.in(group_id).fetchSockets();
// Remove user from room
for (const socketInstance of socketsInRoom) { for (const socketInstance of socketsInRoom) {
if (socketInstance.user_id === user_id) { if (socketInstance.user_id === user_id) {
socketInstance.leave(group_id); socketInstance.leave(group_id);
@@ -253,7 +254,9 @@ function initializeSocket(io) {
group_id, group_id,
user_id, user_id,
}); });
console.log(
`Successfully removed user: ${user_id}, from group: ${group_id}`,
);
return callback({ return callback({
status: "ok", status: "ok",
message: "Successfully removed user from group", message: "Successfully removed user from group",
@@ -267,6 +270,75 @@ function initializeSocket(io) {
} }
}); });
socket.on("added administrator", async (msg, callback) => {
const { group_id, user_id } = msg;
if (!group_id) {
return callback({
status: "error",
message: "No conversation id provided",
});
}
if (!user_id) {
return callback({ status: "error", message: "No user id provided" });
}
const isUserAdmin = await isAdmin(socket.user_id, group_id);
if (!isUserAdmin) {
return callback({
status: "error",
message: "You is not an administrator",
});
}
const result = await addAdministrator(group_id, user_id, socket.user_id);
if (result?.message) {
return callback({ status: "error", message: result.message });
}
console.log(
`Successfully added user: ${user_id} to administrators to group: ${group_id}`,
);
io.to(group_id).emit("added administrator", {
group_id,
user_id,
});
return callback({
status: "ok",
message: "Successfully added administrator",
});
});
socket.on("removed administrator", async (msg, callback) => {
const { group_id, user_id } = msg;
if (!group_id) {
return callback({
status: "error",
message: "No conversation id provided",
});
}
if (!user_id) {
return callback({ status: "error", message: "No user id provided" });
}
const result = await removeAdministrator(
group_id,
user_id,
socket.user_id,
);
if (result?.message) {
return callback({ status: "error", message: result.message });
}
console.log(
`Successfully removed user: ${user_id} from administrators in group: ${group_id}`,
);
io.to(group_id).emit("removed administrator", {
group_id,
user_id,
});
return callback({
status: "ok",
message: "Successfully removed administrator",
});
});
socket.on("disconnect", (reason) => { socket.on("disconnect", (reason) => {
console.log("(socket)", socket.id, " disconnected due to: ", reason); console.log("(socket)", socket.id, " disconnected due to: ", reason);
}); });