Skip to content

Conversation

@V-Gira
Copy link
Contributor

@V-Gira V-Gira commented Aug 25, 2025

BugWPB-18869 [Web] Conversation remains and acts as usual if federated contact is deleted

Description

user.delete backend event are not being handled with 1:1 conversations with federated users

Checklist

  • mentions the JIRA issue in the PR name (Ex. [WPB-XXXX])
  • PR has been self reviewed by the author;
  • Hard-to-understand areas of the code have been commented;
  • If it is a core feature, unit tests have been added;

amplify.publish(WebAppEvents.LIFECYCLE.SIGN_OUT, SIGN_OUT_REASON.ACCOUNT_DELETED, true);
}, 100);
}
this.emit('userDeleted', qualified_id);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emit the event to be consumed by the conversation repo.
User deletion events are not part of the WebAppEvents amplify store the conversation repo could use

@codecov
Copy link

codecov bot commented Aug 25, 2025

Codecov Report

❌ Patch coverage is 11.11111% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.86%. Comparing base (14414cc) to head (56255d1).
⚠️ Report is 1 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev   #19440      +/-   ##
==========================================
- Coverage   42.87%   42.86%   -0.02%     
==========================================
  Files        1341     1341              
  Lines       32405    32422      +17     
  Branches     7174     7178       +4     
==========================================
+ Hits        13895    13897       +2     
- Misses      16843    16857      +14     
- Partials     1667     1668       +1     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

