Skip to content

Commit d1c8c87

Browse files
refactor(credentials): route the editor SA picker through the canonical connect hook
The workflow-editor credential selector (from #5800's merged picker) resolved its service-account setup surface inline and mounted the modal with NO preview gate — so a `credentialKind: 'service-account'` picker would offer a custom-bot setup even when slack_v2 is preview-gated off, the leak the integrations page and chat already guard against. Route it through the shared useServiceAccountConnectTarget hook (the same resolver chat and the integrations page use): suppress the setup action when `hidden`, and use the hook's vendor-accurate label ("Add private app token", "Set up a custom bot") as the default connect-row copy. Existing service accounts stay selectable; the per-block `credentialLabels.serviceAccountConnect` override still wins. One resolver now backs all three SA connect surfaces.
1 parent 8350013 commit d1c8c87

1 file changed

Lines changed: 49 additions & 18 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { ConnectOAuthModal } from '@/app/workspace/[workspaceId]/components/conn
1717
import {
1818
ConnectServiceAccountModal,
1919
type ServiceAccountProviderId,
20+
useServiceAccountConnectTarget,
2021
} from '@/app/workspace/[workspaceId]/integrations/components/connect-service-account-modal'
2122
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
2223
import { getWorkflowSearchLabelHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight'
@@ -130,6 +131,20 @@ export function CredentialSelector({
130131
[credentialKind, isMergedKinds, serviceId]
131132
)
132133

134+
// Canonical resolver for the service-account connect control: the vendor-
135+
// accurate label and — critically — the per-viewer preview gate (a custom
136+
// Slack bot rides `slack_v2`). Shared with the integrations page and chat so
137+
// the gate can't be bypassed here. When `hidden`, the setup action is
138+
// suppressed; existing service-account credentials stay selectable.
139+
const serviceAccountTarget = useServiceAccountConnectTarget({
140+
serviceAccountProviderId: serviceAccountService?.serviceAccountProviderId as
141+
| ServiceAccountProviderId
142+
| undefined,
143+
serviceName: serviceAccountService?.name,
144+
serviceIcon: serviceAccountService?.icon,
145+
})
146+
const serviceAccountConnectHidden = Boolean(serviceAccountTarget?.hidden)
147+
133148
const selectedCredential = useMemo(
134149
() => credentials.find((cred) => cred.id === selectedId),
135150
[credentials, selectedId]
@@ -249,19 +264,23 @@ export function CredentialSelector({
249264
iconElement: getProviderIcon((cred.provider ?? provider) as OAuthProvider),
250265
}))
251266

252-
options.push({
253-
label:
254-
credentialKind === 'service-account'
255-
? (subBlock.credentialLabels?.serviceAccountConnect ??
256-
(credentials.length > 0
257-
? `Add another ${getProviderName(provider)} key`
258-
: `Add ${getProviderName(provider)} key`))
259-
: credentials.length > 0
260-
? `Connect another ${getProviderName(provider)} account`
261-
: `Connect ${getProviderName(provider)} account`,
262-
value: '__connect_account__',
263-
iconElement: <ExternalLink className='size-3' />,
264-
})
267+
// Suppress the setup action when the service-account flow is preview-gated
268+
// for this viewer (a custom Slack bot needs slack_v2) — existing accounts
269+
// above stay selectable.
270+
if (credentialKind !== 'service-account' || !serviceAccountConnectHidden) {
271+
options.push({
272+
label:
273+
credentialKind === 'service-account'
274+
? (subBlock.credentialLabels?.serviceAccountConnect ??
275+
serviceAccountTarget?.label ??
276+
`Add ${getProviderName(provider)} key`)
277+
: credentials.length > 0
278+
? `Connect another ${getProviderName(provider)} account`
279+
: `Connect ${getProviderName(provider)} account`,
280+
value: '__connect_account__',
281+
iconElement: <ExternalLink className='size-3' />,
282+
})
283+
}
265284

266285
return options
267286
}, [
@@ -271,6 +290,8 @@ export function CredentialSelector({
271290
credentials,
272291
credentialKind,
273292
subBlock.credentialLabels,
293+
serviceAccountConnectHidden,
294+
serviceAccountTarget,
274295
provider,
275296
getProviderIcon,
276297
getProviderName,
@@ -302,18 +323,28 @@ export function CredentialSelector({
302323
section: labels?.serviceAccountGroup ?? 'Service accounts',
303324
items: [
304325
...credentials.filter((c) => c.type === 'service_account').map(toOption),
305-
{
306-
label: labels?.serviceAccountConnect ?? `Add ${getProviderName(provider)} key`,
307-
value: '__connect_service_account__',
308-
iconElement: <ExternalLink className='size-3' />,
309-
},
326+
// Drop the setup action when the flow is preview-gated for this viewer.
327+
...(serviceAccountConnectHidden
328+
? []
329+
: [
330+
{
331+
label:
332+
labels?.serviceAccountConnect ??
333+
serviceAccountTarget?.label ??
334+
`Add ${getProviderName(provider)} key`,
335+
value: '__connect_service_account__',
336+
iconElement: <ExternalLink className='size-3' />,
337+
},
338+
]),
310339
],
311340
},
312341
]
313342
}, [
314343
isMergedKinds,
315344
subBlock.credentialLabels,
316345
credentials,
346+
serviceAccountConnectHidden,
347+
serviceAccountTarget,
317348
provider,
318349
getProviderIcon,
319350
getProviderName,

0 commit comments

Comments
 (0)