Skip to content

Commit 0179b48

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(oauth): clear stale connector return context
1 parent 205b664 commit 0179b48

2 files changed

Lines changed: 51 additions & 11 deletions

File tree

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connectors-section/connectors-section.test.tsx

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
88
import type { SyncLogData } from '@/lib/api/contracts/knowledge/connectors'
99
import { CONNECTOR_SYNC_STALE_LOCK_TTL_MS } from '@/lib/knowledge/connectors/sync-limits'
1010

11-
const { connectOAuthModalMock, icon, oauthCredentialsState } = vi.hoisted(() => ({
12-
connectOAuthModalMock: vi.fn(),
13-
icon: (name: string) => (props: SVGProps<SVGSVGElement>) => (
14-
<svg data-testid={`icon-${name}`} className={props.className} />
15-
),
16-
oauthCredentialsState: {
17-
current: [] as Array<{ id: string; name: string; provider: string }>,
18-
},
19-
}))
11+
const { consumeOAuthReturnContextMock, connectOAuthModalMock, icon, oauthCredentialsState } =
12+
vi.hoisted(() => ({
13+
consumeOAuthReturnContextMock: vi.fn(),
14+
connectOAuthModalMock: vi.fn(),
15+
icon: (name: string) => (props: SVGProps<SVGSVGElement>) => (
16+
<svg data-testid={`icon-${name}`} className={props.className} />
17+
),
18+
oauthCredentialsState: {
19+
current: [] as Array<{ id: string; name: string; provider: string }>,
20+
},
21+
}))
2022

2123
vi.mock('@sim/emcn/icons', () => ({
2224
ChevronDown: icon('chevron-down'),
@@ -59,7 +61,7 @@ vi.mock('@sim/emcn', () => ({
5961
}))
6062

6163
vi.mock('@/lib/credentials/client-state', () => ({
62-
consumeOAuthReturnContext: vi.fn(),
64+
consumeOAuthReturnContext: consumeOAuthReturnContextMock,
6365
writeOAuthReturnContext: vi.fn(),
6466
}))
6567
vi.mock('@/lib/oauth', () => ({
@@ -230,6 +232,37 @@ describe('Connector credential reauthorization', () => {
230232
})
231233
)
232234
})
235+
236+
it('clears the OAuth return context if the credential disappears while open', () => {
237+
oauthCredentialsState.current = [
238+
{ id: 'credential-1', name: 'Workspace Slack', provider: 'slack-custom' },
239+
]
240+
const connector = makeConnector()
241+
const container = renderSection(connector)
242+
const reconnectButton = Array.from(container.querySelectorAll('button')).find(
243+
(button) => button.textContent === 'Reconnect'
244+
)
245+
246+
act(() => reconnectButton?.click())
247+
expect(connectOAuthModalMock).toHaveBeenCalledOnce()
248+
249+
connectOAuthModalMock.mockClear()
250+
oauthCredentialsState.current = []
251+
act(() =>
252+
root?.render(
253+
<ConnectorsSection
254+
workspaceId='workspace-1'
255+
knowledgeBaseId='knowledge-1'
256+
connectors={[connector]}
257+
isLoading={false}
258+
canEdit
259+
/>
260+
)
261+
)
262+
263+
expect(consumeOAuthReturnContextMock).toHaveBeenCalledOnce()
264+
expect(connectOAuthModalMock).not.toHaveBeenCalled()
265+
})
233266
})
234267

235268
describe('SyncHistory', () => {

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connectors-section/connectors-section.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useId, useMemo, useState } from 'react'
3+
import { useEffect, useId, useMemo, useState } from 'react'
44
import {
55
Badge,
66
Button,
@@ -296,6 +296,13 @@ function ConnectorCard({
296296
[selectedCredential, requiredScopes]
297297
)
298298

299+
useEffect(() => {
300+
if (showOAuthModal && connector.credentialId && !selectedCredential) {
301+
consumeOAuthReturnContext()
302+
setShowOAuthModal(false)
303+
}
304+
}, [showOAuthModal, connector.credentialId, selectedCredential])
305+
299306
const { data: detail, isLoading: detailLoading } = useConnectorDetail(
300307
expanded ? knowledgeBaseId : undefined,
301308
expanded ? connector.id : undefined

0 commit comments

Comments
 (0)