-
Notifications
You must be signed in to change notification settings - Fork 61k
feat(editor): Display workflow, credential and data table dependencies #26912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a7c65c7
d2eb3dd
a7d4a29
1fb7a8e
4736882
5e642c6
e2b0e6d
61fcb81
b3d3e81
8bbfd4c
10197d0
d4d4883
968bc70
a053059
1c3d25a
2bc4722
6e2cfbc
4f66fb4
77e74cf
87c2a68
e3ed2c9
a2a077b
32e761f
92c4705
0aee7d1
6817ab2
427198c
839a70d
4034c60
697ecec
33e61c3
21bac65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { z } from 'zod'; | ||
|
|
||
| import { Z } from '../../zod-class'; | ||
|
|
||
| export class GetResourceDependenciesDto extends Z.class({ | ||
| resourceIds: z.array(z.string()).min(1).max(100), | ||
| resourceType: z.enum(['workflow', 'credential', 'dataTable']), | ||
| }) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { z } from 'zod'; | ||
|
|
||
| import { Z } from '../../zod-class'; | ||
|
|
||
| export class GetResourceDependencyCountsDto extends Z.class({ | ||
| resourceIds: z.array(z.string()).min(1).max(100), | ||
| resourceType: z.enum(['workflow', 'credential', 'dataTable']), | ||
| }) {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| export interface DependencyTypeCounts { | ||
| credentialId: number; | ||
| dataTableId: number; | ||
| workflowCall: number; | ||
| workflowParent: number; | ||
| } | ||
|
|
||
| /** | ||
| * Lightweight response for workflow cards — only the counts per type, | ||
| * no resolved names / project IDs. Keyed by resource ID. | ||
| */ | ||
| export type DependencyCountsBatchResponse = Record<string, DependencyTypeCounts>; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| export type DependencyType = 'credentialId' | 'dataTableId' | 'workflowCall' | 'workflowParent'; | ||
|
|
||
| export type DependencyResourceType = 'workflow' | 'credential' | 'dataTable'; | ||
|
|
||
| export interface ResolvedDependency { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: (Based on your team's feedback about preferring precise union DTOs over looser shared types.) Prompt for AI agents
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case it's also optional for the case where a user doesn't have access to it
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the feedback! I've saved this as a new learning to improve future reviews. |
||
| type: DependencyType; | ||
| id: string; | ||
| name: string; | ||
| /** Project ID — included for data tables so the frontend can build a direct link */ | ||
| projectId?: string; | ||
| } | ||
|
|
||
| export interface ResolvedDependenciesResult { | ||
| dependencies: ResolvedDependency[]; | ||
| /** Number of dependencies the user does not have access to view */ | ||
| inaccessibleCount: number; | ||
| } | ||
|
|
||
| export type DependenciesBatchResponse = Record<string, ResolvedDependenciesResult>; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -224,6 +224,54 @@ export class CredentialsFinderService { | |
| return sharedCredentialsList; | ||
| } | ||
|
|
||
| /** | ||
| * Given a list of credential IDs, return only those the user can access with the given scopes. | ||
| */ | ||
| async findCredentialIdsWithScopeForUser( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Add tests for the new credential access-filtering helper. This introduces authorization logic for dependency visibility, but there is no coverage for the new helper or its workflow-dependency integration, so regressions here would be easy to miss. Prompt for AI agents |
||
| credentialIds: string[], | ||
| user: User, | ||
| scopes: Scope[], | ||
| ): Promise<Set<string>> { | ||
| if (credentialIds.length === 0) return new Set(); | ||
|
|
||
| let where: FindOptionsWhere<SharedCredentials> = { credentialsId: In(credentialIds) }; | ||
|
|
||
| if (!hasGlobalScope(user, scopes, { mode: 'allOf' })) { | ||
| const [projectRoles, credentialRoles] = await Promise.all([ | ||
| this.roleService.rolesWithScope('project', scopes), | ||
| this.roleService.rolesWithScope('credential', scopes), | ||
| ]); | ||
| where = { | ||
| ...where, | ||
| role: In(credentialRoles), | ||
| project: { | ||
| projectRelations: { | ||
| role: In(projectRoles), | ||
| userId: user.id, | ||
| }, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| const sharedCredentials = await this.sharedCredentialsRepository.find({ | ||
| select: { credentialsId: true }, | ||
| where, | ||
| }); | ||
|
|
||
| const result = new Set(sharedCredentials.map((sc) => sc.credentialsId)); | ||
|
|
||
| // Also include global credentials if scopes allow read-only access | ||
| if (this.hasGlobalReadOnlyAccess(scopes)) { | ||
| const globalCreds = await this.credentialsRepository.find({ | ||
| where: { id: In(credentialIds), isGlobal: true }, | ||
| select: ['id'], | ||
| }); | ||
| for (const gc of globalCreds) result.add(gc.id); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| async getCredentialIdsByUserAndRole( | ||
| userIds: string[], | ||
| options: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.