From a3f468ef98a83a193ee783addc6dbbeb9bd84a94 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Sun, 29 Mar 2026 12:26:08 +0200 Subject: [PATCH] chore: remove IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED and IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED feature flags (#19082) ## Summary - Removes `IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED` feature flag, making row-level permission predicates always enabled. Removes early-return guards from query builders (select, update, insert) and the shared utility, the public feature flag metadata entry, and `updateFeatureFlag` calls from integration tests. - Removes `IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED` feature flag, making whole-day datetime filtering always enabled. Simplifies filter input components and hooks to always use date-only format for `IS` operand on `DATE_TIME` fields. - Cleans up enum definitions, seed data, generated schema files, and test mocks for both flags. --- .../src/metadata/generated/schema.graphql | 2 -- .../src/metadata/generated/schema.ts | 4 +--- .../src/generated-metadata/graphql.ts | 2 -- .../AdvancedFilterSidePanelValueFormInput.tsx | 6 ------ .../ObjectFilterDropdownFilterInput.tsx | 11 +---------- .../useApplyObjectFilterDropdownOperand.ts | 18 ++---------------- .../hooks/useGetInitialFilterValue.ts | 10 +--------- ...gsRolePermissionsObjectLevelObjectForm.tsx | 19 +++++-------------- .../constants/public-feature-flag.const.ts | 9 --------- .../workspace-entity-manager.spec.ts | 3 --- .../workspace-insert-query-builder.ts | 10 +--------- .../workspace-select-query-builder.ts | 10 +--------- .../workspace-update-query-builder.ts | 18 +----------------- ...ly-row-level-permission-predicates.util.ts | 9 --------- .../core/utils/seed-feature-flags.util.ts | 10 ---------- ...up-by-with-records-rls.integration-spec.ts | 18 +----------------- ...ssion-predicate-upsert.integration-spec.ts | 14 -------------- ...ssion-predicate-upsert.integration-spec.ts | 14 -------------- .../twenty-shared/src/types/FeatureFlagKey.ts | 2 -- 19 files changed, 14 insertions(+), 175 deletions(-) diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index f72273f77f..75a6949144 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -1729,11 +1729,9 @@ enum FeatureFlagKey { IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED IS_PUBLIC_DOMAIN_ENABLED IS_EMAILING_DOMAIN_ENABLED - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED IS_JUNCTION_RELATIONS_ENABLED IS_COMMAND_MENU_ITEM_ENABLED IS_NAVIGATION_MENU_ITEM_ENABLED - IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED IS_DRAFT_EMAIL_ENABLED IS_USAGE_ANALYTICS_ENABLED diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index fc613776ac..d278d95299 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -1427,7 +1427,7 @@ export interface PublicFeatureFlag { __typename: 'PublicFeatureFlag' } -export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_ENABLED' | 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED' +export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_ENABLED' | 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED' export interface ClientConfig { appVersion?: Scalars['String'] @@ -9145,11 +9145,9 @@ export const enumFeatureFlagKey = { IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED: 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' as const, IS_PUBLIC_DOMAIN_ENABLED: 'IS_PUBLIC_DOMAIN_ENABLED' as const, IS_EMAILING_DOMAIN_ENABLED: 'IS_EMAILING_DOMAIN_ENABLED' as const, - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED' as const, IS_JUNCTION_RELATIONS_ENABLED: 'IS_JUNCTION_RELATIONS_ENABLED' as const, IS_COMMAND_MENU_ITEM_ENABLED: 'IS_COMMAND_MENU_ITEM_ENABLED' as const, IS_NAVIGATION_MENU_ITEM_ENABLED: 'IS_NAVIGATION_MENU_ITEM_ENABLED' as const, - IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED: 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED' as const, IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED: 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED' as const, IS_DRAFT_EMAIL_ENABLED: 'IS_DRAFT_EMAIL_ENABLED' as const, IS_USAGE_ANALYTICS_ENABLED: 'IS_USAGE_ANALYTICS_ENABLED' as const, diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index c85d713329..8a7f8c192e 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1705,7 +1705,6 @@ export enum FeatureFlagKey { IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED', IS_CONNECTED_ACCOUNT_MIGRATED = 'IS_CONNECTED_ACCOUNT_MIGRATED', IS_DATASOURCE_MIGRATED = 'IS_DATASOURCE_MIGRATED', - IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED = 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED', IS_DIRECT_GRAPHQL_EXECUTION_ENABLED = 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED', IS_DRAFT_EMAIL_ENABLED = 'IS_DRAFT_EMAIL_ENABLED', IS_EMAILING_DOMAIN_ENABLED = 'IS_EMAILING_DOMAIN_ENABLED', @@ -1720,7 +1719,6 @@ export enum FeatureFlagKey { IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED = 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED', IS_RECORD_TABLE_WIDGET_ENABLED = 'IS_RECORD_TABLE_WIDGET_ENABLED', IS_RICH_TEXT_V1_MIGRATED = 'IS_RICH_TEXT_V1_MIGRATED', - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED', IS_UNIQUE_INDEXES_ENABLED = 'IS_UNIQUE_INDEXES_ENABLED', IS_USAGE_ANALYTICS_ENABLED = 'IS_USAGE_ANALYTICS_ENABLED' } diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/side-panel/components/AdvancedFilterSidePanelValueFormInput.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/side-panel/components/AdvancedFilterSidePanelValueFormInput.tsx index fd96611817..c86d1feb58 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/side-panel/components/AdvancedFilterSidePanelValueFormInput.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/side-panel/components/AdvancedFilterSidePanelValueFormInput.tsx @@ -23,7 +23,6 @@ import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue'; import { stringifyRelativeDateFilter } from '@/views/view-filter-value/utils/stringifyRelativeDateFilter'; import { WORKFLOW_TIMEZONE } from '@/workflow/constants/WorkflowTimeZone'; -import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap'; import { isObject, isString } from '@sniptt/guards'; import { useContext } from 'react'; import { FieldMetadataType } from 'twenty-shared/types'; @@ -69,10 +68,6 @@ export const AdvancedFilterSidePanelValueFormInput = ({ const { applyObjectFilterDropdownFilterValue } = useApplyObjectFilterDropdownFilterValue(); - const featureFlags = useFeatureFlagsMap(); - const isWholeDayFilterEnabled = - featureFlags.IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED ?? false; - const handleChange = (newValue: JsonValue) => { if (isString(newValue)) { applyObjectFilterDropdownFilterValue(newValue); @@ -196,7 +191,6 @@ export const AdvancedFilterSidePanelValueFormInput = ({ const field = { type: - isWholeDayFilterEnabled === true && recordFilter.type === FieldMetadataType.DATE_TIME && recordFilter.operand === RecordFilterOperand.IS ? FieldMetadataType.DATE diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx index e79598ee31..8045e3bcfb 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx @@ -5,8 +5,6 @@ import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-d import { ObjectFilterDropdownRecordSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect'; import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; -import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap'; - import { ViewFilterOperand } from 'twenty-shared/types'; import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect'; @@ -30,10 +28,6 @@ export const ObjectFilterDropdownFilterInput = ({ filterDropdownId, recordFilterId, }: ObjectFilterDropdownFilterInputProps) => { - const featureFlags = useFeatureFlagsMap(); - const isWholeDayFilterEnabled = - featureFlags.IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED ?? false; - const fieldMetadataItemUsedInDropdown = useAtomComponentSelectorValue( fieldMetadataItemUsedInDropdownComponentSelector, ); @@ -82,10 +76,7 @@ export const ObjectFilterDropdownFilterInput = ({ ); } else if (filterType === 'DATE_TIME') { - if ( - isWholeDayFilterEnabled && - selectedOperandInDropdown === ViewFilterOperand.IS - ) { + if (selectedOperandInDropdown === ViewFilterOperand.IS) { return ( <> diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts index 3304402ed5..2bdd77d589 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts @@ -15,7 +15,6 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState'; import { stringifyRelativeDateFilter } from '@/views/view-filter-value/utils/stringifyRelativeDateFilter'; -import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap'; import { DEFAULT_RELATIVE_DATE_FILTER_VALUE } from 'twenty-shared/constants'; import { isDefined, @@ -49,10 +48,6 @@ export const useApplyObjectFilterDropdownOperand = () => { const { getRelativeDateFilterWithUserTimezone } = useGetRelativeDateFilterWithUserTimezone(); - const featureFlags = useFeatureFlagsMap(); - const isWholeDayFilterEnabled = - featureFlags.IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED ?? false; - const applyObjectFilterDropdownOperand = ( newOperand: RecordFilterOperand, ) => { @@ -127,7 +122,6 @@ export const useApplyObjectFilterDropdownOperand = () => { recordFilterToUpsert.value, newOperand, userTimezone, - isWholeDayFilterEnabled, ); } else if (filterValueIsEmpty || isStillRelativeFilterValue.success) { const zonedDateToUse = Temporal.Now.zonedDateTimeISO(userTimezone); @@ -139,10 +133,7 @@ export const useApplyObjectFilterDropdownOperand = () => { recordFilterToUpsert.value = initialNowDateFilterValue; } else { - if ( - newOperand === RecordFilterOperand.IS && - isWholeDayFilterEnabled - ) { + if (newOperand === RecordFilterOperand.IS) { recordFilterToUpsert.value = zonedDateToUse .toPlainDate() .toString(); @@ -172,7 +163,6 @@ const convertDateTimeFilterValue = ( currentValue: string, targetOperand: RecordFilterOperand, userTimezone: string, - isWholeDayFilterEnabled = false, ): string => { const zonedDateToUse = Temporal.Now.zonedDateTimeISO(userTimezone); @@ -182,11 +172,7 @@ const convertDateTimeFilterValue = ( ? Temporal.Instant.from(currentValue).toZonedDateTimeISO(userTimezone) : Temporal.PlainDate.from(currentValue).toZonedDateTime(userTimezone); - if (isWholeDayFilterEnabled) { - return existingZoned.toPlainDate().toString(); - } else { - return existingZoned.toInstant().toString(); - } + return existingZoned.toPlainDate().toString(); } catch { return zonedDateToUse.toPlainDate().toString(); } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useGetInitialFilterValue.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useGetInitialFilterValue.ts index d3d6e164fe..228dfcd21f 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useGetInitialFilterValue.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useGetInitialFilterValue.ts @@ -5,8 +5,6 @@ import { useGetDateTimeFilterDisplayValue } from '@/object-record/object-filter- import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand'; import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone'; -import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap'; - import { type FilterableAndTSVectorFieldType } from 'twenty-shared/types'; const activeDatePickerOperands = [ @@ -19,9 +17,6 @@ export const useGetInitialFilterValue = () => { const { userTimezone } = useUserTimezone(); const { getDateFilterDisplayValue } = useGetDateFilterDisplayValue(); const { getDateTimeFilterDisplayValue } = useGetDateTimeFilterDisplayValue(); - const featureFlags = useFeatureFlagsMap(); - const isWholeDayFilterEnabled = - featureFlags.IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED ?? false; const getInitialFilterValue = ( newType: FilterableAndTSVectorFieldType, @@ -50,10 +45,7 @@ export const useGetInitialFilterValue = () => { alreadyExistingZonedDateTime ?? Temporal.Now.zonedDateTimeISO(userTimezone); - if ( - isWholeDayFilterEnabled === true && - newOperand === RecordFilterOperand.IS - ) { + if (newOperand === RecordFilterOperand.IS) { const value = referenceDate.toPlainDate().toString(); const { displayValue } = getDateFilterDisplayValue(referenceDate); 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 c2bd1a708f..37080993f2 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 @@ -8,7 +8,6 @@ import { SettingsRolePermissionsObjectLevelRecordLevelSection } from '@/settings import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue'; -import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap'; import { t } from '@lingui/core/macro'; import { useSearchParams } from 'react-router-dom'; import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; @@ -23,7 +22,6 @@ import { useQuery } from '@apollo/client/react'; import { type BillingEntitlement, BillingEntitlementKey, - FeatureFlagKey, FindOneAgentDocument, } from '~/generated-metadata/graphql'; @@ -55,8 +53,6 @@ export const SettingsRolePermissionsObjectLevelObjectForm = ({ objectId: objectMetadataId, }); - const featureFlagsMap = useFeatureFlagsMap(); - const workspaceBillingEntitlements = currentWorkspace?.billingEntitlements; const isRLSBillingEntitlementEnabled = @@ -66,9 +62,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 +157,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 c4a65dac15..15855ae52d 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', - }, - }, ...(process.env.CLOUDFLARE_API_KEY ? [ // { 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 a62b305604..65cb39c0d2 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 @@ -237,11 +237,9 @@ describe('WorkspaceEntityManager', () => { IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED: false, IS_PUBLIC_DOMAIN_ENABLED: false, IS_EMAILING_DOMAIN_ENABLED: false, - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false, IS_JUNCTION_RELATIONS_ENABLED: false, IS_COMMAND_MENU_ITEM_ENABLED: false, IS_NAVIGATION_MENU_ITEM_ENABLED: false, - IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED: false, IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED: false, IS_DRAFT_EMAIL_ENABLED: false, IS_USAGE_ANALYTICS_ENABLED: false, @@ -274,7 +272,6 @@ describe('WorkspaceEntityManager', () => { IS_AI_ENABLED: false, IS_PUBLIC_DOMAIN_ENABLED: false, IS_EMAILING_DOMAIN_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 0106172965..f54369f585 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 @@ -1,4 +1,4 @@ -import { FeatureFlagKey, type ObjectsPermissions } from 'twenty-shared/types'; +import { type ObjectsPermissions } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { type EntityTarget, @@ -317,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 93a41aaa1f..7cca65361e 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,4 +1,4 @@ -import { FeatureFlagKey, type ObjectsPermissions } from 'twenty-shared/types'; +import { type ObjectsPermissions } from 'twenty-shared/types'; import { type EntityTarget, type ObjectLiteral, @@ -357,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 46306a9119..fb49df1e85 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 @@ -1,6 +1,6 @@ import { msg } from '@lingui/core/macro'; import { QUERY_MAX_RECORDS } from 'twenty-shared/constants'; -import { FeatureFlagKey, type ObjectsPermissions } from 'twenty-shared/types'; +import { type ObjectsPermissions } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { UpdateQueryBuilder, @@ -615,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; } @@ -648,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 48e4ad80e3..9053431d12 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 @@ -1,6 +1,5 @@ /* @license Enterprise */ -import { FeatureFlagKey } from 'twenty-shared/types'; import { Brackets, NotBrackets, @@ -33,14 +32,6 @@ export const applyRowLevelPermissionPredicates = ({ authContext, featureFlagMap, }: ApplyRowLevelPermissionPredicatesArgs): void => { - if ( - featureFlagMap[ - FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED - ] !== true - ) { - return; - } - const userWorkspaceId = isUserAuthContext(authContext) ? 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 0c46b56465..54ba630135 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 @@ -40,11 +40,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, @@ -70,11 +65,6 @@ export const seedFeatureFlags = async ({ workspaceId: workspaceId, value: true, }, - { - key: FeatureFlagKey.IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED, - workspaceId: workspaceId, - value: true, - }, { key: FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED, workspaceId: workspaceId, diff --git a/packages/twenty-server/test/integration/graphql/suites/group-by-with-records-rls.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/group-by-with-records-rls.integration-spec.ts index b83165a31f..bf777d522a 100644 --- a/packages/twenty-server/test/integration/graphql/suites/group-by-with-records-rls.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/group-by-with-records-rls.integration-spec.ts @@ -11,12 +11,8 @@ import { deleteOneRole } from 'test/integration/metadata/suites/role/utils/delet import { findOneRoleByLabel } from 'test/integration/metadata/suites/role/utils/find-one-role-by-label.util'; import { updateWorkspaceMemberRole } from 'test/integration/metadata/suites/role/utils/update-workspace-member-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 { - FeatureFlagKey, - RowLevelPermissionPredicateOperand, -} from 'twenty-shared/types'; +import { RowLevelPermissionPredicateOperand } from 'twenty-shared/types'; import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant'; @@ -36,12 +32,6 @@ describe('group-by with records respects row-level permission predicates', () => 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: { @@ -175,12 +165,6 @@ describe('group-by with records respects row-level permission predicates', () => input: { idToDelete: customRoleId }, }); } - - await updateFeatureFlag({ - featureFlag: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED, - value: false, - expectToFail: false, - }); }); it('filters records in group-by results based on RLS predicates', async () => { 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 4c062db244..20b2e70485 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, @@ -12,7 +11,6 @@ import { import { RowLevelPermissionPredicateGroupLogicalOperator, RowLevelPermissionPredicateOperand, - FeatureFlagKey, } from 'twenty-shared/types'; import { v4 } from 'uuid'; @@ -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 7bb7502794..b5c6fcc1f1 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,12 +2,10 @@ 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, - FeatureFlagKey, } from 'twenty-shared/types'; import { v4 } from 'uuid'; @@ -19,12 +17,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: { @@ -81,12 +73,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, diff --git a/packages/twenty-shared/src/types/FeatureFlagKey.ts b/packages/twenty-shared/src/types/FeatureFlagKey.ts index 6437e154ff..57a716d172 100644 --- a/packages/twenty-shared/src/types/FeatureFlagKey.ts +++ b/packages/twenty-shared/src/types/FeatureFlagKey.ts @@ -6,11 +6,9 @@ export enum FeatureFlagKey { IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED', IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED', IS_EMAILING_DOMAIN_ENABLED = 'IS_EMAILING_DOMAIN_ENABLED', - IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED', IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED', IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED', IS_NAVIGATION_MENU_ITEM_ENABLED = 'IS_NAVIGATION_MENU_ITEM_ENABLED', - IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED = 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED', IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED = 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED', IS_DRAFT_EMAIL_ENABLED = 'IS_DRAFT_EMAIL_ENABLED', IS_USAGE_ANALYTICS_ENABLED = 'IS_USAGE_ANALYTICS_ENABLED',