diff --git a/packages/cli/src/UserManagement/PermissionChecker.ts b/packages/cli/src/UserManagement/PermissionChecker.ts index 9d911343a999d..658ee0c1c03b7 100644 --- a/packages/cli/src/UserManagement/PermissionChecker.ts +++ b/packages/cli/src/UserManagement/PermissionChecker.ts @@ -26,12 +26,19 @@ export class PermissionChecker { // allow if all creds used in this workflow are a subset of // all creds accessible to users who have access to this workflow - const workflowSharings = await Db.collections.SharedWorkflow.find({ - relations: ['workflow'], - where: { workflow: { id: Number(workflow.id) } }, - }); - - const workflowUserIds = workflowSharings.map((s) => s.userId); + let workflowUserIds: string[] = []; + + if (workflow.id) { + const workflowSharings = await Db.collections.SharedWorkflow.find({ + relations: ['workflow'], + where: { workflow: { id: Number(workflow.id) } }, + }); + + workflowUserIds = workflowSharings.map((s) => s.userId); + } else { + // unsaved workflows have no id, so only get credentials for current user + workflowUserIds = [userId]; + } const credentialSharings = await Db.collections.SharedCredentials.find({ where: { user: In(workflowUserIds) }, diff --git a/packages/cli/src/credentials/credentials.controller.ts b/packages/cli/src/credentials/credentials.controller.ts index adbc54e41eaef..ff25a5ff47941 100644 --- a/packages/cli/src/credentials/credentials.controller.ts +++ b/packages/cli/src/credentials/credentials.controller.ts @@ -36,7 +36,7 @@ credentialsController.use('/', EECredentialsController); credentialsController.get( '/', ResponseHelper.send(async (req: CredentialRequest.GetAll): Promise => { - const credentials = await CredentialsService.getAll(req.user); + const credentials = await CredentialsService.getAll(req.user, { roles: ['owner'] }); return credentials.map((credential) => { // eslint-disable-next-line no-param-reassign diff --git a/packages/cli/src/credentials/credentials.service.ee.ts b/packages/cli/src/credentials/credentials.service.ee.ts index 6fcfe64a0976f..cc2935909d87b 100644 --- a/packages/cli/src/credentials/credentials.service.ee.ts +++ b/packages/cli/src/credentials/credentials.service.ee.ts @@ -1,5 +1,5 @@ /* eslint-disable no-param-reassign */ -import { DeleteResult, EntityManager, In, Not } from 'typeorm'; +import { DeleteResult, EntityManager, FindOneOptions, In, Not, ObjectLiteral } from 'typeorm'; import * as Db from '@/Db'; import { RoleService } from '@/role/role.service'; import { CredentialsEntity } from '@db/entities/CredentialsEntity'; @@ -25,6 +25,35 @@ export class EECredentialsService extends CredentialsService { return { ownsCredential: true, credential }; } + /** + * Retrieve the sharing that matches a user and a credential. + */ + static async getSharing( + user: User, + credentialId: number | string, + relations: string[] = ['credentials'], + { allowGlobalOwner } = { allowGlobalOwner: true }, + ): Promise { + const options: FindOneOptions & { where: ObjectLiteral } = { + where: { + credentials: { id: credentialId }, + }, + }; + + // Omit user from where if the requesting user is the global + // owner. This allows the global owner to view and delete + // credentials they don't own. + if (!allowGlobalOwner || user.globalRole.name !== 'owner') { + options.where.user = { id: user.id }; + } + + if (relations?.length) { + options.relations = relations; + } + + return Db.collections.SharedCredentials.findOne(options); + } + static async getSharings( transaction: EntityManager, credentialId: string, diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index 2b5c04a932a2c..7833b87f5b2cc 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -31,7 +31,10 @@ export class CredentialsService { }); } - static async getAll(user: User, options?: { relations: string[] }): Promise { + static async getAll( + user: User, + options?: { relations?: string[]; roles?: string[] }, + ): Promise { const SELECT_FIELDS: Array = [ 'id', 'name', @@ -52,11 +55,21 @@ export class CredentialsService { // if member, return credentials owned by or shared with member - const userSharings = await Db.collections.SharedCredentials.find({ + const whereConditions: FindManyOptions = { where: { user, }, - }); + }; + + if (options?.roles?.length) { + whereConditions.where = { + ...whereConditions.where, + role: { name: In(options.roles) }, + } as FindManyOptions; + whereConditions.relations = ['role']; + } + + const userSharings = await Db.collections.SharedCredentials.find(whereConditions); return Db.collections.Credentials.find({ select: SELECT_FIELDS, @@ -77,7 +90,7 @@ export class CredentialsService { static async getSharing( user: User, credentialId: number | string, - relations: string[] | undefined = ['credentials'], + relations: string[] = ['credentials'], { allowGlobalOwner } = { allowGlobalOwner: true }, ): Promise { const options: FindOneOptions = { @@ -90,8 +103,14 @@ export class CredentialsService { // owner. This allows the global owner to view and delete // credentials they don't own. if (!allowGlobalOwner || user.globalRole.name !== 'owner') { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - options.where.user = { id: user.id }; + options.where = { + ...options.where, + user: { id: user.id }, + role: { name: 'owner' }, + } as FindOneOptions; + if (!relations.includes('role')) { + relations.push('role'); + } } if (relations?.length) { diff --git a/packages/cli/src/workflows/workflows.controller.ee.ts b/packages/cli/src/workflows/workflows.controller.ee.ts index 03894b448e7ae..7e76cbade4149 100644 --- a/packages/cli/src/workflows/workflows.controller.ee.ts +++ b/packages/cli/src/workflows/workflows.controller.ee.ts @@ -247,13 +247,14 @@ EEWorkflowController.post( const workflow = new WorkflowEntity(); Object.assign(workflow, req.body.workflowData); - const safeWorkflow = await EEWorkflows.preventTampering( - workflow, - workflow.id.toString(), - req.user, - ); - - req.body.workflowData.nodes = safeWorkflow.nodes; + if (workflow.id !== undefined) { + const safeWorkflow = await EEWorkflows.preventTampering( + workflow, + workflow.id.toString(), + req.user, + ); + req.body.workflowData.nodes = safeWorkflow.nodes; + } return EEWorkflows.runManually(req.body, req.user, GenericHelpers.getSessionId(req)); }),