feat(core): Handle scoped resource not existing with 404 (#16022)

This commit is contained in:
Guillaume Jacquart
2025-06-11 11:19:18 +02:00
committed by GitHub
parent b10effb3fc
commit 42b9a8a0e7
5 changed files with 209 additions and 16 deletions

View File

@@ -6,6 +6,8 @@ import { hasGlobalScope, rolesWithScope, type Scope } from '@n8n/permissions';
import { In } from '@n8n/typeorm';
import { UnexpectedError } from 'n8n-workflow';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
/**
* Check if a user has the required scopes. The check can be:
*
@@ -49,19 +51,33 @@ export async function userHasScopes(
// those resource roles over the resource being checked.
if (credentialId) {
return await Container.get(SharedCredentialsRepository).existsBy({
const credentials = await Container.get(SharedCredentialsRepository).findBy({
credentialsId: credentialId,
projectId: In(userProjectIds),
role: In(rolesWithScope('credential', scopes)),
});
if (!credentials.length) {
throw new NotFoundError(`Credential with ID "${credentialId}" not found.`);
}
return credentials.some(
(c) =>
userProjectIds.includes(c.projectId) &&
rolesWithScope('credential', scopes).includes(c.role),
);
}
if (workflowId) {
return await Container.get(SharedWorkflowRepository).existsBy({
const workflows = await Container.get(SharedWorkflowRepository).findBy({
workflowId,
projectId: In(userProjectIds),
role: In(rolesWithScope('workflow', scopes)),
});
if (!workflows.length) {
throw new NotFoundError(`Workflow with ID "${workflowId}" not found.`);
}
return workflows.some(
(w) =>
userProjectIds.includes(w.projectId) && rolesWithScope('workflow', scopes).includes(w.role),
);
}
if (projectId) return userProjectIds.includes(projectId);