* Event to delete the matching user.
*/
private userDelete({id}: {id: string}): void {
private userDelete({qualified_id}: {qualified_id: QualifiedId}): void {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qualified_id required for CONVERSATION_EVENT.MEMBER_LEAVE event used to display a message in a conversation

Comment on lines 2467 to 2481
private readonly onUserDeleted = async (userId: QualifiedId) => {
const found1to1Conversation = this.conversationState.get1to1ConversationWithUser(userId);
if (!found1to1Conversation) {
return;
}

const deletedEvent = EventBuilder.buildMemberDeleted(
found1to1Conversation,
userId,
this.serverTimeHandler.toServerTimestamp(),
);
await this.eventRepository.injectEvent(deletedEvent, EventRepository.SOURCE.INJECTED);
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inject a CONVERSATION_EVENT.MEMBER_LEAVE event in 1:1 conversation with a deleted user

@github-actions
Copy link
Contributor

github-actions bot commented Aug 25, 2025

🔗 Download Full Report Artifact

🧪 Playwright Test Summary

  • Passed: 10
  • Failed: 1
  • Skipped: 0
  • 🔁 Flaky: 3
  • 📊 Total: 14
  • Total Runtime: 778.5s (~ 12 min 58 sec)

Failed Tests:

❌ Messages in Groups (tags: TC-8751, crit-flow-web)

Location: specs/CriticalFlow/messagesInGroups-TC-8751.spec.ts:42
Duration: 34445ms

Errors:

TimeoutError: locator.click: Timeout 20000ms exceeded.
Call log:
  - waiting for locator('[data-uie-name="conversation-list-header"] [data-uie-name="go-create-group"]')
    - locator resolved to <button class="css-1pzkaq4" title="Create group" data-uie-name="go-create-group">…</button>
  - attempting click action
    2 × waiting for element to be visible, enabled and stable
      - element is visible, enabled and stable
      - scrolling into view if needed
      - done scrolling
      - <div tabindex="0" role="dialog" aria-modal="true" class=" css-r2fp0z" data-uie-name="modal-template-confirm">…</div> from <div class="css-18o04gs">…</div> subtree intercepts pointer events
    - retrying click action
    - waiting 20ms
    2 × waiting for element to be visible, enabled and stable
      - element is visible, enabled and stable
      - scrolling into view if needed
      - done scrolling
      - <div tabindex="0" role="dialog" aria-modal="true" class=" css-r2fp0z" data-uie-name="modal-template-confirm">…</div> from <div class="css-18o04gs">…</div> subtree intercepts pointer events
    - retrying click action
      - waiting 100ms
    38 × waiting for element to be visible, enabled and stable
       - element is visible, enabled and stable
       - scrolling into view if needed
       - done scrolling
       - <div tabindex="0" role="dialog" aria-modal="true" class=" css-1ocmba1" data-uie-name="modal-template-acknowledge">…</div> from <div class="css-18o04gs">…</div> subtree intercepts pointer events
     - retrying click action
       - waiting 500ms


   at pageManager/webapp/pages/conversationList.page.ts:104

  102 |
  103 |   async clickCreateGroup() {
> 104 |     await this.createGroupButton.click();
      |                                  ^
  105 |   }
  106 |
  107 |   private getConversationLocator(conversationName: string) {
    at ConversationListPage.clickCreateGroup (/home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/pageManager/webapp/pages/conversationList.page.ts:104:34)
    at setupUserA (/home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesInGroups-TC-8751.spec.ts:69:45)
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesInGroups-TC-8751.spec.ts:81:7
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesInGroups-TC-8751.spec.ts:64:5

Flaky Tests:

⚠️ Planning group call with sending various messages during call (tags: TC-8632, crit-flow-web)

Location: specs/CriticalFlow/groupCalls-TC-8632.spec.ts:37

Attempt 1
Result: ❌ Failed
Duration: 25099ms

Errors:

Error: expect(received).toBeTruthy()

Received: false

  106 |
  107 |       await memberCalling.maximizeCell();
> 108 |       expect(await memberCalling.isFullScreenVisible()).toBeTruthy();
      |                                                         ^
  109 |     });
  110 |
  111 |     await test.step('Owner goes full screen', async () => {
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/groupCalls-TC-8632.spec.ts:108:57
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/groupCalls-TC-8632.spec.ts:96:5

Attempt 2
Result: ✅ Passed
Duration: 26182ms

⚠️ Messages in 1:1 (tags: TC-8750, crit-flow-web)

Location: specs/CriticalFlow/messagesIn1On1-TC-8750.spec.ts:47

Attempt 1
Result: ❌ Failed
Duration: 30236ms

Errors:

Error: expect(received).toBeTruthy()

Received: false

  131 |     // Verify that the detail view modal is visible
  132 |     expect(await memberBPM.webapp.modals.detailViewModal().isVisible()).toBeTruthy();
> 133 |     expect(await memberBPM.webapp.modals.detailViewModal().isImageVisible()).toBeTruthy();
      |                                                                              ^
  134 |   });
  135 |   await test.step('User B can download the image', async () => {
  136 |     // Click on the download button to download the image
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesIn1On1-TC-8750.spec.ts:133:78
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesIn1On1-TC-8750.spec.ts:127:3

Attempt 2
Result: ✅ Passed
Duration: 70649ms

⚠️ Messages in Channels (tags: TC-8753, crit-flow-web)

Location: specs/CriticalFlow/messagesInChannels-TC-8753.spec.ts:44

Attempt 1
Result: ❌ Failed
Duration: 29413ms

Errors:

Error: expect(received).toBeTruthy()

Received: false

  118 |       // Verify that the detail view modal is visible
  119 |       expect(await userBModals.detailViewModal().isVisible()).toBeTruthy();
> 120 |       expect(await userBModals.detailViewModal().isImageVisible()).toBeTruthy();
      |                                                                    ^
  121 |     });
  122 |
  123 |     await test.step('User B can download the image', async () => {
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesInChannels-TC-8753.spec.ts:120:68
    at /home/runner/actions-runner/_work/wire-webapp/wire-webapp/test/e2e_tests/specs/CriticalFlow/messagesInChannels-TC-8753.spec.ts:114:5

Attempt 2
Result: ✅ Passed
Duration: 68704ms

Comment on lines +254 to +264
get1to1ConversationWithUser(userId: QualifiedId): Conversation | undefined {
const foundMLSConversation = this.findMLS1to1Conversation(userId);
if (foundMLSConversation) {
return foundMLSConversation;
}
const foundProteusConversations = this.findProteus1to1Conversations(userId);
if (foundProteusConversations && foundProteusConversations.length > 0) {
return foundProteusConversations[0];
}
return undefined;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like it could be one find operation only?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean something like this?

get1to1ConversationWithUser(userId: QualifiedId): Conversation | undefined {
  return this.conversations().find(
    conv => isMLS1to1ConversationWithUser(userId)(conv) || isProteus1to1ConversationWithUser(userId)(conv)
  );
}

We need to return the MLS conversation first I think

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. but the original code isn't that bad either. i'll leave it up to you.

Comment on lines 665 to 682
buildMemberDeleted(
conversationEntity: Conversation,
userId: QualifiedId,
currentTimestamp: number,
): MemberLeaveEvent {
return {
...buildQualifiedId(conversationEntity),
data: {
qualified_user_ids: [userId],
user_ids: [userId.id],
reason: MemberLeaveReason.USER_DELETED,
},
from: userId.id,
time: conversationEntity.getNextIsoDate(currentTimestamp),
type: CONVERSATION_EVENT.MEMBER_LEAVE,
};
},

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we have something for this already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the buildMemberLeave builder, but it doesn't provide a MemberLeaveReason — in that case USER_DELETED

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we adjust it to provide the MemberLeaveReason?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done here b7c8166

V-Gira added 4 commits August 26, 2025 17:18
build user.delete event message

inject memberleave event when a user is deleted

add localisation string for user deleted event

revert user event message changes

revert user event message changes

emit user.delete event
@V-Gira V-Gira force-pushed the v/handle-user-deletion branch from b7c8166 to 56255d1 Compare August 26, 2025 15:19
@sonarqubecloud
Copy link

@V-Gira V-Gira merged commit 75c844b into dev Aug 26, 2025
15 of 16 checks passed
@V-Gira V-Gira deleted the v/handle-user-deletion branch August 26, 2025 15:39
V-Gira added a commit that referenced this pull request Aug 26, 2025
* fix: handle user.delete event

build user.delete event message

inject memberleave event when a user is deleted

add localisation string for user deleted event

revert user event message changes

revert user event message changes

emit user.delete event

* display user deleted message if other member leave messages are not valid

* remove DE localization string

* replace buildMemberDelete with existing buildMember leave builder
V-Gira added a commit that referenced this pull request Aug 26, 2025
V-Gira added a commit that referenced this pull request Aug 26, 2025
* chore: Revert "chore: Update translations (#19446)"

This reverts commit 83804dd.

* chore: Revert "fix: handle user.delete event [WPB-18869] (#19440)"

This reverts commit 75c844b.
V-Gira added a commit that referenced this pull request Aug 27, 2025
* fix: handle user.delete event [WPB-18869] (#19440)

* fix: handle user.delete event

build user.delete event message

inject memberleave event when a user is deleted

add localisation string for user deleted event

revert user event message changes

revert user event message changes

emit user.delete event

* display user deleted message if other member leave messages are not valid

* remove DE localization string

* replace buildMemberDelete with existing buildMember leave builder

* runfix: extend UserDeleteEvent type

* correct typo, add german localization
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants