Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions apps/meteor/app/api/server/v1/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,18 @@ API.v1.addRoute(
},
},
);

API.v1.addRoute(
'rooms.delete',
{
authRequired: true,
},
{
post() {
const { roomId } = this.bodyParams;

Meteor.call('eraseRoom', roomId);
return API.v1.success();
},
},
);
14 changes: 3 additions & 11 deletions apps/meteor/client/views/admin/rooms/EditRoom.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { IRoom, RoomAdminFieldsType } from '@rocket.chat/core-typings';
import { Box, Button, ButtonGroup, TextInput, Field, ToggleSwitch, Icon, TextAreaInput } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import {
useSetModal,
useToastMessageDispatch,
useRoute,
usePermission,
useEndpoint,
useMethod,
useTranslation,
} from '@rocket.chat/ui-contexts';
import { useSetModal, useToastMessageDispatch, useRoute, usePermission, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts';
import React, { useState, useMemo, ReactElement } from 'react';

import { RoomSettingsEnum } from '../../../../definition/IRoomTypeConfig';
Expand Down Expand Up @@ -148,7 +140,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps): ReactElement =>
handleRoomType(roomType === 'p' ? 'c' : 'p');
});

const eraseRoom = useMethod('eraseRoom');
const deleteRoom = useEndpoint('POST', '/v1/rooms.delete');
const deleteTeam = useEndpoint('POST', '/v1/teams.delete');

const handleDelete = useMutableCallback(() => {
Expand Down Expand Up @@ -186,7 +178,7 @@ const EditRoom = ({ room, onChange, onDelete }: EditRoomProps): ReactElement =>
try {
setDeleting(true);
setModal(null);
await eraseRoom(room._id);
await deleteRoom({ roomId: room._id });
dispatchToastMessage({ type: 'success', message: t('Room_has_been_deleted') });
roomsRoute.push({});
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';

import { deleteRoom } from '../../app/lib';
import { methodDeprecationLogger } from '../../app/lib/server/lib/deprecationWarningLogger';
import { deleteRoom } from '../../app/lib/server/functions/deleteRoom';
import { hasPermission } from '../../app/authorization/server';
import { Rooms, Messages } from '../../app/models/server';
import { Apps } from '../../app/apps/server';
import { roomCoordinator } from '../lib/rooms/roomCoordinator';
import { Team } from '../sdk';

Meteor.methods({
eraseRoom(rid) {
async eraseRoom(rid: string) {
check(rid, String);

if (!Meteor.userId()) {
methodDeprecationLogger.warn('eraseRoom will be deprecated in future versions of Rocket.Chat');

const uid = Meteor.userId();

if (!uid) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'eraseRoom',
});
Expand All @@ -32,35 +37,32 @@ Meteor.methods({
});
}

if (
!roomCoordinator
.getRoomDirectives(room.t)
?.canBeDeleted((permissionId, rid) => hasPermission(Meteor.userId(), permissionId, rid), room)
) {
if (!roomCoordinator.getRoomDirectives(room.t)?.canBeDeleted((permissionId, rid) => hasPermission(uid, permissionId, rid), room)) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'eraseRoom',
});
}

if (Apps && Apps.isLoaded()) {
const prevent = Promise.await(Apps.getBridges().getListenerBridge().roomEvent('IPreRoomDeletePrevent', room));
if (Apps?.isLoaded()) {
const prevent = Promise.await(Apps.getBridges()?.getListenerBridge().roomEvent('IPreRoomDeletePrevent', room));
if (prevent) {
throw new Meteor.Error('error-app-prevented-deleting', 'A Rocket.Chat App prevented the room erasing.');
}
}

const result = deleteRoom(rid);
deleteRoom(rid);

const team = room.teamId && (await Team.getOneById(room.teamId));

if (room.teamId) {
const team = Promise.await(Team.getOneById(room.teamId));
if (team) {
const user = Meteor.user();
Messages.createUserDeleteRoomFromTeamWithRoomIdAndUser(team.roomId, room.name, user);
}

if (Apps && Apps.isLoaded()) {
Apps.getBridges().getListenerBridge().roomEvent('IPostRoomDeleted', room);
if (Apps?.isLoaded()) {
Apps.getBridges()?.getListenerBridge().roomEvent('IPostRoomDeleted', room);
}

return result;
return true;
},
});
32 changes: 32 additions & 0 deletions apps/meteor/tests/end-to-end/api/09-rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -1300,4 +1300,36 @@ describe('[Rooms]', function () {
});
});
});

