Skip to content

Commit e8d346d

Browse files
fix(slack): preserve outdated member access repair
1 parent c24535f commit e8d346d

2 files changed

Lines changed: 53 additions & 15 deletions

File tree

apps/sim/ee/credential-groups/components/slack-managed-users-access.test.tsx

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ describe('Slack member access selection', () => {
551551
{ enabled: true, needsValidation: true, sharedAppAvailable: true },
552552
{ enabled: true, needsValidation: false, sharedAppAvailable: false },
553553
])('keeps incomplete shared app setup actionable: %j', async (status) => {
554+
const accounts = mocks.accounts()
555+
accounts.data.credentialGroup.options[0].configurationStatus = 'needs_update'
554556
mocks.apps.mockReturnValue({
555557
isSuccess: true,
556558
isPending: false,
@@ -575,11 +577,12 @@ describe('Slack member access selection', () => {
575577
await render(undefined, [], 'org-1')
576578
expect(document.body.textContent).toContain('Manage Sim Search app')
577579
expect(document.body.textContent).not.toContain('Verify and add')
580+
expect(document.body.textContent).not.toContain('Update member access')
578581
expect(mocks.onOpenChange).not.toHaveBeenCalled()
579582
expect(mocks.start).not.toHaveBeenCalled()
580583
})
581584

582-
it.each(['removed', 'needs_update', 'pending', 'error', 'refreshing'])(
585+
it.each(['removed', 'needs_update', 'needs_update_failed', 'pending', 'error', 'refreshing'])(
583586
'does not skip shared setup when member configuration is %s',
584587
async (state) => {
585588
mocks.apps.mockReturnValue({
@@ -623,8 +626,7 @@ describe('Slack member access selection', () => {
623626
{
624627
provider: 'slack',
625628
status: 'active',
626-
configurationStatus:
627-
state === 'needs_update' ? 'needs_update' : 'ready',
629+
configurationStatus: 'needs_update',
628630
},
629631
],
630632
},
@@ -635,12 +637,39 @@ describe('Slack member access selection', () => {
635637
expect(mocks.start).not.toHaveBeenCalled()
636638
if (state === 'error') {
637639
expect(document.body.textContent).toContain('Could not load member setup')
640+
expect(document.body.textContent).not.toContain('Update member access')
638641
await clickButton('Retry')
639642
expect(mocks.refetchAccounts).toHaveBeenCalledOnce()
640643
} else if (state === 'pending' || state === 'refreshing') {
641644
expect(document.body.textContent).toContain('Checking the installed Slack app')
645+
expect(document.body.textContent).not.toContain('Update member access')
646+
} else if (state === 'needs_update' || state === 'needs_update_failed') {
647+
expect(document.body.textContent).toContain('Member access is outdated')
648+
if (state === 'needs_update_failed')
649+
mocks.start.mockRejectedValueOnce(new Error('Try again'))
650+
await clickButton('Update member access')
651+
expect(mocks.start).toHaveBeenCalledExactlyOnceWith({
652+
organizationId: 'org-1',
653+
credentialGroupId: 'group-1',
654+
body: {
655+
appId: 'A_SHARED',
656+
teamId: 'T_TEAM',
657+
requiredScopes: [...SLACK_SEARCH_USER_SCOPES],
658+
},
659+
})
660+
expect(mocks.install).not.toHaveBeenCalled()
661+
if (state === 'needs_update_failed') {
662+
expect(toast.error).toHaveBeenCalledWith('Try again')
663+
expect(popup.close).toHaveBeenCalledOnce()
664+
expect(mocks.onOpenChange).not.toHaveBeenCalled()
665+
await clickButton('Update member access')
666+
}
667+
await completeAuthorization()
668+
expect(toast.success).toHaveBeenCalledWith('Slack configured')
669+
expect(mocks.onOpenChange).toHaveBeenCalledWith(false)
642670
} else {
643671
expect(document.body.textContent).toContain('Manage Sim Search app')
672+
expect(document.body.textContent).not.toContain('Update member access')
644673
}
645674
}
646675
)

apps/sim/ee/credential-groups/components/slack-managed-users-modal.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ export function SlackManagedUsersModal({
107107
const sharedAppInstalled = organizationSetup && selectedApp?.appKind === 'shared'
108108
const accounts = useOrganizationAccounts(open && sharedAppInstalled ? organizationId : undefined)
109109
const memberGroup = accounts.data?.credentialGroup
110-
const sharedAppReady = Boolean(
110+
const memberOption = memberGroup?.options.find(
111+
(option) => option.provider === 'slack' && option.status === 'active'
112+
)
113+
const sharedAppCanAuthorize = Boolean(
111114
sharedAppInstalled &&
112115
apps.isSuccess &&
113116
!apps.isFetching &&
@@ -118,14 +121,11 @@ export function SlackManagedUsersModal({
118121
accounts.isSuccess &&
119122
!accounts.isFetching &&
120123
!accounts.error &&
121-
memberGroup?.id === credentialGroupId &&
122-
memberGroup.options.some(
123-
(option) =>
124-
option.provider === 'slack' &&
125-
option.status === 'active' &&
126-
option.configurationStatus === 'ready'
127-
)
124+
memberGroup?.id === credentialGroupId
128125
)
126+
const sharedAppReady = sharedAppCanAuthorize && memberOption?.configurationStatus === 'ready'
127+
const sharedAppNeedsUpdate =
128+
sharedAppCanAuthorize && memberOption?.configurationStatus === 'needs_update'
129129
const [clientId, setClientId] = useState('')
130130
const [clientSecret, setClientSecret] = useState('')
131131
const [pending, setPending] = useState(false)
@@ -274,7 +274,12 @@ export function SlackManagedUsersModal({
274274
}
275275

276276
const handleSubmit = async () => {
277-
if (pending || sharedAppInstalled || (!organizationSetup && !selectedBot)) return
277+
if (
278+
pending ||
279+
(sharedAppInstalled && !sharedAppNeedsUpdate) ||
280+
(!organizationSetup && !selectedBot)
281+
)
282+
return
278283
if (
279284
organizationSetup
280285
? !selectedApp || !requiredScopes.length
@@ -341,7 +346,9 @@ export function SlackManagedUsersModal({
341346
? 'Loading...'
342347
: pending
343348
? 'Waiting for Slack...'
344-
: 'Verify and add'
349+
: sharedAppNeedsUpdate
350+
? 'Update member access'
351+
: 'Verify and add'
345352
const primaryDisabled =
346353
isLoading ||
347354
noBots ||
@@ -414,7 +421,9 @@ export function SlackManagedUsersModal({
414421
<ChipModalField type='custom' title='Member accounts'>
415422
<p className='text-[var(--text-secondary)] text-sm'>
416423
{sharedAppInstalled
417-
? 'The Sim Search installation needs attention. Manage the app to finish setup.'
424+
? sharedAppNeedsUpdate
425+
? 'Member access is outdated. Update it so members can reconnect their Slack accounts.'
426+
: 'The Sim Search installation needs attention. Manage the app to finish setup.'
418427
: 'Verify member authorization for the installed app. Each member can then connect their Slack account to index channels and DMs they can access.'}
419428
</p>
420429
{selectedApp && (
@@ -512,7 +521,7 @@ export function SlackManagedUsersModal({
512521
onClick: () => setAppSetupOpen(true),
513522
},
514523
}
515-
: sharedAppInstalled
524+
: sharedAppInstalled && !sharedAppNeedsUpdate
516525
? { defaultAction: 'dismiss' as const }
517526
: noBots
518527
? { defaultAction: 'dismiss' as const }

0 commit comments

Comments
 (0)