feat: Replace owner checks with scope checks (no-changelog) (#7846)

Github issue / Community forum post (link here to close automatically):
This commit is contained in:
Val
2023-11-29 14:48:36 +00:00
committed by GitHub
parent d5762a7539
commit 1cb92ffe16
26 changed files with 136 additions and 78 deletions

View File

@@ -21,7 +21,7 @@ export class WorkflowHistoryService {
private async getSharedWorkflow(user: User, workflowId: string): Promise<SharedWorkflow | null> {
return this.sharedWorkflowRepository.findOne({
where: {
...(!user.isOwner && { userId: user.id }),
...(!(await user.hasGlobalScope('workflow:read')) && { userId: user.id }),
workflowId,
},
});

View File

@@ -211,9 +211,10 @@ workflowsController.get(
const shared = await Container.get(SharedWorkflowRepository).findOne({
relations,
where: whereClause({
where: await whereClause({
user: req.user,
entityType: 'workflow',
globalScope: 'workflow:read',
entityId: workflowId,
roles: ['owner'],
}),

View File

@@ -24,9 +24,10 @@ export class EEWorkflowsService extends WorkflowsService {
user: User,
workflowId: string,
): Promise<{ ownsWorkflow: boolean; workflow?: WorkflowEntity }> {
const sharing = await this.getSharing(user, workflowId, ['workflow', 'role'], {
allowGlobalOwner: false,
});
const sharing = await this.getSharing(user, workflowId, { allowGlobalScope: false }, [
'workflow',
'role',
]);
if (!sharing || sharing.role.name !== 'owner') return { ownsWorkflow: false };

View File

@@ -28,6 +28,7 @@ import { OwnershipService } from '@/services/ownership.service';
import { isStringArray, isWorkflowIdValid } from '@/utils';
import { WorkflowHistoryService } from './workflowHistory/workflowHistory.service.ee';
import { BinaryDataService } from 'n8n-core';
import type { Scope } from '@n8n/permissions';
import { Logger } from '@/Logger';
import { MultiMainSetup } from '@/services/orchestration/main/MultiMainSetup.ee';
import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository';
@@ -36,19 +37,23 @@ import { ExecutionRepository } from '@db/repositories/execution.repository';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
export type WorkflowsGetSharedOptions =
| { allowGlobalScope: true; globalScope: Scope }
| { allowGlobalScope: false };
export class WorkflowsService {
static async getSharing(
user: User,
workflowId: string,
options: WorkflowsGetSharedOptions,
relations: string[] = ['workflow'],
{ allowGlobalOwner } = { allowGlobalOwner: true },
): Promise<SharedWorkflow | null> {
const where: FindOptionsWhere<SharedWorkflow> = { workflowId };
// Omit user from where if the requesting user is the global
// owner. This allows the global owner to view and delete
// workflows they don't own.
if (!allowGlobalOwner || user.globalRole.name !== 'owner') {
// Omit user from where if the requesting user has relevant
// global workflow permissions. This allows the user to
// access workflows they don't own.
if (!options.allowGlobalScope || !(await user.hasGlobalScope(options.globalScope))) {
where.userId = user.id;
}
@@ -195,8 +200,9 @@ export class WorkflowsService {
): Promise<WorkflowEntity> {
const shared = await Container.get(SharedWorkflowRepository).findOne({
relations: ['workflow', 'role'],
where: whereClause({
where: await whereClause({
user,
globalScope: 'workflow:update',
entityType: 'workflow',
entityId: workflowId,
roles,
@@ -476,8 +482,9 @@ export class WorkflowsService {
const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({
relations: ['workflow', 'role'],
where: whereClause({
where: await whereClause({
user,
globalScope: 'workflow:delete',
entityType: 'workflow',
entityId: workflowId,
roles: ['owner'],