[FIX] mail: fix crash when unknown member leaves channel
Before this commit, a crash occurred when an unknown member left a channel. Steps to reproduce: - Open two browsers, one for admin, one for demo - Ensures both users are on the general channel - Execute the `/leave` command with demo - A traceback appears on the admin browser This issue occurs because the `action_unfollow` only sends the channel member id through the bus but the client relies on other keys without checking for their presence. This commit fixes this issue. closes odoo/odoo#128090 X-original-commit: f8452b2eb8f9243402984d78184ed494384a187c Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com> Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
This commit is contained in:
@@ -39,8 +39,8 @@ export class ChannelMemberService {
|
||||
channelId: memberData.persona.guest ? memberData.channel.id : null,
|
||||
});
|
||||
}
|
||||
member.threadId = memberData.threadId ?? member.threadId ?? memberData.channel.id;
|
||||
if (!member.thread) {
|
||||
member.threadId = memberData.threadId ?? member.threadId ?? memberData.channel?.id;
|
||||
if (member.threadId && !member.thread) {
|
||||
// this prevents cyclic dependencies between mail.thread and discuss.channel.member
|
||||
this.env.bus.trigger("mail.thread/insert", {
|
||||
id: member.threadId,
|
||||
@@ -50,7 +50,7 @@ export class ChannelMemberService {
|
||||
switch (command) {
|
||||
case "insert":
|
||||
{
|
||||
if (!member.thread.channelMembers.includes(member)) {
|
||||
if (member.thread && !member.thread.channelMembers.includes(member)) {
|
||||
member.thread.channelMembers.push(member);
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,9 @@ export class ChannelMemberService {
|
||||
removeFromArray(this.store.channelMembers, member);
|
||||
// eslint-disable-next-line no-fallthrough
|
||||
case "insert-and-unlink":
|
||||
removeFromArray(member.thread.channelMembers, member);
|
||||
if (member.thread) {
|
||||
removeFromArray(member.thread.channelMembers, member);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,6 +486,27 @@ QUnit.test("leave command on channel", async (assert) => {
|
||||
assert.verifySteps(["You unsubscribed from general."]);
|
||||
});
|
||||
|
||||
QUnit.test("Can handle leave notification from unknown member", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const userId = pyEnv["res.users"].create({ name: "Dobby" });
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Dobby", user_ids: [userId] });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "general",
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: pyEnv.currentPartnerId }),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await env.services.orm.call("discuss.channel", "action_unfollow", [channelId], {
|
||||
context: { mockedUserId: userId },
|
||||
});
|
||||
await click("button[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains(Mitchell)");
|
||||
assert.containsNone($, ".o-discuss-ChannelMember:contains(Dobby)");
|
||||
});
|
||||
|
||||
QUnit.test("leave command on chat", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Chuck Norris" });
|
||||
|
||||
@@ -91,7 +91,7 @@ patch(MockServer.prototype, "mail/models/discuss_channel", {
|
||||
return this._mockDiscussChannelCreateGroup(partners_to);
|
||||
}
|
||||
if (args.model === "discuss.channel" && args.method === "execute_command_leave") {
|
||||
return this._mockDiscussChannelExecuteCommandLeave(args);
|
||||
return this._mockDiscussChannelExecuteCommandLeave(args, args.kwargs?.context);
|
||||
}
|
||||
if (args.model === "discuss.channel" && args.method === "execute_command_who") {
|
||||
return this._mockDiscussChannelExecuteCommandWho(args);
|
||||
@@ -218,9 +218,6 @@ patch(MockServer.prototype, "mail/models/discuss_channel", {
|
||||
["channel_id", "in", ids],
|
||||
["partner_id", "=", partnerId],
|
||||
]);
|
||||
const formattedChannelMember = this._mockDiscussChannelMember_DiscussChannelMemberFormat([
|
||||
channelMember.id,
|
||||
])[0];
|
||||
if (!channelMember) {
|
||||
return true;
|
||||
}
|
||||
@@ -241,7 +238,7 @@ patch(MockServer.prototype, "mail/models/discuss_channel", {
|
||||
this.pyEnv["bus.bus"]._sendone(channel, "mail.record/insert", {
|
||||
Channel: {
|
||||
id: channel.id,
|
||||
channelMembers: [["insert-and-unlink", formattedChannelMember]],
|
||||
channelMembers: [["insert-and-unlink", { id: channelMember.id }]],
|
||||
memberCount: this.pyEnv["discuss.channel.member"].searchCount([
|
||||
["channel_id", "=", channel.id],
|
||||
]),
|
||||
@@ -844,10 +841,10 @@ patch(MockServer.prototype, "mail/models/discuss_channel", {
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_mockDiscussChannelExecuteCommandLeave(args) {
|
||||
_mockDiscussChannelExecuteCommandLeave(args, context = {}) {
|
||||
const channel = this.getRecords("discuss.channel", [["id", "in", args.args[0]]])[0];
|
||||
if (channel.channel_type === "channel") {
|
||||
this._mockDiscussChannelActionUnfollow([channel.id]);
|
||||
this._mockDiscussChannelActionUnfollow([channel.id], context);
|
||||
} else {
|
||||
this._mockDiscussChannelChannelPin([channel.id], false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user