From c01853c349627f6524052d7e15b05553a69ba3f9 Mon Sep 17 00:00:00 2001 From: Weiko Date: Mon, 9 Feb 2026 16:52:12 +0100 Subject: [PATCH] Releasing RLS --- .../src/generated-metadata/graphql.ts | 1 - .../twenty-front/src/generated/graphql.ts | 1 - ...gsRolePermissionsObjectLevelObjectForm.tsx | 18 +++++---------- .../constants/public-feature-flag.const.ts | 9 -------- .../enums/feature-flag-key.enum.ts | 1 - .../workspace-entity-manager.spec.ts | 2 -- .../workspace-insert-query-builder.ts | 9 -------- .../workspace-select-query-builder.ts | 23 ++++++------------- .../workspace-update-query-builder.ts | 17 -------------- ...ly-row-level-permission-predicates.util.ts | 10 -------- .../core/utils/seed-feature-flags.util.ts | 5 ---- ...ssion-predicate-upsert.integration-spec.ts | 14 ----------- ...ssion-predicate-upsert.integration-spec.ts | 14 ----------- 13 files changed, 13 insertions(+), 111 deletions(-) diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 1901f460762..19e95e9607c 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1501,7 +1501,6 @@ export enum FeatureFlagKey { IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED', IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED', IS_RECORD_PAGE_LAYOUT_ENABLED = 'IS_RECORD_PAGE_LAYOUT_ENABLED', - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED', IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED', IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED', IS_TIMELINE_ACTIVITY_MIGRATED = 'IS_TIMELINE_ACTIVITY_MIGRATED', diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index c319fac5475..e95f7527b95 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -1473,7 +1473,6 @@ export enum FeatureFlagKey { IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED', IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED', IS_RECORD_PAGE_LAYOUT_ENABLED = 'IS_RECORD_PAGE_LAYOUT_ENABLED', - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED', IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED', IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED', IS_TIMELINE_ACTIVITY_MIGRATED = 'IS_TIMELINE_ACTIVITY_MIGRATED', diff --git a/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/SettingsRolePermissionsObjectLevelObjectForm.tsx b/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/SettingsRolePermissionsObjectLevelObjectForm.tsx index 360dbd01a65..87bc4f2744c 100644 --- a/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/SettingsRolePermissionsObjectLevelObjectForm.tsx +++ b/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/object-form/components/SettingsRolePermissionsObjectLevelObjectForm.tsx @@ -17,8 +17,7 @@ import { Button } from 'twenty-ui/input'; import { type BillingEntitlement, BillingEntitlementKey, - FeatureFlagKey, - useFindOneAgentQuery, + useFindOneAgentQuery } from '~/generated-metadata/graphql'; type SettingsRolePermissionsObjectLevelObjectFormProps = { @@ -59,9 +58,6 @@ export const SettingsRolePermissionsObjectLevelObjectForm = ({ entitlement.value === true, ) ?? false; - const isRowLevelPermissionPredicatesEnabled = - featureFlagsMap[FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED]; - const objectMetadataItem = objectMetadata.objectMetadataItem; const objectLabelSingular = objectMetadataItem.labelSingular; @@ -164,13 +160,11 @@ export const SettingsRolePermissionsObjectLevelObjectForm = ({ objectMetadataItem={objectMetadataItem} roleId={roleId} /> - {isRowLevelPermissionPredicatesEnabled && ( - - )} + ); diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/constants/public-feature-flag.const.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/constants/public-feature-flag.const.ts index a92a7143ff0..6f19c91f136 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/constants/public-feature-flag.const.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/constants/public-feature-flag.const.ts @@ -20,15 +20,6 @@ export const PUBLIC_FEATURE_FLAGS: PublicFeatureFlag[] = [ 'Enable many-to-many relations through junction tables configuration', }, }, - { - key: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - metadata: { - label: 'Row Level Permissions', - description: 'Enable row level permission', - imagePath: - 'https://twenty.com/images/lab/is-row-level-permission-predicates-enabled.png', - }, - }, { key: FeatureFlagKey.IS_SSE_DB_EVENTS_ENABLED, metadata: { diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts index 7f05938ef51..cb11410b3b0 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts @@ -15,7 +15,6 @@ export enum FeatureFlagKey { IS_NOTE_TARGET_MIGRATED = 'IS_NOTE_TARGET_MIGRATED', IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED', IS_FILES_FIELD_MIGRATED = 'IS_FILES_FIELD_MIGRATED', - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED', IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED', IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED', IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED', diff --git a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts index fcc22ca82f8..37ef204bf8f 100644 --- a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts +++ b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts @@ -235,7 +235,6 @@ describe('WorkspaceEntityManager', () => { IS_TASK_TARGET_MIGRATED: false, IS_TIMELINE_ACTIVITY_MIGRATED: false, IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED: false, - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false, IS_JUNCTION_RELATIONS_ENABLED: false, IS_SSE_DB_EVENTS_ENABLED: false, IS_COMMAND_MENU_ITEM_ENABLED: false, @@ -269,7 +268,6 @@ describe('WorkspaceEntityManager', () => { IS_PUBLIC_DOMAIN_ENABLED: false, IS_EMAILING_DOMAIN_ENABLED: false, IS_DASHBOARD_V2_ENABLED: false, - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false, }, permissionsPerRoleId: {}, eventEmitterService: mockInternalContext.eventEmitterService, diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts index 08e7e67aa01..cdb78a30a87 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-insert-query-builder.ts @@ -12,7 +12,6 @@ import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/ import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { type QueryDeepPartialEntityWithNestedRelationFields } from 'src/engine/twenty-orm/entity-manager/types/query-deep-partial-entity-with-nested-relation-fields.type'; import { type RelationConnectQueryConfig } from 'src/engine/twenty-orm/entity-manager/types/relation-connect-query-config.type'; import { type RelationDisconnectQueryFieldsByEntityIndex } from 'src/engine/twenty-orm/entity-manager/types/relation-nested-query-fields-by-entity-index.type'; @@ -318,14 +317,6 @@ export class WorkspaceInsertQueryBuilder< } private validateRLSPredicatesForInsert(): void { - if ( - this.featureFlagMap[ - FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED - ] !== true - ) { - return; - } - const mainAliasTarget = this.getMainAliasTarget(); const objectMetadata = getObjectMetadataFromEntityTarget( mainAliasTarget, diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-select-query-builder.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-select-query-builder.ts index fc2fa206fee..6c7b851c7d2 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-select-query-builder.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-select-query-builder.ts @@ -1,8 +1,8 @@ import { type ObjectsPermissions } from 'twenty-shared/types'; import { - type EntityTarget, - type ObjectLiteral, - SelectQueryBuilder, + type EntityTarget, + type ObjectLiteral, + SelectQueryBuilder, } from 'typeorm'; import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'; @@ -10,15 +10,14 @@ import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interf import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface'; import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { - PermissionsException, - PermissionsExceptionCode, + PermissionsException, + PermissionsExceptionCode, } from 'src/engine/metadata-modules/permissions/permissions.exception'; import { computeTwentyORMException } from 'src/engine/twenty-orm/error-handling/compute-twenty-orm-exception'; import { - TwentyORMException, - TwentyORMExceptionCode, + TwentyORMException, + TwentyORMExceptionCode, } from 'src/engine/twenty-orm/exceptions/twenty-orm.exception'; import { validateQueryIsPermittedOrThrow } from 'src/engine/twenty-orm/repository/permissions.utils'; import { WorkspaceDeleteQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-delete-query-builder'; @@ -358,14 +357,6 @@ export class WorkspaceSelectQueryBuilder< } private applyRowLevelPermissionPredicates(): void { - if ( - this.featureFlagMap[ - FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED - ] !== true - ) { - return; - } - if (this.shouldBypassPermissionChecks) { return; } diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-update-query-builder.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-update-query-builder.ts index 3d6a9ae0124..cb3c4d1d80e 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace-update-query-builder.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace-update-query-builder.ts @@ -16,7 +16,6 @@ import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/ import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { type QueryDeepPartialEntityWithNestedRelationFields } from 'src/engine/twenty-orm/entity-manager/types/query-deep-partial-entity-with-nested-relation-fields.type'; import { type RelationConnectQueryConfig } from 'src/engine/twenty-orm/entity-manager/types/relation-connect-query-config.type'; import { type RelationDisconnectQueryFieldsByEntityIndex } from 'src/engine/twenty-orm/entity-manager/types/relation-nested-query-fields-by-entity-index.type'; @@ -616,14 +615,6 @@ export class WorkspaceUpdateQueryBuilder< } private applyRowLevelPermissionPredicates(): void { - if ( - this.featureFlagMap[ - FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED - ] !== true - ) { - return; - } - if (this.shouldBypassPermissionChecks) { return; } @@ -649,14 +640,6 @@ export class WorkspaceUpdateQueryBuilder< }: { updatedRecords: T[]; }): void { - if ( - this.featureFlagMap[ - FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED - ] !== true - ) { - return; - } - const mainAliasTarget = this.getMainAliasTarget(); const objectMetadata = getObjectMetadataFromEntityTarget( mainAliasTarget, diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util.ts index b8251f97349..1ff3370f576 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/apply-row-level-permission-predicates.util.ts @@ -12,7 +12,6 @@ import { type WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/ import { GraphqlQueryFilterFieldParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query-filter/graphql-query-filter-field.parser'; import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { type WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder'; import { buildRowLevelPermissionRecordFilter } from 'src/engine/twenty-orm/utils/build-row-level-permission-record-filter.util'; @@ -30,16 +29,7 @@ export const applyRowLevelPermissionPredicates = ({ objectMetadata, internalContext, authContext, - featureFlagMap, }: ApplyRowLevelPermissionPredicatesArgs): void => { - if ( - featureFlagMap[ - FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED - ] !== true - ) { - return; - } - const roleId = authContext.userWorkspaceId ? internalContext.userWorkspaceRoleMap[authContext.userWorkspaceId] : undefined; diff --git a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util.ts b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util.ts index 32085bc033e..5495ff5f131 100644 --- a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util.ts @@ -76,11 +76,6 @@ export const seedFeatureFlags = async ({ workspaceId: workspaceId, value: true, }, - { - key: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - workspaceId: workspaceId, - value: true, - }, { key: FeatureFlagKey.IS_JUNCTION_RELATIONS_ENABLED, workspaceId: workspaceId, diff --git a/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/failing-row-level-permission-predicate-upsert.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/failing-row-level-permission-predicate-upsert.integration-spec.ts index accb8cc0499..20b2e704853 100644 --- a/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/failing-row-level-permission-predicate-upsert.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/failing-row-level-permission-predicate-upsert.integration-spec.ts @@ -3,7 +3,6 @@ import { findManyObjectMetadata } from 'test/integration/metadata/suites/object- import { createOneRole } from 'test/integration/metadata/suites/role/utils/create-one-role.util'; import { deleteOneRole } from 'test/integration/metadata/suites/role/utils/delete-one-role.util'; import { upsertRowLevelPermissionPredicates } from 'test/integration/metadata/suites/row-level-permission-predicate/utils/upsert-row-level-permission-predicates.util'; -import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util'; import { jestExpectToBeDefined } from 'test/utils/jest-expect-to-be-defined.util.test'; import { eachTestingContextFilter, @@ -15,7 +14,6 @@ import { } from 'twenty-shared/types'; import { v4 } from 'uuid'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { type UpsertRowLevelPermissionPredicatesInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/upsert-row-level-permission-predicates.input'; type TestSetup = { @@ -163,12 +161,6 @@ describe('Row Level Permission Predicate upsert should fail', () => { let companyNameFieldMetadataId: string; beforeAll(async () => { - await updateFeatureFlag({ - featureFlag: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - value: true, - expectToFail: false, - }); - const { objects } = await findManyObjectMetadata({ expectToFail: false, input: { @@ -225,12 +217,6 @@ describe('Row Level Permission Predicate upsert should fail', () => { }); afterAll(async () => { - await updateFeatureFlag({ - featureFlag: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - value: false, - expectToFail: false, - }); - if (createdRoleId) { await deleteOneRole({ expectToFail: false, diff --git a/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/successful-row-level-permission-predicate-upsert.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/successful-row-level-permission-predicate-upsert.integration-spec.ts index 237e42176e3..a4735d90506 100644 --- a/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/successful-row-level-permission-predicate-upsert.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/row-level-permission-predicate/successful-row-level-permission-predicate-upsert.integration-spec.ts @@ -2,14 +2,12 @@ import { findManyObjectMetadata } from 'test/integration/metadata/suites/object- import { createOneRole } from 'test/integration/metadata/suites/role/utils/create-one-role.util'; import { deleteOneRole } from 'test/integration/metadata/suites/role/utils/delete-one-role.util'; import { upsertRowLevelPermissionPredicates } from 'test/integration/metadata/suites/row-level-permission-predicate/utils/upsert-row-level-permission-predicates.util'; -import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util'; import { jestExpectToBeDefined } from 'test/utils/jest-expect-to-be-defined.util.test'; import { RowLevelPermissionPredicateGroupLogicalOperator, RowLevelPermissionPredicateOperand, } from 'twenty-shared/types'; -import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { type UpsertRowLevelPermissionPredicatesInput } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/inputs/upsert-row-level-permission-predicates.input'; describe('Row Level Permission Predicate upsert should succeed', () => { @@ -18,12 +16,6 @@ describe('Row Level Permission Predicate upsert should succeed', () => { let createdRoleId: string; beforeAll(async () => { - await updateFeatureFlag({ - featureFlag: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - value: true, - expectToFail: false, - }); - const { objects } = await findManyObjectMetadata({ expectToFail: false, input: { @@ -80,12 +72,6 @@ describe('Row Level Permission Predicate upsert should succeed', () => { }); afterAll(async () => { - await updateFeatureFlag({ - featureFlag: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - value: false, - expectToFail: false, - }); - if (createdRoleId) { await deleteOneRole({ expectToFail: false,