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:
@@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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'],
|
||||
}),
|
||||
|
||||
@@ -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 };
|
||||
|
||||
|
||||
@@ -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'],
|
||||
|
||||
Reference in New Issue
Block a user