Fix insert new record with RLS (#17164)

## Context
Now that RLS predicates are applied, creating a record through the FE
(which is empty by default) is failing if your role has predicates and
your input does not respect them (which will always be true since, as
said above, input will be pretty much empty)

## Implementation
- Moved isMatching* filters to twenty-shared
- Implemented isMatchingRlsPredicates utils in the backend (ORM) to
check before insertion/update if the record is matching the current user
role Rls predicates, reusing the isMatching* filters utils moved to
twenty-shared
- Frontend now applies RLS predicates before creating a new record
(similarly to what we do with view filters)

Note:
It seems composite were not properly handled with view-filter insertion
logic, since I'm reusing the util for now, the issue remains for RLS and
will need to be addressed
This commit is contained in:
Weiko
2026-01-15 17:40:47 +01:00
committed by GitHub
parent 2cff75d772
commit 8413c6f3dd
84 changed files with 1499 additions and 463 deletions
@@ -284,6 +284,12 @@ export const ALL_METADATA_RELATIONS = {
objectPermissions: null,
permissionFlags: null,
fieldPermissions: null,
rowLevelPermissionPredicates: {
metadataName: 'rowLevelPermissionPredicate',
},
rowLevelPermissionPredicateGroups: {
metadataName: 'rowLevelPermissionPredicateGroup',
},
},
},
roleTarget: {
@@ -62,6 +62,8 @@ exports[`getMetadataRelatedMetadataNames should return related metadata names fo
exports[`getMetadataRelatedMetadataNames should return related metadata names for role 1`] = `
[
"roleTarget",
"rowLevelPermissionPredicate",
"rowLevelPermissionPredicateGroup",
]
`;
@@ -54,5 +54,7 @@ export const fromCreateRoleInputToFlatRoleToCreate = ({
objectPermissionIds: [],
permissionFlagIds: [],
fieldPermissionIds: [],
rowLevelPermissionPredicateIds: [],
rowLevelPermissionPredicateGroupIds: [],
};
};
@@ -27,5 +27,10 @@ export const fromRoleEntityToFlatRole = (role: RoleEntity): FlatRole => {
objectPermissionIds: role.objectPermissions.map((op) => op.id),
permissionFlagIds: role.permissionFlags.map((pf) => pf.id),
fieldPermissionIds: role.fieldPermissions.map((fp) => fp.id),
rowLevelPermissionPredicateIds: role.rowLevelPermissionPredicates.map(
(rp) => rp.id,
),
rowLevelPermissionPredicateGroupIds:
role.rowLevelPermissionPredicateGroups.map((rp) => rp.id),
};
};
@@ -4,6 +4,8 @@ import GraphQLJSON from 'graphql-type-json';
import { RestrictedFieldsPermissions } from 'twenty-shared/types';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
import { RowLevelPermissionPredicateDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate.dto';
@ObjectType('ObjectPermission')
export class ObjectPermissionDTO {
@@ -26,4 +28,10 @@ export class ObjectPermissionDTO {
nullable: true,
})
restrictedFields?: RestrictedFieldsPermissions;
@Field(() => [RowLevelPermissionPredicateDTO], { nullable: true })
rowLevelPermissionPredicates?: RowLevelPermissionPredicateDTO[];
@Field(() => [RowLevelPermissionPredicateGroupDTO], { nullable: true })
rowLevelPermissionPredicateGroups?: RowLevelPermissionPredicateGroupDTO[];
}
@@ -61,6 +61,8 @@ describe('FieldPermissionService', () => {
canSoftDeleteObjectRecords: false,
canDestroyObjectRecords: false,
restrictedFields: {},
rowLevelPermissionPredicates: [],
rowLevelPermissionPredicateGroups: [],
},
[fieldRelationMock.objectMetadataId]: {
canReadObjectRecords: true,
@@ -68,6 +70,8 @@ describe('FieldPermissionService', () => {
canSoftDeleteObjectRecords: false,
canDestroyObjectRecords: false,
restrictedFields: {},
rowLevelPermissionPredicates: [],
rowLevelPermissionPredicateGroups: [],
},
},
};
@@ -13,6 +13,8 @@ import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permis
import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
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 { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity('role')
@@ -92,4 +94,21 @@ export class RoleEntity extends SyncableEntity implements Required<RoleEntity> {
(fieldPermission: FieldPermissionEntity) => fieldPermission.role,
)
fieldPermissions: Relation<FieldPermissionEntity[]>;
@OneToMany(
() => RowLevelPermissionPredicateEntity,
(rowLevelPermissionPredicate: RowLevelPermissionPredicateEntity) =>
rowLevelPermissionPredicate.role,
)
rowLevelPermissionPredicates: Relation<RowLevelPermissionPredicateEntity[]>;
@OneToMany(
() => RowLevelPermissionPredicateGroupEntity,
(
rowLevelPermissionPredicateGroup: RowLevelPermissionPredicateGroupEntity,
) => rowLevelPermissionPredicateGroup.role,
)
rowLevelPermissionPredicateGroups: Relation<
RowLevelPermissionPredicateGroupEntity[]
>;
}
@@ -17,13 +17,15 @@ import { ObjectPermissionModule } from 'src/engine/metadata-modules/object-permi
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
import { PermissionFlagModule } from 'src/engine/metadata-modules/permission-flag/permission-flag.module';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { RowLevelPermissionModule } from 'src/engine/metadata-modules/row-level-permission-predicate/row-level-permission.module';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleResolver } from 'src/engine/metadata-modules/role/role.resolver';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { WorkspaceFlatRoleMapCacheService } from 'src/engine/metadata-modules/role/services/workspace-flat-role-map-cache.service';
import { WorkspaceRolesPermissionsCacheService } from 'src/engine/metadata-modules/role/services/workspace-roles-permissions-cache.service';
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 { RowLevelPermissionModule } from 'src/engine/metadata-modules/row-level-permission-predicate/row-level-permission.module';
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { WorkspaceMigrationBuilderGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-builder-graphql-api-exception.interceptor';
@@ -39,6 +41,8 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
FieldPermissionEntity,
UserWorkspaceEntity,
ObjectMetadataEntity,
RowLevelPermissionPredicateEntity,
RowLevelPermissionPredicateGroupEntity,
]),
UserRoleModule,
AiAgentRoleModule,
@@ -14,6 +14,8 @@ import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permi
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
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 { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -34,6 +36,10 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
private readonly permissionFlagRepository: Repository<PermissionFlagEntity>,
@InjectRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: Repository<FieldPermissionEntity>,
@InjectRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: Repository<RowLevelPermissionPredicateEntity>,
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
) {
super();
}
@@ -47,6 +53,8 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
objectPermissions,
permissionFlags,
fieldPermissions,
rowLevelPermissionPredicates,
rowLevelPermissionPredicateGroups,
] = await Promise.all([
this.roleRepository.find({
where: { workspaceId },
@@ -72,6 +80,16 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
select: ['id', 'roleId'],
withDeleted: true,
}),
this.rowLevelPermissionPredicateRepository.find({
where: { workspaceId },
select: ['id', 'roleId'],
withDeleted: true,
}),
this.rowLevelPermissionPredicateGroupRepository.find({
where: { workspaceId },
select: ['id', 'roleId'],
withDeleted: true,
}),
]);
const [
@@ -79,6 +97,8 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
objectPermissionsByRoleId,
permissionFlagsByRoleId,
fieldPermissionsByRoleId,
rowLevelPermissionPredicatesByRoleId,
rowLevelPermissionPredicateGroupsByRoleId,
] = (
[
{
@@ -97,6 +117,14 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
entities: fieldPermissions,
foreignKey: 'roleId',
},
{
entities: rowLevelPermissionPredicates,
foreignKey: 'roleId',
},
{
entities: rowLevelPermissionPredicateGroups,
foreignKey: 'roleId',
},
] as const
).map(regroupEntitiesByRelatedEntityId);
@@ -109,6 +137,10 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
objectPermissions: objectPermissionsByRoleId.get(roleEntity.id) || [],
permissionFlags: permissionFlagsByRoleId.get(roleEntity.id) || [],
fieldPermissions: fieldPermissionsByRoleId.get(roleEntity.id) || [],
rowLevelPermissionPredicates:
rowLevelPermissionPredicatesByRoleId.get(roleEntity.id) || [],
rowLevelPermissionPredicateGroups:
rowLevelPermissionPredicateGroupsByRoleId.get(roleEntity.id) || [],
} as RoleEntity);
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
@@ -1,6 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { PermissionFlagType } from 'twenty-shared/constants';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
type ObjectsPermissions,
@@ -9,7 +10,6 @@ import {
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { PermissionFlagType } from 'twenty-shared/constants';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
@@ -42,7 +42,13 @@ export class WorkspaceRolesPermissionsCacheService extends WorkspaceCacheProvide
where: {
workspaceId,
},
relations: ['objectPermissions', 'permissionFlags', 'fieldPermissions'],
relations: [
'objectPermissions',
'permissionFlags',
'fieldPermissions',
'rowLevelPermissionPredicates',
'rowLevelPermissionPredicateGroups',
],
});
const workspaceObjectMetadataCollection =
@@ -132,6 +138,18 @@ export class WorkspaceRolesPermissionsCacheService extends WorkspaceCacheProvide
canSoftDeleteObjectRecords: canSoftDelete,
canDestroyObjectRecords: canDestroy,
restrictedFields,
rowLevelPermissionPredicates:
role.rowLevelPermissionPredicates.filter(
(rowLevelPermissionPredicate) =>
rowLevelPermissionPredicate.objectMetadataId ===
objectMetadataId,
),
rowLevelPermissionPredicateGroups:
role.rowLevelPermissionPredicateGroups.filter(
(rowLevelPermissionPredicateGroup) =>
rowLevelPermissionPredicateGroup.objectMetadataId ===
objectMetadataId,
),
};
}
@@ -15,6 +15,9 @@ export const fromUserWorkspacePermissionsToUserWorkspacePermissionsDto = ({
canSoftDeleteObjectRecords: permissions.canSoftDeleteObjectRecords,
canDestroyObjectRecords: permissions.canDestroyObjectRecords,
restrictedFields: permissions.restrictedFields,
rowLevelPermissionPredicates: permissions.rowLevelPermissionPredicates,
rowLevelPermissionPredicateGroups:
permissions.rowLevelPermissionPredicateGroups,
}),
);
@@ -2,7 +2,7 @@
import { Field, InputType } from '@nestjs/graphql';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'twenty-shared/types';
@InputType()
export class CreateRowLevelPermissionPredicateGroupInput {
@@ -3,9 +3,10 @@
import { Field, InputType } from '@nestjs/graphql';
import GraphQLJSON from 'graphql-type-json';
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
import {
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
@InputType()
export class CreateRowLevelPermissionPredicateInput {
@@ -2,7 +2,7 @@
import { Field, InputType } from '@nestjs/graphql';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'twenty-shared/types';
@InputType()
export class UpdateRowLevelPermissionPredicateGroupInput {
@@ -3,9 +3,10 @@
import { Field, InputType } from '@nestjs/graphql';
import GraphQLJSON from 'graphql-type-json';
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
import {
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
@InputType()
export class UpdateRowLevelPermissionPredicateInput {
@@ -11,11 +11,13 @@ import {
ValidateNested,
} from 'class-validator';
import GraphQLJSON from 'graphql-type-json';
import {
RowLevelPermissionPredicateGroupLogicalOperator,
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
@InputType()
export class RowLevelPermissionPredicateInput {
@@ -2,7 +2,7 @@
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'twenty-shared/types';
registerEnumType(RowLevelPermissionPredicateGroupLogicalOperator, {
name: 'RowLevelPermissionPredicateGroupLogicalOperator',
@@ -3,9 +3,10 @@
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import GraphQLJSON from 'graphql-type-json';
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
import { RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
import {
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
registerEnumType(RowLevelPermissionPredicateOperand, {
name: 'RowLevelPermissionPredicateOperand',
@@ -1,5 +1,9 @@
/* @license Enterprise */
import {
RowLevelPermissionPredicateGroup,
RowLevelPermissionPredicateGroupLogicalOperator,
} from 'twenty-shared/types';
import {
Column,
CreateDateColumn,
@@ -17,7 +21,6 @@ import {
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity({ name: 'rowLevelPermissionPredicateGroup', schema: 'core' })
@@ -28,7 +31,9 @@ import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-enti
])
export class RowLevelPermissionPredicateGroupEntity
extends SyncableEntity
implements Required<RowLevelPermissionPredicateGroupEntity>
implements
Required<RowLevelPermissionPredicateGroupEntity>,
RowLevelPermissionPredicateGroup
{
@PrimaryGeneratedColumn('uuid')
id: string;
@@ -1,5 +1,10 @@
/* @license Enterprise */
import {
RowLevelPermissionPredicate,
RowLevelPermissionPredicateOperand,
RowLevelPermissionPredicateValue,
} from 'twenty-shared/types';
import {
Column,
CreateDateColumn,
@@ -17,8 +22,6 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
import { type RowLevelPermissionPredicateValue } from 'src/engine/metadata-modules/row-level-permission-predicate/types/row-level-permission-predicate-value.type';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
@Entity({ name: 'rowLevelPermissionPredicate', schema: 'core' })
@@ -31,7 +34,9 @@ import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-enti
@Index('IDX_RLPP_GROUP_ID', ['rowLevelPermissionPredicateGroupId'])
export class RowLevelPermissionPredicateEntity
extends SyncableEntity
implements Required<RowLevelPermissionPredicateEntity>
implements
Required<RowLevelPermissionPredicateEntity>,
RowLevelPermissionPredicate
{
@PrimaryGeneratedColumn('uuid')
id: string;
@@ -1,6 +0,0 @@
/* @license Enterprise */
export enum RowLevelPermissionPredicateGroupLogicalOperator {
AND = 'AND',
OR = 'OR',
}
@@ -1,20 +0,0 @@
/* @license Enterprise */
export enum RowLevelPermissionPredicateOperand {
IS = 'IS',
IS_NOT_NULL = 'IS_NOT_NULL',
IS_NOT = 'IS_NOT',
LESS_THAN_OR_EQUAL = 'LESS_THAN_OR_EQUAL',
GREATER_THAN_OR_EQUAL = 'GREATER_THAN_OR_EQUAL',
IS_BEFORE = 'IS_BEFORE',
IS_AFTER = 'IS_AFTER',
CONTAINS = 'CONTAINS',
DOES_NOT_CONTAIN = 'DOES_NOT_CONTAIN',
IS_EMPTY = 'IS_EMPTY',
IS_NOT_EMPTY = 'IS_NOT_EMPTY',
IS_RELATIVE = 'IS_RELATIVE',
IS_IN_PAST = 'IS_IN_PAST',
IS_IN_FUTURE = 'IS_IN_FUTURE',
IS_TODAY = 'IS_TODAY',
VECTOR_SEARCH = 'VECTOR_SEARCH',
}
@@ -3,6 +3,8 @@
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';
@@ -11,7 +13,6 @@ import { CreateRowLevelPermissionPredicateGroupInput } from 'src/engine/metadata
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 { RowLevelPermissionPredicateGroupLogicalOperator } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-group-logical-operator.enum';
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
@Resolver(() => RowLevelPermissionPredicateGroupDTO)
@@ -3,6 +3,8 @@
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';
@@ -11,7 +13,6 @@ import { CreateRowLevelPermissionPredicateInput } from 'src/engine/metadata-modu
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 { RowLevelPermissionPredicateOperand } from 'src/engine/metadata-modules/row-level-permission-predicate/enums/row-level-permission-predicate-operand';
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
@Resolver(() => RowLevelPermissionPredicateDTO)
@@ -18,19 +18,16 @@ import { type DestroyRowLevelPermissionPredicateGroupInput } from 'src/engine/me
import { type 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 { 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';
const RLP_CACHE_KEYS = [
'flatRowLevelPermissionPredicateMaps',
'flatRowLevelPermissionPredicateGroupMaps',
] as const;
@Injectable()
export class RowLevelPermissionPredicateGroupService {
constructor(
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly workspaceCacheService: WorkspaceCacheService,
) {}
async createOne({
@@ -290,9 +287,9 @@ export class RowLevelPermissionPredicateGroupService {
);
}
await this.flatEntityMapsCacheService.invalidateFlatEntityMaps({
workspaceId,
flatMapsKeys: [...RLP_CACHE_KEYS],
});
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
'rolesPermissions',
'flatRowLevelPermissionPredicateMaps',
]);
}
}
@@ -28,6 +28,7 @@ import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules
import { RowLevelPermissionPredicateDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate.dto';
import { type FlatRowLevelPermissionPredicateGroup } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group.type';
import { type FlatRowLevelPermissionPredicate } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate.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';
@@ -36,6 +37,7 @@ export class RowLevelPermissionPredicateService {
constructor(
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly workspaceCacheService: WorkspaceCacheService,
) {}
async createOne({
@@ -607,6 +609,10 @@ export class RowLevelPermissionPredicateService {
'Validation errors occurred while upserting row level permission predicates',
);
}
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
'rolesPermissions',
]);
}
private async runMigration({
@@ -641,5 +647,10 @@ export class RowLevelPermissionPredicateService {
'Validation errors occurred while applying row level permission predicate mutation',
);
}
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
'rolesPermissions',
'flatRowLevelPermissionPredicateGroupMaps',
]);
}
}
@@ -1,16 +0,0 @@
/* @license Enterprise */
export type RelationPredicateValue = {
isCurrentWorkspaceMemberSelected?: boolean;
selectedRecordIds: string[];
};
export type RowLevelPermissionPredicateValue =
| string
| string[]
| boolean
| number
| RelationPredicateValue
| Record<string, unknown>
| null
| undefined;