fix(rls): prefill RLS predicate fields when creating related records (#22620)
## What / Why Creating a record from a relation section (e.g. adding a child record from its parent's record page) fails with **"Record does not satisfy security constraints"** for any role restricted by row-level permissions. Root cause: `useAddNewRecordAndOpenSidePanel` builds the create payload with only the label field and the parent FK. Fields required by the role's RLS predicates (e.g. `owner = current workspace member`) are missing, so the server rejects the insert in `validateRLSPredicatesForRecords` with `RLS_VALIDATION_FAILED`. `useCreateNewIndexRecord` (the record table "+ New" path) already handles this via `buildRecordInputFromRLSPredicates()`. The relation-section creation path was simply never updated — same bug class, different entry point. ## How Spread `buildRecordInputFromRLSPredicates()` into the create payload in `useAddNewRecordAndOpenSidePanel`, mirroring `useCreateNewIndexRecord`. The record is then created with the RLS-required fields prefilled (e.g. owner = current member), so it passes server-side validation. No behavior change for roles without RLS predicates: `buildRecordInputFromRLSPredicates()` returns an empty object when there are none. ## Test plan Requires row-level permissions (Enterprise) enabled. 1. Create a role with an RLS predicate `owner IS current workspace member`. 2. Assign it to a non-admin user; create a parent record owned by that user. 3. As that user, open the parent record and add a child record from a relation section (the "+" on a one-to-many / many-to-one relation field). 4. **Before:** "Record does not satisfy security constraints". **After:** the child record is created, with owner prefilled to the current member. Also verified via REST against a self-hosted instance: inserting the child record without the owner field is rejected (HTTP 400, RLS_VALIDATION_FAILED); inserting it with `ownerId = current member` succeeds (HTTP 201). <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22620?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+14
-5
@@ -5,6 +5,7 @@ import { useOpenRecordInSidePanel } from '@/side-panel/hooks/useOpenRecordInSide
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { useBuildRecordInputFromRLSPredicates } from '@/object-record/hooks/useBuildRecordInputFromRLSPredicates';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||
import { canCreateRecordsForObjectMetadataItem } from '@/object-record/utils/canCreateRecordsForObjectMetadataItem';
|
||||
@@ -49,6 +50,11 @@ export const useAddNewRecordAndOpenSidePanel = ({
|
||||
|
||||
const { updateOneRecord } = useUpdateOneRecord();
|
||||
|
||||
const { buildRecordInputFromRLSPredicates } =
|
||||
useBuildRecordInputFromRLSPredicates({
|
||||
objectMetadataItem: relationObjectMetadataItem,
|
||||
});
|
||||
|
||||
const { openRecordInSidePanel } = useOpenRecordInSidePanel();
|
||||
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
@@ -75,11 +81,14 @@ export const useAddNewRecordAndOpenSidePanel = ({
|
||||
createNewRecordAndOpenSidePanel: async (searchInput?: string) => {
|
||||
const newRecordId = v4();
|
||||
|
||||
const createRecordPayload = buildRecordLabelPayload({
|
||||
id: newRecordId,
|
||||
searchInput,
|
||||
objectMetadataItem: relationObjectMetadataItem,
|
||||
});
|
||||
const createRecordPayload = {
|
||||
...buildRecordInputFromRLSPredicates(),
|
||||
...buildRecordLabelPayload({
|
||||
id: newRecordId,
|
||||
searchInput,
|
||||
objectMetadataItem: relationObjectMetadataItem,
|
||||
}),
|
||||
};
|
||||
|
||||
if (relationFieldMetadataItemRelationType === RelationType.MANY_TO_ONE) {
|
||||
const gqlField =
|
||||
|
||||
Reference in New Issue
Block a user