Files
Automata/packages/cli/src/workflows/workflow-sharing.service.ts

94 lines
2.9 KiB
TypeScript

import { Service } from 'typedi';
// eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import
import { In } from '@n8n/typeorm';
import type { User } from '@/databases/entities/user';
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
import { RoleService } from '@/services/role.service';
import type { Scope } from '@n8n/permissions';
import type { ProjectRole } from '@/databases/entities/project-relation';
import type { WorkflowSharingRole } from '@/databases/entities/shared-workflow';
import { ProjectRelationRepository } from '@/databases/repositories/project-relation.repository';
@Service()
export class WorkflowSharingService {
constructor(
private readonly sharedWorkflowRepository: SharedWorkflowRepository,
private readonly roleService: RoleService,
private readonly projectRelationRepository: ProjectRelationRepository,
) {}
/**
* Get the IDs of the workflows that have been shared with the user based on
* scope or roles.
* If `scopes` is passed the roles are inferred. Alternatively `projectRoles`
* and `workflowRoles` can be passed specifically.
*
* Returns all IDs if user has the 'workflow:read' global scope.
*/
async getSharedWorkflowIds(
user: User,
options:
| { scopes: Scope[]; projectId?: string }
| { projectRoles: ProjectRole[]; workflowRoles: WorkflowSharingRole[]; projectId?: string },
): Promise<string[]> {
const { projectId } = options;
if (user.hasGlobalScope('workflow:read')) {
const sharedWorkflows = await this.sharedWorkflowRepository.find({
select: ['workflowId'],
...(projectId && { where: { projectId } }),
});
return sharedWorkflows.map(({ workflowId }) => workflowId);
}
const projectRoles =
'scopes' in options
? this.roleService.rolesWithScope('project', options.scopes)
: options.projectRoles;
const workflowRoles =
'scopes' in options
? this.roleService.rolesWithScope('workflow', options.scopes)
: options.workflowRoles;
const sharedWorkflows = await this.sharedWorkflowRepository.find({
where: {
role: In(workflowRoles),
project: {
projectRelations: {
userId: user.id,
role: In(projectRoles),
},
},
},
select: ['workflowId'],
});
return sharedWorkflows.map(({ workflowId }) => workflowId);
}
async getSharedWorkflowScopes(
workflowIds: string[],
user: User,
): Promise<Array<[string, Scope[]]>> {
const projectRelations = await this.projectRelationRepository.findAllByUser(user.id);
const sharedWorkflows =
await this.sharedWorkflowRepository.getRelationsByWorkflowIdsAndProjectIds(
workflowIds,
projectRelations.map((p) => p.projectId),
);
return workflowIds.map((workflowId) => {
return [
workflowId,
this.roleService.combineResourceScopes(
'workflow',
user,
sharedWorkflows.filter((s) => s.workflowId === workflowId),
projectRelations,
),
];
});
}
}