fix(server): key connected-account lookup on handle and provider (#22964)
Connect flows (Google, Microsoft, IMAP/SMTP/CalDAV) looked up an existing connectedAccount by `handle` alone, so connecting a second account with the same handle but a different provider overwrote the first instead of inserting a new row (e.g. IMAP inbox clobbering a calendar-only Google account). Fix: add the `provider` discriminator to the lookup. Same provider+handle still updates; a different provider gets its own row. Integration test covers the Google-then-IMAP case.
This commit is contained in:
@@ -154,6 +154,7 @@ export class GoogleAPIsService {
|
||||
handle,
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
provider: ConnectedAccountProvider.GOOGLE,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ export class MicrosoftAPIsService {
|
||||
handle,
|
||||
userWorkspaceId: userWorkspaceId,
|
||||
workspaceId,
|
||||
provider: ConnectedAccountProvider.MICROSOFT,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+33
@@ -658,6 +658,7 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
handle: 'test@example.com',
|
||||
userWorkspaceId: 'user-workspace-id',
|
||||
workspaceId: 'workspace-id',
|
||||
provider: ConnectedAccountProvider.IMAP_SMTP_CALDAV,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -674,6 +675,38 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a new row instead of overriding an account with the same handle under a different provider', async () => {
|
||||
mockConnectedAccountRepository.findOne.mockResolvedValue(null);
|
||||
mockMessageChannelRepository.findOne.mockResolvedValue(null);
|
||||
mockCalendarChannelRepository.findOne.mockResolvedValue(null);
|
||||
mockWorkspaceMemberRepository.findOne.mockResolvedValue({
|
||||
id: 'workspace-member-id',
|
||||
userId: 'user-id',
|
||||
});
|
||||
mockUserWorkspaceRepository.findOne.mockResolvedValue({
|
||||
id: 'user-workspace-id',
|
||||
userId: 'user-id',
|
||||
});
|
||||
|
||||
await service.upsertConnectedAccount(baseInput);
|
||||
|
||||
expect(mockConnectedAccountRepository.findOne).toHaveBeenCalledWith({
|
||||
where: {
|
||||
handle: 'test@example.com',
|
||||
userWorkspaceId: 'user-workspace-id',
|
||||
workspaceId: 'workspace-id',
|
||||
provider: ConnectedAccountProvider.IMAP_SMTP_CALDAV,
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockTransactionManagerSave).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'mocked-uuid',
|
||||
provider: ConnectedAccountProvider.IMAP_SMTP_CALDAV,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not create channels when neither IMAP nor CALDAV is configured', async () => {
|
||||
const smtpOnlyInput = {
|
||||
...baseInput,
|
||||
|
||||
+6
-1
@@ -86,7 +86,12 @@ export class ImapSmtpCalDavAPIService {
|
||||
const existingAccount =
|
||||
input.existingAccount ??
|
||||
(await this.connectedAccountRepository.findOne({
|
||||
where: { handle, userWorkspaceId, workspaceId },
|
||||
where: {
|
||||
handle,
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
provider: ConnectedAccountProvider.IMAP_SMTP_CALDAV,
|
||||
},
|
||||
}));
|
||||
|
||||
const newOrExistingAccountId = existingAccount?.id ?? v4();
|
||||
|
||||
Reference in New Issue
Block a user