Skip to content

Commit 6b0feef

Browse files
committed
fix(credentials): keep GitLab personal tokens available after GitLab moves to gitlab_v2
Personal-token visibility resolved the GitLab integration by the legacy block type, so hiding that block and renaming its catalog entry hid every existing personal token and refused new ones. It now resolves the current GitLab version, and the integration page lists personal tokens beside saved GitLab credentials.
1 parent 85946b4 commit 6b0feef

3 files changed

Lines changed: 37 additions & 14 deletions

File tree

‎apps/sim/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail.tsx‎

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ function IntegrationBlockDetailContent({ integration, workspaceId }: Integration
175175
const [oauthOpen, setOAuthOpen] = useState(false)
176176
const [personalTokenOpen, setPersonalTokenOpen] = useState(false)
177177
const personalTokenAvailable =
178-
integration.type === 'gitlab' &&
178+
integration.slug === 'gitlab' &&
179179
(availability?.state === 'ready' || availability?.state === 'limited')
180180

181181
const { data: credentials = [], isPending: credentialsLoading } = useWorkspaceCredentials({
@@ -191,16 +191,21 @@ function IntegrationBlockDetailContent({ integration, workspaceId }: Integration
191191
* `providerId`s instead hides it from all of them.
192192
*/
193193
const connectedCredentials = useMemo(() => {
194-
if (integration.type === 'gitlab')
195-
return credentials.filter((c) => c.type === 'personal_token' && c.providerId === 'gitlab')
196-
if (!oauthService) return []
197-
return credentials.filter(
198-
(c) =>
199-
(c.type === 'oauth' || c.type === 'service_account') &&
200-
c.providerId &&
201-
credentialProviderMatchesService(c.providerId, oauthService)
202-
)
203-
}, [credentials, oauthService, integration.type])
194+
const serviceCredentials = oauthService
195+
? credentials.filter(
196+
(c) =>
197+
(c.type === 'oauth' || c.type === 'service_account') &&
198+
c.providerId &&
199+
credentialProviderMatchesService(c.providerId, oauthService)
200+
)
201+
: []
202+
if (integration.slug !== 'gitlab') return serviceCredentials
203+
// GitLab also has personal tokens, which Copilot acts with on the person's behalf.
204+
return [
205+
...credentials.filter((c) => c.type === 'personal_token' && c.providerId === 'gitlab'),
206+
...serviceCredentials,
207+
]
208+
}, [credentials, oauthService, integration.slug])
204209
const [serviceAccountOpen, setServiceAccountOpen] = useState(false)
205210
const serviceAccountTarget = useServiceAccountConnectTarget({
206211
serviceAccountProviderId: oauthService?.serviceAccountProviderId,

‎apps/sim/lib/integrations/credential-visibility.server.test.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,21 @@ describe('integration credential visibility', () => {
235235
expect(disabled.isCredentialVisible(credential)).toBe(false)
236236
})
237237

238+
it('keeps GitLab personal tokens visible after the GitLab block moves to a new version', () => {
239+
getIntegrationAvailabilityMock.mockReturnValue([
240+
availability('gitlab_v2', 'ready', { oauthAvailable: false, serviceAccountAvailable: true }),
241+
])
242+
const visibility = createIntegrationCredentialVisibility({
243+
allowedIntegrationTypes: new Set(['gitlab_v2']),
244+
blockVisibility: null,
245+
oauthServices: SERVICES,
246+
})
247+
248+
expect(visibility.isCredentialVisible({ providerId: 'gitlab', type: 'personal_token' })).toBe(
249+
true
250+
)
251+
})
252+
238253
it('leaves non-integration credentials visible', () => {
239254
const visibility = createIntegrationCredentialVisibility({
240255
allowedIntegrationTypes: new Set(),

‎apps/sim/lib/integrations/credential-visibility.server.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { getGitHubInstallationConfiguration } from '@/lib/oauth/github-installat
1313
import { GITHUB_INSTALLATION_PROVIDER_ID } from '@/lib/oauth/github-installation-types'
1414
import type { OAuthServiceMetadata } from '@/lib/oauth/types'
1515
import { getAllOAuthServices } from '@/lib/oauth/utils'
16+
import { resolveAccessControlBlockType } from '@/lib/permission-groups/integration-allowlist'
1617
import { getBlock } from '@/blocks/registry'
1718
import { isHiddenUnder } from '@/blocks/visibility/context'
1819

@@ -157,13 +158,15 @@ export function createIntegrationCredentialVisibility({
157158
return oauthOwnersByProviderId.get(providerId)?.some(isManagedOAuthServiceVisible) ?? false
158159
}
159160
if (type === 'personal_token') {
161+
// Personal tokens belong to the GitLab integration, whichever block version is current.
162+
const gitlabType = resolveAccessControlBlockType('gitlab')
160163
if (
161164
providerId !== 'gitlab' ||
162-
(allowedIntegrationTypes && !allowedIntegrationTypes.has('gitlab'))
165+
(allowedIntegrationTypes && !allowedIntegrationTypes.has(gitlabType))
163166
)
164167
return false
165-
const block = getBlock('gitlab')
166-
const availability = availabilityByType.get('gitlab')
168+
const block = getBlock(gitlabType)
169+
const availability = availabilityByType.get(gitlabType)
167170
if (!block || block.hideFromToolbar || isHiddenUnder(blockVisibility, block) || !availability)
168171
return false
169172
const state = resolveIntegrationAvailabilityStateForVisibility(availability, blockVisibility)

0 commit comments

Comments
 (0)