Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
17 changes: 17 additions & 0 deletions apps/meteor/app/api/server/v1/rooms.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Meteor } from 'meteor/meteor';
import Ajv from 'ajv';
import { isRoomsEraseProps } from '@rocket.chat/rest-typings';

import { API } from '../api';

Expand Down Expand Up @@ -37,3 +38,19 @@ API.v1.addRoute(
},
},
);

API.v1.addRoute(
'rooms.erase',
{
authRequired: true,
validateParams: isRoomsEraseProps,
},
{
post() {
const { rid } = this.bodyParams;

Meteor.call('eraseRoom', rid);
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 eraseRoom = useEndpoint('POST', '/v1/rooms.erase');
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 eraseRoom({ rid: 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,21 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import type { ITeam } from '@rocket.chat/core-typings';

import { deleteRoom } from '../../app/lib';
import { methodDeprecationLogger } from '../../app/lib/server/lib/deprecationWarningLogger';
import { deleteRoom } from '../../app/lib/server';
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) {
check(rid, String);
eraseRoom(rid: string) {
Comment thread
felipe-rod123 marked this conversation as resolved.
Outdated
methodDeprecationLogger.warn('eraseRoom will be deprecated in future versions of Rocket.Chat');

if (!Meteor.userId()) {
const uid = Meteor.userId();

if (!uid) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'eraseRoom',
});
Expand All @@ -32,18 +35,14 @@ 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.');
}
Expand All @@ -52,13 +51,13 @@ Meteor.methods({
const result = deleteRoom(rid);

if (room.teamId) {
const team = Promise.await(Team.getOneById(room.teamId));
const team = Promise.await(Team.getOneById(room.teamId)) as ITeam;
Comment thread
felipe-rod123 marked this conversation as resolved.
Outdated
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;
Expand Down
50 changes: 50 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,54 @@ describe('[Rooms]', function () {
});
});
});

describe('/rooms.erase:', () => {
let testChannel;
it('create an channel', (done) => {
createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` }).end((err, res) => {
testChannel = res.body.channel;
done();
});
});
it('should delete a room when the request is correct', (done) => {
request
.post(api('rooms.erase'))
.set(credentials)
.send({
rid: 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 is not provided', (done) => {
request
.post(api('rooms.erase'))
.set(credentials)
.send({})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
})
.end(done);
});
it('should throw an error when the room id is incorrect', (done) => {
request
.post(api('rooms.erase'))
.set(credentials)
.send({
rid: false,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
})
.end(done);
});
});
});
1 change: 1 addition & 0 deletions packages/rest-typings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export * from './v1/permissions';
export * from './v1/roles';
export * from './v1/settings';
export * from './v1/teams';
export * from './v1/rooms/RoomsEraseParamsPOST';
export * from './v1/videoConference';
export * from './v1/assets';
export * from './v1/channels/ChannelsAddAllProps';
Expand Down
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.erase': {
POST: (params: { rid: string }) => void;
};
};
20 changes: 20 additions & 0 deletions packages/rest-typings/src/v1/rooms/RoomsEraseParamsPOST.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Ajv from 'ajv';

const ajv = new Ajv({ coerceTypes: true });

export type RoomsEraseProps = {
rid: string;
};

const RoomsErasePropsSchema = {
type: 'object',
properties: {
rid: {
type: 'string',
},
},
required: ['rid'],
additionalProperties: false,
};

export const isRoomsEraseProps = ajv.compile<RoomsEraseProps>(RoomsErasePropsSchema);
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);