Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/two-flowers-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fixes a very rare issue where switching from a DM to a regular room would show an error page
2 changes: 1 addition & 1 deletion apps/meteor/client/lib/rooms/roomCoordinator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class RoomCoordinatorClient extends RoomCoordinator {
id: name,
element: appLayout.wrap(
<MainLayout>
<RoomRoute extractOpenRoomParams={extractOpenRoomParams} />
<RoomRoute key={name} extractOpenRoomParams={extractOpenRoomParams} />
</MainLayout>,
),
},
Expand Down
4 changes: 4 additions & 0 deletions apps/meteor/client/views/room/hooks/useOpenRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export function useOpenRoom({ type, reference }: { type: RoomType; reference: st
throw new NotAuthorizedError();
}

if (!reference || !type) {
throw new RoomNotFoundError(undefined, { type, reference });
}

let roomData;
try {
roomData = await getRoomByTypeAndName(type, reference);
Expand Down
6 changes: 6 additions & 0 deletions apps/meteor/server/publications/room/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Meteor.methods<ServerMethods>({
},

async 'getRoomByTypeAndName'(type, name) {
if (!type || !name) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'getRoomByTypeAndName',
});
}

const userId = Meteor.userId();

if (!userId && settings.get('Accounts_AllowAnonymousRead') === false) {
Expand Down
210 changes: 210 additions & 0 deletions apps/meteor/tests/end-to-end/api/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2568,6 +2568,216 @@ describe('Meteor.methods', () => {
});
});

describe('[@getRoomByTypeAndName]', () => {
let testUser: TestUser<IUser>;
let testUser2: TestUser<IUser>;
let testUserCredentials: Credentials;
let dmId: IRoom['_id'];
let room: IRoom;

before(async () => {
testUser = await createUser();
testUser2 = await createUser();
testUserCredentials = await login(testUser.username, password);
});

before(async () => {
room = (
await createRoom({
type: 'c',
name: `channel.test.${Date.now()}-${Math.random()}`,
})
).body.channel;
});

before('create direct conversation with user', (done) => {
void request
.post(methodCall('createDirectMessage'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'createDirectMessage',
params: [testUser2.username],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
const result = JSON.parse(res.body.message);
expect(result.result).to.be.an('object');
expect(result.result).to.have.property('rid').that.is.an('string');

dmId = result.result.rid;
done();
});
});

after(() =>
Promise.all([
deleteRoom({ type: 'd', roomId: dmId }),
deleteRoom({ type: 'c', roomId: room._id }),
deleteUser(testUser),
deleteUser(testUser2),
]),
);

it("should throw an error if the user isn't logged in", (done) => {
void request
.post(methodCall('getRoomByTypeAndName'))
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: ['d', dmId],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
expect(res.body).to.have.property('status', 'error');
expect(res.body).to.have.property('message');
expect(res.body.message).to.be.equal('You must be logged in to do this.');
done();
});
});

it("should throw an error if name isn't provided", (done) => {
void request
.post(methodCall('getRoomByTypeAndName'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: ['d', null],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
expect(res.body).to.have.property('message');

const parsedResponse = JSON.parse(res.body.message);

expect(parsedResponse).to.have.property('error');
expect(parsedResponse.error).to.have.property('error');
expect(parsedResponse.error.error).to.equal('error-invalid-room');
done();
});
});

it("should throw an error if type isn't provided", (done) => {
void request
.post(methodCall('getRoomByTypeAndName'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: [null, dmId],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
expect(res.body).to.have.property('message');

const parsedResponse = JSON.parse(res.body.message);

expect(parsedResponse).to.have.property('error');
expect(parsedResponse.error).to.have.property('error');
expect(parsedResponse.error.error).to.equal('error-invalid-room');
done();
});
});

it("should throw an error if the user doesn't have access to the room", (done) => {
void request
.post(methodCall('getRoomByTypeAndName'))
.set(testUserCredentials)
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: ['d', dmId],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
expect(res.body).to.have.property('message');

const parsedResponse = JSON.parse(res.body.message);
expect(parsedResponse).to.have.property('error');
expect(parsedResponse.error).to.have.property('error');
expect(parsedResponse.error.error).to.equal('error-no-permission');
done();
});
});

it("should throw an error if the room doesn't exist", (done) => {
void request
.post(methodCall('getRoomByTypeAndName'))
.set(testUserCredentials)
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: ['d', 'testId'],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
expect(res.body).to.have.property('message');

const parsedResponse = JSON.parse(res.body.message);

expect(parsedResponse).to.have.property('error');
expect(parsedResponse.error).to.have.property('error');
expect(parsedResponse.error.error).to.equal('error-invalid-room');
done();
});
});

it('should return the room object for a Public Channel if anonymous read is enabled', async () => {
await updateSetting('Accounts_AllowAnonymousRead', true);

const res = await request
.post(methodCall('getRoomByTypeAndName'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: ['c', room._id],
id: 'id',
msg: 'method',
}),
});

expect(res.body.success).to.equal(true);
const parsedResponse = JSON.parse(res.body.message);
expect(parsedResponse.result.name).to.equal(room.name);

await updateSetting('Accounts_AllowAnonymousRead', false);
});

it('should return the room object for a DM', (done) => {
void request
.post(methodCall('getRoomByTypeAndName'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'getRoomByTypeAndName',
params: ['d', dmId],
id: 'id',
msg: 'method',
}),
})
.end((_err, res) => {
expect(res.body.success).to.equal(true);
const parsedResponse = JSON.parse(res.body.message);
expect(parsedResponse.result._id).to.equal(dmId);
done();
});
});
});

describe('[@setUserActiveStatus]', () => {
let testUser: TestUser<IUser>;
let testUser2: TestUser<IUser>;
Expand Down
Loading