import { AppEvents, Apps } from '@rocket.chat/apps'; import { MeteorError, Team } from '@rocket.chat/core-services'; import type { IRoom, ITeam, IUser, AtLeast } from '@rocket.chat/core-typings'; import { Rooms } from '@rocket.chat/models'; import { eraseRoom } from '../../lib/eraseRoom'; import { SystemLogger } from '../../lib/logger/system'; import { deleteRoom } from '../../lib/rooms/deleteRoom'; type EraseRoomFnType = >(rid: string, user: T) => Promise; export const eraseTeamShared = async >( user: T, team: ITeam, roomsToRemove: IRoom['_id'][] = [], eraseRoomFn: EraseRoomFnType, ) => { const rooms: string[] = roomsToRemove.length ? (await Team.getMatchingTeamRooms(team._id, roomsToRemove)).filter((roomId) => roomId !== team.roomId) : []; if (!user) { throw new MeteorError('Invalid user provided for erasing team', 'error-invalid-user', { method: 'eraseTeamShared', }); } // If we got a list of rooms to delete along with the team, remove them first await Promise.all(rooms.map((room) => eraseRoomFn(room, user))); // Move every other room back to the workspace await Team.unsetTeamIdOfRooms(user, team); const room = await Rooms.findOneById>(team.roomId, { projection: { _id: 1 } }); if (room) { await eraseRoomFn(team.roomId, user); } // Delete all team memberships await Team.removeAllMembersFromTeam(team._id); // And finally delete the team itself await Team.deleteById(team._id); }; export const eraseTeam = async (user: IUser, team: ITeam, roomsToRemove: IRoom['_id'][]) => { await eraseTeamShared(user, team, roomsToRemove, async (rid, user) => { return eraseRoom(rid, user); }); }; /** * @param team * @param roomsToRemove * @returns deleted room ids */ export const eraseTeamOnRelinquishRoomOwnerships = async (team: ITeam, roomsToRemove: IRoom['_id'][] = []): Promise => { const deletedRooms = new Set(); await eraseTeamShared({ _id: 'rocket.cat', username: 'rocket.cat', name: 'Rocket.Cat' } as IUser, team, roomsToRemove, async (rid) => { const isDeleted = await eraseRoomLooseValidation(rid); if (isDeleted) { deletedRooms.add(rid); } }); return Array.from(deletedRooms); }; export async function eraseRoomLooseValidation(rid: string): Promise { const room = await Rooms.findOneById(rid); if (!room) { return false; } if (room.federated) { return false; } if (Apps.self?.isLoaded()) { const prevent = await Apps.self?.triggerEvent(AppEvents.IPreRoomDeletePrevent, room); if (prevent) { return false; } } try { await deleteRoom(rid); } catch (err) { SystemLogger.error({ err }); return false; } if (Apps.self?.isLoaded()) { void Apps.self?.triggerEvent(AppEvents.IPostRoomDeleted, room); } return true; }