mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
* 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>
133 lines
4 KiB
TypeScript
133 lines
4 KiB
TypeScript
/**
|
|
* Permissions table implementation
|
|
*
|
|
* @usage getCredentialPermissions(user, credential).isOwner;
|
|
*/
|
|
|
|
import { IUser, ICredentialsResponse, IRootState, IWorkflowDb } from '@/Interface';
|
|
import { EnterpriseEditionFeature, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
|
|
import { useSettingsStore } from './stores/settings';
|
|
|
|
export enum UserRole {
|
|
InstanceOwner = 'isInstanceOwner',
|
|
ResourceOwner = 'isOwner',
|
|
ResourceEditor = 'isEditor',
|
|
ResourceSharee = 'isSharee',
|
|
}
|
|
|
|
export type IPermissions = Record<string, boolean>;
|
|
|
|
type IPermissionsTableRowTestFn = (permissions: IPermissions) => boolean;
|
|
|
|
export interface IPermissionsTableRow {
|
|
name: string;
|
|
test: string[] | IPermissionsTableRowTestFn;
|
|
}
|
|
|
|
export type IPermissionsTable = IPermissionsTableRow[];
|
|
|
|
/**
|
|
* Returns the permissions for the given user and resource
|
|
*
|
|
* @param user
|
|
* @param table
|
|
*/
|
|
export const parsePermissionsTable = (
|
|
user: IUser | null,
|
|
table: IPermissionsTable,
|
|
): IPermissions => {
|
|
const genericTable = [{ name: UserRole.InstanceOwner, test: () => user?.isOwner }];
|
|
|
|
return [...genericTable, ...table].reduce((permissions: IPermissions, row) => {
|
|
permissions[row.name] = Array.isArray(row.test)
|
|
? row.test.some((ability) => permissions[ability])
|
|
: (row.test as IPermissionsTableRowTestFn)(permissions);
|
|
|
|
return permissions;
|
|
}, {});
|
|
};
|
|
|
|
/**
|
|
* User permissions definition
|
|
*/
|
|
|
|
export const getCredentialPermissions = (user: IUser | null, credential: ICredentialsResponse) => {
|
|
const settingsStore = useSettingsStore();
|
|
const isSharingEnabled = settingsStore.isEnterpriseFeatureEnabled(
|
|
EnterpriseEditionFeature.Sharing,
|
|
);
|
|
|
|
const table: IPermissionsTable = [
|
|
{
|
|
name: UserRole.ResourceOwner,
|
|
test: () =>
|
|
!!(credential && credential.ownedBy && credential.ownedBy.id === user?.id) ||
|
|
!isSharingEnabled,
|
|
},
|
|
{
|
|
name: UserRole.ResourceSharee,
|
|
test: () =>
|
|
!!(
|
|
credential &&
|
|
credential.sharedWith &&
|
|
credential.sharedWith.find((sharee) => sharee.id === user?.id)
|
|
),
|
|
},
|
|
{
|
|
name: 'read',
|
|
test: [UserRole.ResourceOwner, UserRole.InstanceOwner, UserRole.ResourceSharee],
|
|
},
|
|
{ name: 'save', test: [UserRole.ResourceOwner, UserRole.InstanceOwner] },
|
|
{ name: 'updateName', test: [UserRole.ResourceOwner, UserRole.InstanceOwner] },
|
|
{ name: 'updateConnection', test: [UserRole.ResourceOwner] },
|
|
{ name: 'updateSharing', test: [UserRole.ResourceOwner] },
|
|
{ name: 'updateNodeAccess', test: [UserRole.ResourceOwner] },
|
|
{ name: 'delete', test: [UserRole.ResourceOwner, UserRole.InstanceOwner] },
|
|
{ name: 'use', test: [UserRole.ResourceOwner, UserRole.ResourceSharee] },
|
|
];
|
|
|
|
return parsePermissionsTable(user, table);
|
|
};
|
|
|
|
export const getWorkflowPermissions = (user: IUser | null, workflow: IWorkflowDb) => {
|
|
const settingsStore = useSettingsStore();
|
|
const isSharingEnabled = settingsStore.isEnterpriseFeatureEnabled(
|
|
EnterpriseEditionFeature.Sharing,
|
|
);
|
|
const isNewWorkflow = workflow.id === PLACEHOLDER_EMPTY_WORKFLOW_ID;
|
|
|
|
const table: IPermissionsTable = [
|
|
{
|
|
name: UserRole.ResourceOwner,
|
|
test: () =>
|
|
!!(isNewWorkflow || (workflow && workflow.ownedBy && workflow.ownedBy.id === user?.id)) ||
|
|
!isSharingEnabled,
|
|
},
|
|
{
|
|
name: UserRole.ResourceSharee,
|
|
test: () =>
|
|
!!(
|
|
workflow &&
|
|
workflow.sharedWith &&
|
|
workflow.sharedWith.find((sharee) => sharee.id === user?.id)
|
|
),
|
|
},
|
|
{
|
|
name: 'read',
|
|
test: [UserRole.ResourceOwner, UserRole.InstanceOwner, UserRole.ResourceSharee],
|
|
},
|
|
{ name: 'save', test: [UserRole.ResourceOwner, UserRole.InstanceOwner] },
|
|
{ name: 'updateName', test: [UserRole.ResourceOwner, UserRole.InstanceOwner] },
|
|
{ name: 'updateConnection', test: [UserRole.ResourceOwner] },
|
|
{ name: 'updateSharing', test: [UserRole.ResourceOwner] },
|
|
{ name: 'updateNodeAccess', test: [UserRole.ResourceOwner] },
|
|
{ name: 'delete', test: [UserRole.ResourceOwner, UserRole.InstanceOwner] },
|
|
{
|
|
name: 'use',
|
|
test: [UserRole.ResourceOwner, UserRole.InstanceOwner, UserRole.ResourceSharee],
|
|
},
|
|
];
|
|
|
|
return parsePermissionsTable(user, table);
|
|
};
|