n8n/packages/editor-ui/src/permissions.ts
Omar Ajoue 25e9f0817a
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>
2022-12-21 16:42:07 +01:00

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);
};