describe('/rooms.delete', () => {
let testChannel;
before('create an channel', async () => {
const result = await createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` });
testChannel = result.body.channel;
});
it('should delete a room when the request is correct', (done) => {
request
.post(api('rooms.delete'))
.set(credentials)
.send({ roomId: testChannel._id })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.end(done);
});
it('should throw an error when the room id doesn exist', (done) => {
request
.post(api('rooms.delete'))
.set(credentials)
.send({ roomId: 'invalid' })
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
})
.end(done);
});
});
});
6 changes: 6 additions & 0 deletions packages/rest-typings/src/v1/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ export type RoomsEndpoints = {
success: boolean;
};
};

'/v1/rooms.favorite': {
POST: (
params:
Expand All @@ -503,9 +504,14 @@ export type RoomsEndpoints = {
},
) => void;
};

'/v1/rooms.nameExists': {
GET: (params: { roomName: string }) => {
exists: boolean;
};
};

'/v1/rooms.delete': {
POST: (params: { roomId: string }) => void;
};
};
5 changes: 2 additions & 3 deletions packages/rest-typings/src/v1/teams/TeamsAddMembersProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';

import type { ITeamMemberParams } from './ITeamMemberParams';
Expand All @@ -8,7 +7,7 @@ const ajv = new Ajv();
export type TeamsAddMembersProps = ({ teamId: string } | { teamName: string }) & {
members: ITeamMemberParams[];
};
const teamsAddMembersPropsSchema: JSONSchemaType<TeamsAddMembersProps> = {
const teamsAddMembersPropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -77,4 +76,4 @@ const teamsAddMembersPropsSchema: JSONSchemaType<TeamsAddMembersProps> = {
],
};

export const isTeamsAddMembersProps = ajv.compile(teamsAddMembersPropsSchema);
export const isTeamsAddMembersProps = ajv.compile<TeamsAddMembersProps>(teamsAddMembersPropsSchema);
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';

const ajv = new Ajv();
Expand All @@ -7,7 +6,7 @@ export type TeamsConvertToChannelProps = {
roomsToRemove?: string[];
} & ({ teamId: string } | { teamName: string });

const teamsConvertToTeamsPropsSchema: JSONSchemaType<TeamsConvertToChannelProps> = {
const teamsConvertToTeamsPropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -47,4 +46,4 @@ const teamsConvertToTeamsPropsSchema: JSONSchemaType<TeamsConvertToChannelProps>
],
};

export const isTeamsConvertToChannelProps = ajv.compile(teamsConvertToTeamsPropsSchema);
export const isTeamsConvertToChannelProps = ajv.compile<TeamsConvertToChannelProps>(teamsConvertToTeamsPropsSchema);
5 changes: 2 additions & 3 deletions packages/rest-typings/src/v1/teams/TeamsDeleteProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';

const ajv = new Ajv();
Expand All @@ -7,7 +6,7 @@ export type TeamsDeleteProps = ({ teamId: string } | { teamName: string }) & {
roomsToRemove?: string[];
};

const teamsDeletePropsSchema: JSONSchemaType<TeamsDeleteProps> = {
const teamsDeletePropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -50,4 +49,4 @@ const teamsDeletePropsSchema: JSONSchemaType<TeamsDeleteProps> = {
],
};

export const isTeamsDeleteProps = ajv.compile(teamsDeletePropsSchema);
export const isTeamsDeleteProps = ajv.compile<TeamsDeleteProps>(teamsDeletePropsSchema);
5 changes: 2 additions & 3 deletions packages/rest-typings/src/v1/teams/TeamsLeaveProps.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';

const ajv = new Ajv();

export type TeamsLeaveProps = ({ teamId: string } | { teamName: string }) & { rooms?: string[] };

const teamsLeavePropsSchema: JSONSchemaType<TeamsLeaveProps> = {
const teamsLeavePropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -48,4 +47,4 @@ const teamsLeavePropsSchema: JSONSchemaType<TeamsLeaveProps> = {
],
};

export const isTeamsLeaveProps = ajv.compile(teamsLeavePropsSchema);
export const isTeamsLeaveProps = ajv.compile<TeamsLeaveProps>(teamsLeavePropsSchema);
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';

const ajv = new Ajv();
Expand All @@ -8,7 +7,7 @@ export type TeamsRemoveMemberProps = ({ teamId: string } | { teamName: string })
rooms?: Array<string>;
};

const teamsRemoveMemberPropsSchema: JSONSchemaType<TeamsRemoveMemberProps> = {
const teamsRemoveMemberPropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -57,4 +56,4 @@ const teamsRemoveMemberPropsSchema: JSONSchemaType<TeamsRemoveMemberProps> = {
],
};

export const isTeamsRemoveMemberProps = ajv.compile(teamsRemoveMemberPropsSchema);
export const isTeamsRemoveMemberProps = ajv.compile<TeamsRemoveMemberProps>(teamsRemoveMemberPropsSchema);
5 changes: 2 additions & 3 deletions packages/rest-typings/src/v1/teams/TeamsRemoveRoomProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';
import type { IRoom } from '@rocket.chat/core-typings';

Expand All @@ -8,7 +7,7 @@ export type TeamsRemoveRoomProps = ({ teamId: string } | { teamName: string }) &
roomId: IRoom['_id'];
};

export const teamsRemoveRoomPropsSchema: JSONSchemaType<TeamsRemoveRoomProps> = {
export const teamsRemoveRoomPropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -39,4 +38,4 @@ export const teamsRemoveRoomPropsSchema: JSONSchemaType<TeamsRemoveRoomProps> =
],
};

export const isTeamsRemoveRoomProps = ajv.compile(teamsRemoveRoomPropsSchema);
export const isTeamsRemoveRoomProps = ajv.compile<TeamsRemoveRoomProps>(teamsRemoveRoomPropsSchema);
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';

import type { ITeamMemberParams } from './ITeamMemberParams';
Expand All @@ -9,7 +8,7 @@ export type TeamsUpdateMemberProps = ({ teamId: string } | { teamName: string })
member: ITeamMemberParams;
};

const teamsUpdateMemberPropsSchema: JSONSchemaType<TeamsUpdateMemberProps> = {
const teamsUpdateMemberPropsSchema = {
oneOf: [
{
type: 'object',
Expand Down Expand Up @@ -68,4 +67,4 @@ const teamsUpdateMemberPropsSchema: JSONSchemaType<TeamsUpdateMemberProps> = {
],
};

export const isTeamsUpdateMemberProps = ajv.compile(teamsUpdateMemberPropsSchema);
export const isTeamsUpdateMemberProps = ajv.compile<TeamsUpdateMemberProps>(teamsUpdateMemberPropsSchema);
5 changes: 2 additions & 3 deletions packages/rest-typings/src/v1/teams/TeamsUpdateProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { JSONSchemaType } from 'ajv';
import Ajv from 'ajv';
import { TEAM_TYPE } from '@rocket.chat/core-typings';

Expand All @@ -16,7 +15,7 @@ export type TeamsUpdateProps = ({ teamId: string } | { teamName: string }) & {
};
};

const teamsUpdatePropsSchema: JSONSchemaType<TeamsUpdateProps> = {
const teamsUpdatePropsSchema = {
type: 'object',
properties: {
updateRoom: {
Expand Down Expand Up @@ -71,4 +70,4 @@ const teamsUpdatePropsSchema: JSONSchemaType<TeamsUpdateProps> = {
additionalProperties: false,
};

export const isTeamsUpdateProps = ajv.compile(teamsUpdatePropsSchema);
export const isTeamsUpdateProps = ajv.compile<TeamsUpdateProps>(teamsUpdatePropsSchema);