mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
refactor: Workflow sharing bug bash fixes (#4888)
* fix: Prevent workflows with only manual trigger from being activated * fix: Fix workflow id when sharing from workflows list * fix: Update sharing modal translations * fix: Allow sharees to disable workflows and fix issue with unique key when removing a user * refactor: Improve error messages and change logging level to be less verbose * fix: Broken user removal transfer issue * feat: Implement workflow sharing BE telemetry * chore: temporarily add sharing env vars * feat: Implement BE telemetry for workflow sharing * fix: Prevent issues with possibly missing workflow id * feat: Replace WorkflowSharing flag references (no-changelog) (#4918) * ci: Block all external network calls in tests (no-changelog) (#4930) * setup nock to prevent tests from making any external requests * mock all calls to posthog sdk * feat: Replace WorkflowSharing flag references (no-changelog) Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <netroy@users.noreply.github.com> * refactor: Remove temporary feature flag for workflow sharing * refactor: add sharing_role to both manual and node executions * refactor: Allow changing name, position and disabled of read only nodes * feat: Overhaul dynamic translations for local and cloud (#4943) * feat: Overhaul dynamic translations for local and cloud * fix: remove type casting * chore: remove unused translations * fix: fix workflow sharing translation * test: Fix broken test * refactor: remove unnecessary import * refactor: Minor code improvements * refactor: rename dynamicTranslations to contextBasedTranslationKeys * fix: fix type imports * refactor: Consolidate sharing feature check * feat: update cred sharing unavailable translations * feat: update upgrade message when user management not available * fix: rename plan names to Pro and Power * feat: update translations to no longer contain plan names * wip: subworkflow permissions * feat: add workflowsFromSameOwner caller policy * feat: Fix subworkflow permissions * shared entites should check for role when deleting users * refactor: remove circular dependency * role filter shouldn't be an array * fixed role issue * fix: Corrected behavior when removing users * feat: show instance owner credential sharing message only if isnt sharee * feat: update workflow caller policy caller ids labels * feat: update upgrade plan links to contain instance ids * fix: show check errors below creds message only to owner * fix(editor): Hide usage page on cloud * fix: update credential validation error message for sharee * fix(core): Remove duplicate import * fix(editor): Extending deployment types * feat: Overhaul contextual translations (#4992) feat: update how contextual translations work * refactor: improve messageing for subworkflow permissions * test: Fix issue with user deletion and transfer * fix: Explicitly throw error message so it can be displayed in UI Co-authored-by: Alex Grozav <alex@grozav.com> Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <netroy@users.noreply.github.com> Co-authored-by: freyamade <freya@n8n.io> Co-authored-by: Csaba Tuncsik <csaba@n8n.io>
This commit is contained in:
@@ -65,6 +65,7 @@ import * as WorkflowHelpers from '@/WorkflowHelpers';
|
||||
import { getUserById, getWorkflowOwner, whereClause } from '@/UserManagement/UserManagementHelper';
|
||||
import { findSubworkflowStart } from '@/utils';
|
||||
import { PermissionChecker } from './UserManagement/PermissionChecker';
|
||||
import { WorkflowsService } from './workflows/workflows.services';
|
||||
|
||||
const ERROR_TRIGGER_TYPE = config.getEnv('nodes.errorTriggerType');
|
||||
|
||||
@@ -779,34 +780,6 @@ export async function getRunData(
|
||||
): Promise<IWorkflowExecutionDataProcess> {
|
||||
const mode = 'integrated';
|
||||
|
||||
const policy =
|
||||
workflowData.settings?.callerPolicy ?? config.getEnv('workflows.callerPolicyDefaultOption');
|
||||
|
||||
if (policy === 'none') {
|
||||
throw new SubworkflowOperationError(
|
||||
`Target workflow ID ${workflowData.id} may not be called by other workflows.`,
|
||||
'Please update the settings of the target workflow or ask its owner to do so.',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
policy === 'workflowsFromAList' &&
|
||||
typeof workflowData.settings?.callerIds === 'string' &&
|
||||
parentWorkflowId !== undefined
|
||||
) {
|
||||
const allowedCallerIds = workflowData.settings.callerIds
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id !== '');
|
||||
|
||||
if (!allowedCallerIds.includes(parentWorkflowId)) {
|
||||
throw new SubworkflowOperationError(
|
||||
`Target workflow ID ${workflowData.id} may only be called by a list of workflows, which does not include current workflow ID ${parentWorkflowId}.`,
|
||||
'Please update the settings of the target workflow or ask its owner to do so.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const startingNode = findSubworkflowStart(workflowData.nodes);
|
||||
|
||||
// Always start with empty data if no inputData got supplied
|
||||
@@ -852,7 +825,6 @@ export async function getRunData(
|
||||
|
||||
export async function getWorkflowData(
|
||||
workflowInfo: IExecuteWorkflowInfo,
|
||||
userId: string,
|
||||
parentWorkflowId?: string,
|
||||
parentWorkflowSettings?: IWorkflowSettings,
|
||||
): Promise<IWorkflowBase> {
|
||||
@@ -869,23 +841,15 @@ export async function getWorkflowData(
|
||||
// to get initialized first
|
||||
await Db.init();
|
||||
}
|
||||
const user = await getUserById(userId);
|
||||
let relations = ['workflow', 'workflow.tags'];
|
||||
|
||||
if (config.getEnv('workflowTagsDisabled')) {
|
||||
relations = relations.filter((relation) => relation !== 'workflow.tags');
|
||||
}
|
||||
const relations = config.getEnv('workflowTagsDisabled') ? [] : ['tags'];
|
||||
|
||||
const shared = await Db.collections.SharedWorkflow.findOne({
|
||||
relations,
|
||||
where: whereClause({
|
||||
user,
|
||||
entityType: 'workflow',
|
||||
entityId: workflowInfo.id,
|
||||
}),
|
||||
});
|
||||
|
||||
workflowData = shared?.workflow;
|
||||
workflowData = await WorkflowsService.get(
|
||||
{ id: parseInt(workflowInfo.id, 10) },
|
||||
{
|
||||
relations,
|
||||
},
|
||||
);
|
||||
|
||||
if (workflowData === undefined) {
|
||||
throw new Error(`The workflow with the id "${workflowInfo.id}" does not exist.`);
|
||||
@@ -911,7 +875,7 @@ export async function getWorkflowData(
|
||||
async function executeWorkflow(
|
||||
workflowInfo: IExecuteWorkflowInfo,
|
||||
additionalData: IWorkflowExecuteAdditionalData,
|
||||
options?: {
|
||||
options: {
|
||||
parentWorkflowId?: string;
|
||||
inputData?: INodeExecutionData[];
|
||||
parentExecutionId?: string;
|
||||
@@ -926,13 +890,8 @@ async function executeWorkflow(
|
||||
const nodeTypes = NodeTypes();
|
||||
|
||||
const workflowData =
|
||||
options?.loadedWorkflowData ??
|
||||
(await getWorkflowData(
|
||||
workflowInfo,
|
||||
additionalData.userId,
|
||||
options?.parentWorkflowId,
|
||||
options?.parentWorkflowSettings,
|
||||
));
|
||||
options.loadedWorkflowData ??
|
||||
(await getWorkflowData(workflowInfo, options.parentWorkflowId, options.parentWorkflowSettings));
|
||||
|
||||
const workflowName = workflowData ? workflowData.name : undefined;
|
||||
const workflow = new Workflow({
|
||||
@@ -947,23 +906,28 @@ async function executeWorkflow(
|
||||
});
|
||||
|
||||
const runData =
|
||||
options?.loadedRunData ??
|
||||
(await getRunData(workflowData, additionalData.userId, options?.inputData));
|
||||
options.loadedRunData ??
|
||||
(await getRunData(workflowData, additionalData.userId, options.inputData));
|
||||
|
||||
let executionId;
|
||||
|
||||
if (options?.parentExecutionId !== undefined) {
|
||||
executionId = options?.parentExecutionId;
|
||||
if (options.parentExecutionId !== undefined) {
|
||||
executionId = options.parentExecutionId;
|
||||
} else {
|
||||
executionId =
|
||||
options?.parentExecutionId !== undefined
|
||||
? options?.parentExecutionId
|
||||
options.parentExecutionId !== undefined
|
||||
? options.parentExecutionId
|
||||
: await ActiveExecutions.getInstance().add(runData);
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
await PermissionChecker.check(workflow, additionalData.userId);
|
||||
await PermissionChecker.checkSubworkflowExecutePolicy(
|
||||
workflow,
|
||||
additionalData.userId,
|
||||
options.parentWorkflowId,
|
||||
);
|
||||
|
||||
// Create new additionalData to have different workflow loaded and to call
|
||||
// different webhooks
|
||||
@@ -1005,7 +969,7 @@ async function executeWorkflow(
|
||||
runData.executionMode,
|
||||
runExecutionData,
|
||||
);
|
||||
if (options?.parentExecutionId !== undefined) {
|
||||
if (options.parentExecutionId !== undefined) {
|
||||
// Must be changed to become typed
|
||||
return {
|
||||
startedAt: new Date(),
|
||||
@@ -1049,6 +1013,7 @@ async function executeWorkflow(
|
||||
throw {
|
||||
...error,
|
||||
stack: error.stack,
|
||||
message: error.message,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user