Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement runtine check for enterprise features #4676

Merged
merged 10 commits into from
Nov 22, 2022
30 changes: 20 additions & 10 deletions packages/cli/src/UserManagement/PermissionChecker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { INode, NodeOperationError, Workflow } from 'n8n-workflow';
import { In } from 'typeorm';
import { FindManyOptions, In, ObjectLiteral } from 'typeorm';
import * as Db from '@/Db';
import config from '@/config';
import type { SharedCredentials } from '@db/entities/SharedCredentials';
import { getRole } from './UserManagementHelper';

export class PermissionChecker {
/**
Expand All @@ -26,23 +29,30 @@ export class PermissionChecker {
// allow if all creds used in this workflow are a subset of
// all creds accessible to users who have access to this workflow

let workflowUserIds: string[] = [];
let workflowUserIds = [userId];

if (workflow.id) {
if (workflow.id && config.getEnv('enterprise.workflowSharingEnabled')) {
const workflowSharings = await Db.collections.SharedWorkflow.find({
relations: ['workflow'],
where: { workflow: { id: Number(workflow.id) } },
});

workflowUserIds = workflowSharings.map((s) => s.userId);
} else {
// unsaved workflows have no id, so only get credentials for current user
workflowUserIds = [userId];
}

const credentialSharings = await Db.collections.SharedCredentials.find({
where: { user: In(workflowUserIds) },
});
const credentialsWhereCondition: FindManyOptions<SharedCredentials> & { where: ObjectLiteral } =
{
where: { user: In(workflowUserIds) },
};

if (!config.getEnv('enterprise.features.sharing')) {
// If credential sharing is not enabled, get only credentials owned by this user
const credentialOwnerRole = await getRole('credential', 'owner');
credentialsWhereCondition.where.role = credentialOwnerRole;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const credentialOwnerRole = await getRole('credential', 'owner');
credentialsWhereCondition.where.role = credentialOwnerRole;
credentialsWhereCondition.where.role = await getRole('credential', 'owner');

}

const credentialSharings = await Db.collections.SharedCredentials.find(
credentialsWhereCondition,
);

const accessibleCredIds = credentialSharings.map((s) => s.credentialId.toString());

Expand Down
12 changes: 11 additions & 1 deletion packages/cli/src/UserManagement/UserManagementHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as Db from '@/Db';
import * as ResponseHelper from '@/ResponseHelper';
import { PublicUser } from './Interfaces';
import { MAX_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH, User } from '@db/entities/User';
import { Role } from '@db/entities/Role';
import { Role, RoleNames, RoleScopes } from '@db/entities/Role';
import { AuthenticatedRequest } from '@/requests';
import config from '@/config';
import { getWebhookBaseUrl } from '../WebhookHelpers';
Expand Down Expand Up @@ -78,6 +78,16 @@ export async function getInstanceOwner(): Promise<User> {
return owner;
}

export async function getRole(scope: RoleScopes, name: RoleNames): Promise<Role> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use lookup types to avoid ex/importing: Role['name'], Role['scope'].

const role = await Db.collections.Role.findOneOrFail({
where: {
name,
scope,
},
});
return role;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const role = await Db.collections.Role.findOneOrFail({
where: {
name,
scope,
},
});
return role;
return await Db.collections.Role.findOneOrFail({
where: {
name,
scope,
},
});

}

/**
* Return the n8n instance base URL without trailing slash.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/databases/entities/Role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { SharedWorkflow } from './SharedWorkflow';
import { SharedCredentials } from './SharedCredentials';
import { AbstractEntity } from './AbstractEntity';

type RoleNames = 'owner' | 'member' | 'user' | 'editor';
type RoleScopes = 'global' | 'workflow' | 'credential';
export type RoleNames = 'owner' | 'member' | 'user' | 'editor';
export type RoleScopes = 'global' | 'workflow' | 'credential';

@Entity()
@Unique(['scope', 'name'])
Expand Down