Refactor rls backend simplify add tests (#17357)

## Context
Removing full CRUD to RLS since we are actually using an upsert only
over the role resolver, this removes a lot of unused code (could be
re-added later but unlikely). Simplified the folder arch at the same
time
Add simple integration tests to RLS
This commit is contained in:
Weiko
2026-01-22 16:44:18 +01:00
committed by GitHub
parent 669da1a87d
commit 296a3099db
35 changed files with 1085 additions and 1453 deletions
@@ -14,8 +14,8 @@ import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata
import { FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout/constants/flat-page-layout-editable-properties.constant';
import { FLAT_ROLE_TARGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role-target/constants/flat-role-target-editable-properties.constant';
import { FLAT_ROLE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role/constants/flat-role-editable-properties.constant';
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-editable-properties.constant';
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
import { FLAT_SKILL_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-skill/constants/flat-skill-editable-properties.constant';
import { FLAT_VIEW_FIELD_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-editable-properties.constant';
import { FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter-group/constants/flat-view-filter-group-editable-properties.constant';
@@ -1,62 +0,0 @@
/* @license Enterprise */
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate-group.input';
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
export const fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate =
({
createRowLevelPermissionPredicateGroupInput:
rawCreateRowLevelPermissionPredicateGroupInput,
workspaceId,
workspaceCustomApplicationId,
}: {
createRowLevelPermissionPredicateGroupInput: CreateRowLevelPermissionPredicateGroupInput;
workspaceId: string;
workspaceCustomApplicationId: string;
}): FlatRowLevelPermissionPredicateGroup => {
const sanitizedInput = (
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties as unknown as (
input: CreateRowLevelPermissionPredicateGroupInput,
keys: string[],
) => CreateRowLevelPermissionPredicateGroupInput
)(rawCreateRowLevelPermissionPredicateGroupInput, [
'roleId',
'objectMetadataId',
'parentRowLevelPermissionPredicateGroupId',
'logicalOperator',
]);
const {
roleId,
objectMetadataId,
...createRowLevelPermissionPredicateGroupInput
} = sanitizedInput;
const createdAt = new Date().toISOString();
const predicateGroupId = v4();
return {
id: predicateGroupId,
workspaceId,
roleId,
objectMetadataId,
childRowLevelPermissionPredicateGroupIds: [],
rowLevelPermissionPredicateIds: [],
createdAt,
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: predicateGroupId,
parentRowLevelPermissionPredicateGroupId:
createRowLevelPermissionPredicateGroupInput.parentRowLevelPermissionPredicateGroupId ??
null,
logicalOperator:
createRowLevelPermissionPredicateGroupInput.logicalOperator,
positionInRowLevelPermissionPredicateGroup:
createRowLevelPermissionPredicateGroupInput.positionInRowLevelPermissionPredicateGroup ??
null,
applicationId: workspaceCustomApplicationId,
};
};
@@ -1,45 +0,0 @@
/* @license Enterprise */
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { type DeleteRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate-group.input';
import {
RowLevelPermissionPredicateGroupException,
RowLevelPermissionPredicateGroupExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
export const fromDeleteRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow =
({
deleteRowLevelPermissionPredicateGroupInput:
rawDeleteRowLevelPermissionPredicateGroupInput,
flatRowLevelPermissionPredicateGroupMaps,
}: {
deleteRowLevelPermissionPredicateGroupInput: DeleteRowLevelPermissionPredicateGroupInput;
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
}): FlatRowLevelPermissionPredicateGroup => {
const { id: predicateGroupId } = extractAndSanitizeObjectStringFields(
rawDeleteRowLevelPermissionPredicateGroupInput,
['id'],
);
const existingFlatPredicateGroup =
flatRowLevelPermissionPredicateGroupMaps.byId[predicateGroupId];
if (!isDefined(existingFlatPredicateGroup)) {
throw new RowLevelPermissionPredicateGroupException(
t`Row level permission predicate group to delete not found`,
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
);
}
return {
...existingFlatPredicateGroup,
deletedAt: new Date().toISOString(),
};
};
@@ -1,42 +0,0 @@
/* @license Enterprise */
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { type DestroyRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate-group.input';
import {
RowLevelPermissionPredicateGroupException,
RowLevelPermissionPredicateGroupExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
export const fromDestroyRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow =
({
destroyRowLevelPermissionPredicateGroupInput:
rawDestroyRowLevelPermissionPredicateGroupInput,
flatRowLevelPermissionPredicateGroupMaps,
}: {
destroyRowLevelPermissionPredicateGroupInput: DestroyRowLevelPermissionPredicateGroupInput;
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
}): FlatRowLevelPermissionPredicateGroup => {
const { id: predicateGroupId } = extractAndSanitizeObjectStringFields(
rawDestroyRowLevelPermissionPredicateGroupInput,
['id'],
);
const existingFlatPredicateGroup =
flatRowLevelPermissionPredicateGroupMaps.byId[predicateGroupId];
if (!isDefined(existingFlatPredicateGroup)) {
throw new RowLevelPermissionPredicateGroupException(
t`Row level permission predicate group to destroy not found`,
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
);
}
return existingFlatPredicateGroup;
};
@@ -1,55 +0,0 @@
/* @license Enterprise */
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
} from 'twenty-shared/utils';
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/constants/flat-row-level-permission-predicate-group-editable-properties.constant';
import { type UpdateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate-group.input';
import {
RowLevelPermissionPredicateGroupException,
RowLevelPermissionPredicateGroupExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
export const fromUpdateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToUpdateOrThrow =
({
updateRowLevelPermissionPredicateGroupInput:
rawUpdateRowLevelPermissionPredicateGroupInput,
flatRowLevelPermissionPredicateGroupMaps,
}: {
updateRowLevelPermissionPredicateGroupInput: UpdateRowLevelPermissionPredicateGroupInput;
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
}): FlatRowLevelPermissionPredicateGroup => {
const { id: predicateGroupId } =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawUpdateRowLevelPermissionPredicateGroupInput,
['id'],
);
const existingFlatPredicateGroup =
flatRowLevelPermissionPredicateGroupMaps.byId[predicateGroupId];
if (!isDefined(existingFlatPredicateGroup)) {
throw new RowLevelPermissionPredicateGroupException(
t`Row level permission predicate group to update not found`,
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND,
);
}
const sanitizedUpdate = extractAndSanitizeObjectStringFields(
rawUpdateRowLevelPermissionPredicateGroupInput,
FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES,
);
return mergeUpdateInExistingRecord({
existing: existingFlatPredicateGroup,
properties: FLAT_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_EDITABLE_PROPERTIES,
update: sanitizedUpdate,
});
};
@@ -1,74 +0,0 @@
/* @license Enterprise */
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate.input';
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
export const fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate =
({
createRowLevelPermissionPredicateInput:
rawCreateRowLevelPermissionPredicateInput,
workspaceId,
workspaceCustomApplicationId,
}: {
createRowLevelPermissionPredicateInput: CreateRowLevelPermissionPredicateInput;
workspaceId: string;
workspaceCustomApplicationId: string;
}): FlatRowLevelPermissionPredicate => {
const sanitizedInput = (
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties as unknown as (
input: CreateRowLevelPermissionPredicateInput,
keys: string[],
) => CreateRowLevelPermissionPredicateInput
)(rawCreateRowLevelPermissionPredicateInput, [
'fieldMetadataId',
'objectMetadataId',
'roleId',
'rowLevelPermissionPredicateGroupId',
'workspaceMemberFieldMetadataId',
'subFieldName',
'workspaceMemberSubFieldName',
'operand',
]);
const {
fieldMetadataId,
objectMetadataId,
roleId,
value,
...createRowLevelPermissionPredicateInput
} = sanitizedInput;
const createdAt = new Date().toISOString();
const predicateId = v4();
return {
id: predicateId,
fieldMetadataId,
objectMetadataId,
roleId,
workspaceId,
createdAt,
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: predicateId,
operand: createRowLevelPermissionPredicateInput.operand,
value: value,
rowLevelPermissionPredicateGroupId:
createRowLevelPermissionPredicateInput.rowLevelPermissionPredicateGroupId ??
null,
positionInRowLevelPermissionPredicateGroup:
createRowLevelPermissionPredicateInput.positionInRowLevelPermissionPredicateGroup ??
null,
subFieldName: createRowLevelPermissionPredicateInput.subFieldName ?? null,
workspaceMemberFieldMetadataId:
createRowLevelPermissionPredicateInput.workspaceMemberFieldMetadataId ??
null,
workspaceMemberSubFieldName:
createRowLevelPermissionPredicateInput.workspaceMemberSubFieldName ??
null,
applicationId: workspaceCustomApplicationId,
};
};
@@ -1,45 +0,0 @@
/* @license Enterprise */
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { type DeleteRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate.input';
import {
RowLevelPermissionPredicateException,
RowLevelPermissionPredicateExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
export const fromDeleteRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow =
({
deleteRowLevelPermissionPredicateInput:
rawDeleteRowLevelPermissionPredicateInput,
flatRowLevelPermissionPredicateMaps,
}: {
deleteRowLevelPermissionPredicateInput: DeleteRowLevelPermissionPredicateInput;
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
}): FlatRowLevelPermissionPredicate => {
const { id: predicateId } = extractAndSanitizeObjectStringFields(
rawDeleteRowLevelPermissionPredicateInput,
['id'],
);
const existingFlatPredicate =
flatRowLevelPermissionPredicateMaps.byId[predicateId];
if (!isDefined(existingFlatPredicate)) {
throw new RowLevelPermissionPredicateException(
t`Row level permission predicate to delete not found`,
RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
);
}
return {
...existingFlatPredicate,
deletedAt: new Date().toISOString(),
};
};
@@ -1,42 +0,0 @@
/* @license Enterprise */
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { type DestroyRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate.input';
import {
RowLevelPermissionPredicateException,
RowLevelPermissionPredicateExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
export const fromDestroyRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow =
({
destroyRowLevelPermissionPredicateInput:
rawDestroyRowLevelPermissionPredicateInput,
flatRowLevelPermissionPredicateMaps,
}: {
destroyRowLevelPermissionPredicateInput: DestroyRowLevelPermissionPredicateInput;
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
}): FlatRowLevelPermissionPredicate => {
const { id: predicateId } = extractAndSanitizeObjectStringFields(
rawDestroyRowLevelPermissionPredicateInput,
['id'],
);
const existingFlatPredicate =
flatRowLevelPermissionPredicateMaps.byId[predicateId];
if (!isDefined(existingFlatPredicate)) {
throw new RowLevelPermissionPredicateException(
t`Row level permission predicate to destroy not found`,
RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
);
}
return existingFlatPredicate;
};
@@ -1,55 +0,0 @@
/* @license Enterprise */
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
} from 'twenty-shared/utils';
import { FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/constants/flat-row-level-permission-predicate-editable-properties.constant';
import { type UpdateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate.input';
import {
RowLevelPermissionPredicateException,
RowLevelPermissionPredicateExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate.exception';
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.type';
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
export const fromUpdateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToUpdateOrThrow =
({
updateRowLevelPermissionPredicateInput:
rawUpdateRowLevelPermissionPredicateInput,
flatRowLevelPermissionPredicateMaps,
}: {
updateRowLevelPermissionPredicateInput: UpdateRowLevelPermissionPredicateInput;
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
}): FlatRowLevelPermissionPredicate => {
const { id: predicateId } =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawUpdateRowLevelPermissionPredicateInput,
['id'],
);
const existingFlatPredicate =
flatRowLevelPermissionPredicateMaps.byId[predicateId];
if (!isDefined(existingFlatPredicate)) {
throw new RowLevelPermissionPredicateException(
t`Row level permission predicate to update not found`,
RowLevelPermissionPredicateExceptionCode.ROW_LEVEL_PERMISSION_PREDICATE_NOT_FOUND,
);
}
const sanitizedUpdate = extractAndSanitizeObjectStringFields(
rawUpdateRowLevelPermissionPredicateInput,
FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES,
);
return mergeUpdateInExistingRecord({
existing: existingFlatPredicate,
properties: FLAT_ROW_LEVEL_PERMISSION_PREDICATE_EDITABLE_PROPERTIES,
update: sanitizedUpdate,
});
};
@@ -1,23 +0,0 @@
/* @license Enterprise */
import { Field, InputType } from '@nestjs/graphql';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'twenty-shared/types';
@InputType()
export class CreateRowLevelPermissionPredicateGroupInput {
@Field(() => String, { nullable: true })
parentRowLevelPermissionPredicateGroupId?: string | null;
@Field(() => RowLevelPermissionPredicateGroupLogicalOperator)
logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator;
@Field(() => Number, { nullable: true })
positionInRowLevelPermissionPredicateGroup?: number | null;
@Field(() => String)
roleId: string;
@Field(() => String)
objectMetadataId: string;
}
@@ -1,42 +0,0 @@
/* @license Enterprise */
import { Field, InputType } from '@nestjs/graphql';
import GraphQLJSON from 'graphql-type-json';
import {
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
@InputType()
export class CreateRowLevelPermissionPredicateInput {
@Field(() => String)
fieldMetadataId: string;
@Field(() => String)
objectMetadataId: string;
@Field(() => RowLevelPermissionPredicateOperand)
operand: RowLevelPermissionPredicateOperand;
@Field(() => GraphQLJSON, { nullable: true })
value: RowLevelPermissionPredicateValue | null;
@Field(() => String, { nullable: true })
subFieldName?: string | null;
@Field(() => String, { nullable: true })
workspaceMemberFieldMetadataId?: string | null;
@Field(() => String, { nullable: true })
workspaceMemberSubFieldName?: string | null;
@Field(() => String, { nullable: true })
rowLevelPermissionPredicateGroupId?: string | null;
@Field(() => Number, { nullable: true })
positionInRowLevelPermissionPredicateGroup?: number | null;
@Field(() => String)
roleId: string;
}
@@ -1,9 +0,0 @@
/* @license Enterprise */
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class DeleteRowLevelPermissionPredicateGroupInput {
@Field(() => String)
id: string;
}
@@ -1,9 +0,0 @@
/* @license Enterprise */
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class DeleteRowLevelPermissionPredicateInput {
@Field(() => String)
id: string;
}
@@ -1,18 +0,0 @@
/* @license Enterprise */
import { InputType } from '@nestjs/graphql';
import { IDField } from '@ptc-org/nestjs-query-graphql';
import { IsUUID } from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
@InputType()
export class DestroyRowLevelPermissionPredicateGroupInput {
@IDField(() => UUIDScalarType, {
description:
'The id of the row level permission predicate group to destroy.',
})
@IsUUID()
id: string;
}
@@ -1,17 +0,0 @@
/* @license Enterprise */
import { InputType } from '@nestjs/graphql';
import { IDField } from '@ptc-org/nestjs-query-graphql';
import { IsUUID } from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
@InputType()
export class DestroyRowLevelPermissionPredicateInput {
@IDField(() => UUIDScalarType, {
description: 'The id of the row level permission predicate to destroy.',
})
@IsUUID()
id: string;
}
@@ -1,22 +0,0 @@
/* @license Enterprise */
import { Field, InputType } from '@nestjs/graphql';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'twenty-shared/types';
@InputType()
export class UpdateRowLevelPermissionPredicateGroupInput {
@Field(() => String)
id: string;
@Field(() => String, { nullable: true })
parentRowLevelPermissionPredicateGroupId?: string | null;
@Field(() => RowLevelPermissionPredicateGroupLogicalOperator, {
nullable: true,
})
logicalOperator?: RowLevelPermissionPredicateGroupLogicalOperator;
@Field(() => Number, { nullable: true })
positionInRowLevelPermissionPredicateGroup?: number | null;
}
@@ -1,39 +0,0 @@
/* @license Enterprise */
import { Field, InputType } from '@nestjs/graphql';
import GraphQLJSON from 'graphql-type-json';
import {
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
@InputType()
export class UpdateRowLevelPermissionPredicateInput {
@Field(() => String)
id: string;
@Field(() => String, { nullable: true })
fieldMetadataId?: string;
@Field(() => RowLevelPermissionPredicateOperand, { nullable: true })
operand?: RowLevelPermissionPredicateOperand;
@Field(() => GraphQLJSON, { nullable: true })
value?: RowLevelPermissionPredicateValue;
@Field(() => String, { nullable: true })
subFieldName?: string | null;
@Field(() => String, { nullable: true })
workspaceMemberFieldMetadataId?: string | null;
@Field(() => String, { nullable: true })
workspaceMemberSubFieldName?: string | null;
@Field(() => String, { nullable: true })
rowLevelPermissionPredicateGroupId?: string | null;
@Field(() => Number, { nullable: true })
positionInRowLevelPermissionPredicateGroup?: number | null;
}
@@ -15,7 +15,9 @@ export const RowLevelPermissionPredicateGroupExceptionCode =
INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA:
'INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA',
ROLE_NOT_FOUND: 'ROLE_NOT_FOUND',
OBJECT_METADATA_NOT_FOUND: 'OBJECT_METADATA_NOT_FOUND',
UNAUTHORIZED_ROLE_MODIFICATION: 'UNAUTHORIZED_ROLE_MODIFICATION',
UNAUTHORIZED_OBJECT_MODIFICATION: 'UNAUTHORIZED_OBJECT_MODIFICATION',
ROW_LEVEL_PERMISSION_FEATURE_DISABLED:
'ROW_LEVEL_PERMISSION_FEATURE_DISABLED',
} as const);
@@ -27,7 +29,9 @@ const rowLevelPermissionPredicateGroupExceptionUserFriendlyMessages: Record<
ROW_LEVEL_PERMISSION_PREDICATE_GROUP_NOT_FOUND: msg`Row level permission predicate group not found.`,
INVALID_ROW_LEVEL_PERMISSION_PREDICATE_GROUP_DATA: msg`Invalid row level permission predicate group data.`,
ROLE_NOT_FOUND: msg`Role not found.`,
OBJECT_METADATA_NOT_FOUND: msg`Object metadata not found.`,
UNAUTHORIZED_ROLE_MODIFICATION: msg`Cannot modify predicate group belonging to a different role.`,
UNAUTHORIZED_OBJECT_MODIFICATION: msg`Cannot modify predicate group belonging to a different object.`,
ROW_LEVEL_PERMISSION_FEATURE_DISABLED: msg`Row level permission predicate feature is disabled.`,
INTERNAL_SERVER_ERROR: msg`An unexpected error occurred.`,
};
@@ -1,82 +0,0 @@
/* @license Enterprise */
import { UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'twenty-shared/types';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate-group.input';
import { DeleteRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate-group.input';
import { UpdateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate-group.input';
import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
@Resolver(() => RowLevelPermissionPredicateGroupDTO)
@UseGuards(WorkspaceAuthGuard, NoPermissionGuard)
export class RowLevelPermissionPredicateGroupResolver {
constructor(
private readonly predicateGroupService: RowLevelPermissionPredicateGroupService,
) {}
@Query(() => [RowLevelPermissionPredicateGroupDTO])
async getRowLevelPermissionPredicateGroups(
@AuthWorkspace() workspace: WorkspaceEntity,
@Args('roleId', { type: () => String, nullable: true }) roleId?: string,
): Promise<RowLevelPermissionPredicateGroupDTO[]> {
if (roleId) {
return this.predicateGroupService.findByRole(workspace.id, roleId);
}
return this.predicateGroupService.findByWorkspaceId(workspace.id);
}
@Mutation(() => RowLevelPermissionPredicateGroupDTO)
async createRowLevelPermissionPredicateGroup(
@Args('input')
input: CreateRowLevelPermissionPredicateGroupInput,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateGroupDTO> {
return this.predicateGroupService.createOne({
createRowLevelPermissionPredicateGroupInput: {
...input,
logicalOperator:
input.logicalOperator as RowLevelPermissionPredicateGroupLogicalOperator,
},
workspaceId: workspace.id,
});
}
@Mutation(() => RowLevelPermissionPredicateGroupDTO)
async updateRowLevelPermissionPredicateGroup(
@Args('input')
input: UpdateRowLevelPermissionPredicateGroupInput,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateGroupDTO> {
return this.predicateGroupService.updateOne({
updateRowLevelPermissionPredicateGroupInput: {
...input,
logicalOperator:
input.logicalOperator as RowLevelPermissionPredicateGroupLogicalOperator,
},
workspaceId: workspace.id,
});
}
@Mutation(() => RowLevelPermissionPredicateGroupDTO)
async deleteRowLevelPermissionPredicateGroup(
@Args('input')
input: DeleteRowLevelPermissionPredicateGroupInput,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateGroupDTO> {
return this.predicateGroupService.deleteOne({
deleteRowLevelPermissionPredicateGroupInput: {
...input,
},
workspaceId: workspace.id,
});
}
}
@@ -1,96 +0,0 @@
/* @license Enterprise */
import { UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { RowLevelPermissionPredicateOperand } from 'twenty-shared/types';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate.input';
import { DeleteRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate.input';
import { UpdateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate.input';
import { RowLevelPermissionPredicateDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate.dto';
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
@Resolver(() => RowLevelPermissionPredicateDTO)
@UseGuards(WorkspaceAuthGuard, NoPermissionGuard)
export class RowLevelPermissionPredicateResolver {
constructor(
private readonly predicateService: RowLevelPermissionPredicateService,
) {}
@Query(() => [RowLevelPermissionPredicateDTO])
async getRowLevelPermissionPredicates(
@AuthWorkspace() workspace: WorkspaceEntity,
@Args('roleId', { type: () => String, nullable: true }) roleId?: string,
@Args('objectMetadataId', { type: () => String, nullable: true })
objectMetadataId?: string,
): Promise<RowLevelPermissionPredicateDTO[]> {
if (roleId && objectMetadataId) {
return this.predicateService.findByRoleAndObject(
workspace.id,
roleId,
objectMetadataId,
);
}
return this.predicateService.findByWorkspaceId(workspace.id);
}
@Query(() => RowLevelPermissionPredicateDTO, { nullable: true })
async getRowLevelPermissionPredicate(
@Args('id', { type: () => String }) id: string,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateDTO | null> {
return this.predicateService.findById(id, workspace.id);
}
@Mutation(() => RowLevelPermissionPredicateDTO)
async createRowLevelPermissionPredicate(
@Args('input')
input: CreateRowLevelPermissionPredicateInput,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateDTO> {
return this.predicateService.createOne({
createRowLevelPermissionPredicateInput: {
...input,
operand: input.operand as RowLevelPermissionPredicateOperand,
value: input.value,
},
workspaceId: workspace.id,
});
}
@Mutation(() => RowLevelPermissionPredicateDTO)
async updateRowLevelPermissionPredicate(
@Args('input')
input: UpdateRowLevelPermissionPredicateInput,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateDTO> {
return this.predicateService.updateOne({
updateRowLevelPermissionPredicateInput: {
...input,
operand: input.operand as RowLevelPermissionPredicateOperand,
value: input.value,
},
workspaceId: workspace.id,
});
}
@Mutation(() => RowLevelPermissionPredicateDTO)
async deleteRowLevelPermissionPredicate(
@Args('input')
input: DeleteRowLevelPermissionPredicateInput,
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<RowLevelPermissionPredicateDTO> {
return this.predicateService.deleteOne({
deleteRowLevelPermissionPredicateInput: {
...input,
},
workspaceId: workspace.id,
});
}
}
@@ -8,8 +8,6 @@ import { BillingModule } from 'src/engine/core-modules/billing/billing.module';
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { RowLevelPermissionPredicateGroupResolver } from 'src/engine/metadata-modules/row-level-permission-predicate/resolvers/row-level-permission-predicate-group.resolver';
import { RowLevelPermissionPredicateResolver } from 'src/engine/metadata-modules/row-level-permission-predicate/resolvers/row-level-permission-predicate.resolver';
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
@@ -30,8 +28,6 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
providers: [
RowLevelPermissionPredicateService,
RowLevelPermissionPredicateGroupService,
RowLevelPermissionPredicateResolver,
RowLevelPermissionPredicateGroupResolver,
],
exports: [
RowLevelPermissionPredicateService,
@@ -7,215 +7,26 @@ import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-create-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-to-create.util';
import { fromDeleteRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-delete-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-or-throw.util';
import { fromDestroyRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-destroy-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-or-throw.util';
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
import { fromUpdateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToUpdateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-update-row-level-permission-predicate-group-input-to-flat-row-level-permission-predicate-group-to-update-or-throw.util';
import { type CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate-group.input';
import { type DeleteRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate-group.input';
import { type DestroyRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate-group.input';
import { type UpdateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate-group.input';
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import {
RowLevelPermissionPredicateGroupException,
RowLevelPermissionPredicateGroupExceptionCode,
} from 'src/engine/metadata-modules/row-level-permission-predicate/exceptions/row-level-permission-predicate-group.exception';
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@Injectable()
export class RowLevelPermissionPredicateGroupService {
constructor(
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly billingService: BillingService,
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
private readonly configService: ConfigService,
private readonly applicationService: ApplicationService,
) {}
async createOne({
createRowLevelPermissionPredicateGroupInput,
workspaceId,
}: {
createRowLevelPermissionPredicateGroupInput: CreateRowLevelPermissionPredicateGroupInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateGroupDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
const flatGroupToCreate =
fromCreateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToCreate(
{
createRowLevelPermissionPredicateGroupInput,
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
},
);
await this.runMigration({
workspaceId,
flatEntityToCreate: [flatGroupToCreate],
});
const { flatRowLevelPermissionPredicateGroupMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
},
);
return fromFlatRowLevelPermissionPredicateGroupToDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatGroupToCreate.id,
flatEntityMaps: flatRowLevelPermissionPredicateGroupMaps,
}),
);
}
async updateOne({
updateRowLevelPermissionPredicateGroupInput,
workspaceId,
}: {
updateRowLevelPermissionPredicateGroupInput: UpdateRowLevelPermissionPredicateGroupInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateGroupDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { flatRowLevelPermissionPredicateGroupMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
},
);
const flatGroupToUpdate =
fromUpdateRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupToUpdateOrThrow(
{
flatRowLevelPermissionPredicateGroupMaps,
updateRowLevelPermissionPredicateGroupInput,
},
);
await this.runMigration({
workspaceId,
flatEntityToUpdate: [flatGroupToUpdate],
});
const { flatRowLevelPermissionPredicateGroupMaps: recomputedFlatMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
},
);
return fromFlatRowLevelPermissionPredicateGroupToDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatGroupToUpdate.id,
flatEntityMaps: recomputedFlatMaps,
}),
);
}
async deleteOne({
deleteRowLevelPermissionPredicateGroupInput,
workspaceId,
}: {
deleteRowLevelPermissionPredicateGroupInput: DeleteRowLevelPermissionPredicateGroupInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateGroupDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { flatRowLevelPermissionPredicateGroupMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
},
);
const flatGroupWithDeletedAt =
fromDeleteRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow(
{
deleteRowLevelPermissionPredicateGroupInput,
flatRowLevelPermissionPredicateGroupMaps,
},
);
await this.runMigration({
workspaceId,
flatEntityToUpdate: [flatGroupWithDeletedAt],
});
const { flatRowLevelPermissionPredicateGroupMaps: recomputedFlatMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
},
);
return fromFlatRowLevelPermissionPredicateGroupToDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatGroupWithDeletedAt.id,
flatEntityMaps: recomputedFlatMaps,
}),
);
}
async destroyOne({
destroyRowLevelPermissionPredicateGroupInput,
workspaceId,
}: {
destroyRowLevelPermissionPredicateGroupInput: DestroyRowLevelPermissionPredicateGroupInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateGroupDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { flatRowLevelPermissionPredicateGroupMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateGroupMaps'],
},
);
const flatGroupToDelete =
fromDestroyRowLevelPermissionPredicateGroupInputToFlatRowLevelPermissionPredicateGroupOrThrow(
{
destroyRowLevelPermissionPredicateGroupInput,
flatRowLevelPermissionPredicateGroupMaps,
},
);
await this.runMigration({
workspaceId,
flatEntityToDelete: [flatGroupToDelete],
});
return fromFlatRowLevelPermissionPredicateGroupToDto(flatGroupToDelete);
}
async findByWorkspaceId(
workspaceId: string,
): Promise<RowLevelPermissionPredicateGroupDTO[]> {
@@ -318,45 +129,6 @@ export class RowLevelPermissionPredicateGroupService {
]);
}
private async runMigration({
workspaceId,
flatEntityToCreate = [],
flatEntityToUpdate = [],
flatEntityToDelete = [],
}: {
workspaceId: string;
flatEntityToCreate?: FlatRowLevelPermissionPredicateGroup[];
flatEntityToUpdate?: FlatRowLevelPermissionPredicateGroup[];
flatEntityToDelete?: FlatRowLevelPermissionPredicateGroup[];
}): Promise<void> {
const validateAndBuildResult =
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
{
allFlatEntityOperationByMetadataName: {
rowLevelPermissionPredicateGroup: {
flatEntityToCreate,
flatEntityToDelete,
flatEntityToUpdate,
},
},
workspaceId,
isSystemBuild: false,
},
);
if (isDefined(validateAndBuildResult)) {
throw new WorkspaceMigrationBuilderException(
validateAndBuildResult,
'Validation errors occurred while applying row level permission predicate group mutation',
);
}
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
'rolesPermissions',
'flatRowLevelPermissionPredicateMaps',
]);
}
private async hasRowLevelPermissionFeature(
workspaceId: string,
): Promise<boolean> {
@@ -372,16 +144,4 @@ export class RowLevelPermissionPredicateGroupService {
return hasValidEnterpriseKey && isRowLevelPermissionEnabled;
}
private async hasRowLevelPermissionFeatureOrThrow(workspaceId: string) {
const hasRowLevelPermissionFeature =
await this.hasRowLevelPermissionFeature(workspaceId);
if (!hasRowLevelPermissionFeature) {
throw new RowLevelPermissionPredicateGroupException(
'Row level permission predicate feature is disabled',
RowLevelPermissionPredicateGroupExceptionCode.ROW_LEVEL_PERMISSION_FEATURE_DISABLED,
);
}
}
}
@@ -11,18 +11,9 @@ import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/bil
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate-group/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
import { fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-create-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-to-create.util';
import { fromDeleteRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-delete-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-or-throw.util';
import { fromDestroyRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-destroy-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-or-throw.util';
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
import { fromFlatRowLevelPermissionPredicateToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-to-dto.util';
import { fromUpdateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToUpdateOrThrow } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-update-row-level-permission-predicate-input-to-flat-row-level-permission-predicate-to-update-or-throw.util';
import { type CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/create-row-level-permission-predicate.input';
import { type DeleteRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/delete-row-level-permission-predicate.input';
import { type DestroyRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/destroy-row-level-permission-predicate.input';
import { type UpdateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/update-row-level-permission-predicate.input';
import {
type RowLevelPermissionPredicateGroupInput,
type RowLevelPermissionPredicateInput,
@@ -51,176 +42,6 @@ export class RowLevelPermissionPredicateService {
private readonly applicationService: ApplicationService,
) {}
async createOne({
createRowLevelPermissionPredicateInput,
workspaceId,
}: {
createRowLevelPermissionPredicateInput: CreateRowLevelPermissionPredicateInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
const flatPredicateToCreate =
fromCreateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToCreate(
{
createRowLevelPermissionPredicateInput,
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
},
);
await this.runMigration({
workspaceId,
flatEntityToCreate: [flatPredicateToCreate],
});
const { flatRowLevelPermissionPredicateMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
},
);
return fromFlatRowLevelPermissionPredicateToDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatPredicateToCreate.id,
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
}),
);
}
async updateOne({
updateRowLevelPermissionPredicateInput,
workspaceId,
}: {
updateRowLevelPermissionPredicateInput: UpdateRowLevelPermissionPredicateInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { flatRowLevelPermissionPredicateMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
},
);
const flatPredicateToUpdate =
fromUpdateRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateToUpdateOrThrow(
{
flatRowLevelPermissionPredicateMaps,
updateRowLevelPermissionPredicateInput,
},
);
await this.runMigration({
workspaceId,
flatEntityToUpdate: [flatPredicateToUpdate],
});
const { flatRowLevelPermissionPredicateMaps: recomputedFlatMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
},
);
return fromFlatRowLevelPermissionPredicateToDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatPredicateToUpdate.id,
flatEntityMaps: recomputedFlatMaps,
}),
);
}
async deleteOne({
deleteRowLevelPermissionPredicateInput,
workspaceId,
}: {
deleteRowLevelPermissionPredicateInput: DeleteRowLevelPermissionPredicateInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { flatRowLevelPermissionPredicateMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
},
);
const flatPredicateWithDeletedAt =
fromDeleteRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow(
{
deleteRowLevelPermissionPredicateInput,
flatRowLevelPermissionPredicateMaps,
},
);
await this.runMigration({
workspaceId,
flatEntityToUpdate: [flatPredicateWithDeletedAt],
});
const { flatRowLevelPermissionPredicateMaps: recomputedFlatMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
},
);
return fromFlatRowLevelPermissionPredicateToDto(
findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId: flatPredicateWithDeletedAt.id,
flatEntityMaps: recomputedFlatMaps,
}),
);
}
async destroyOne({
destroyRowLevelPermissionPredicateInput,
workspaceId,
}: {
destroyRowLevelPermissionPredicateInput: DestroyRowLevelPermissionPredicateInput;
workspaceId: string;
}): Promise<RowLevelPermissionPredicateDTO> {
await this.hasRowLevelPermissionFeatureOrThrow(workspaceId);
const { flatRowLevelPermissionPredicateMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatRowLevelPermissionPredicateMaps'],
},
);
const flatPredicateToDelete =
fromDestroyRowLevelPermissionPredicateInputToFlatRowLevelPermissionPredicateOrThrow(
{
destroyRowLevelPermissionPredicateInput,
flatRowLevelPermissionPredicateMaps,
},
);
await this.runMigration({
workspaceId,
flatEntityToDelete: [flatPredicateToDelete],
});
return fromFlatRowLevelPermissionPredicateToDto(flatPredicateToDelete);
}
async findByWorkspaceId(
workspaceId: string,
): Promise<RowLevelPermissionPredicateDTO[]> {
@@ -378,7 +199,6 @@ export class RowLevelPermissionPredicateService {
existingGroups,
inputGroups: predicateGroups,
roleId,
objectMetadataId,
workspaceId,
flatRowLevelPermissionPredicateGroupMaps,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
@@ -449,7 +269,6 @@ export class RowLevelPermissionPredicateService {
existingGroups,
inputGroups,
roleId,
objectMetadataId,
workspaceId,
flatRowLevelPermissionPredicateGroupMaps,
workspaceCustomApplicationId,
@@ -457,7 +276,6 @@ export class RowLevelPermissionPredicateService {
existingGroups: FlatRowLevelPermissionPredicateGroup[];
inputGroups: RowLevelPermissionPredicateGroupInput[];
roleId: string;
objectMetadataId: string;
workspaceId: string;
flatRowLevelPermissionPredicateGroupMaps: FlatEntityMaps<FlatRowLevelPermissionPredicateGroup>;
workspaceCustomApplicationId: string;
@@ -495,7 +313,7 @@ export class RowLevelPermissionPredicateService {
id: groupId,
workspaceId,
roleId,
objectMetadataId,
objectMetadataId: inputGroup.objectMetadataId,
logicalOperator: inputGroup.logicalOperator,
parentRowLevelPermissionPredicateGroupId:
inputGroup.parentRowLevelPermissionPredicateGroupId ?? null,
@@ -676,45 +494,6 @@ export class RowLevelPermissionPredicateService {
]);
}
private async runMigration({
workspaceId,
flatEntityToCreate = [],
flatEntityToUpdate = [],
flatEntityToDelete = [],
}: {
workspaceId: string;
flatEntityToCreate?: FlatRowLevelPermissionPredicate[];
flatEntityToUpdate?: FlatRowLevelPermissionPredicate[];
flatEntityToDelete?: FlatRowLevelPermissionPredicate[];
}): Promise<void> {
const validateAndBuildResult =
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
{
allFlatEntityOperationByMetadataName: {
rowLevelPermissionPredicate: {
flatEntityToCreate,
flatEntityToDelete,
flatEntityToUpdate,
},
},
workspaceId,
isSystemBuild: false,
},
);
if (isDefined(validateAndBuildResult)) {
throw new WorkspaceMigrationBuilderException(
validateAndBuildResult,
'Validation errors occurred while applying row level permission predicate mutation',
);
}
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
'rolesPermissions',
'flatRowLevelPermissionPredicateGroupMaps',
]);
}
private async hasRowLevelPermissionFeature(
workspaceId: string,
): Promise<boolean> {