[permissions] Adapt field permissions to connect + createMany (#13655)

In this PR we adapt field permission to two things

1. Connect: the recent insertion of the connect feature introduces the
possibility to have "connect" objects in typeORM's expressionMap's
valueSet, where we previously only had column names (if i followed
correctly). For instance for a person object that a N - 1 relationship
to company, person will have both companyId and company as possible
valueSet keys for the upsert. We need to reflect that in our
`getColumnNameToFieldMetadataIdMap` util that returns a map containing
every possible value we could encounter in valueSet. In an attempt to
tie this to the schema generation where this is introduced, I created
the shallow util extractGraphQLRelationFieldNames (probably ill-named -
im willing to update the name if @etiennejouan has a better idea?) to
remind us that these two are linked.

2. CreateMany: When calling query builders methods directly on custom
object (like we do in graphql-create-many-resolver), we need to be
careful to call them with a selection of readable fields. We had a
debate on whether we should compute this selection containing all
readable fields by default under the hood when no selected fields are
indicated. I am still not 100% convinced as I think it should remain the
caller's responsibility, but this case reminds us that it could easily
be forgotten by developers - although it is all the more the case as we
don't have seeds yet that help us realize that ([PR on the
way](https://github.com/twentyhq/twenty/pull/13646)).
This commit is contained in:
Marie
2025-08-06 10:31:52 +02:00
committed by GitHub
parent a804d65210
commit 9957057d1f
12 changed files with 114 additions and 60 deletions
@@ -0,0 +1,37 @@
import { RestrictedFields } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { getFieldMetadataIdToColumnNamesMap } from 'src/engine/twenty-orm/utils/get-field-metadata-id-to-column-names-map.util';
export const getAllSelectableFields = ({
restrictedFields,
objectMetadata,
}: {
restrictedFields: RestrictedFields;
objectMetadata: { objectMetadataMapItem: ObjectMetadataItemWithFieldMaps };
}) => {
const restrictedFieldsIds = Object.entries(restrictedFields)
.filter(([_, value]) => value.canRead === false)
.map(([key]) => key);
const fieldMetadataIdToColumnNamesMap = getFieldMetadataIdToColumnNamesMap(
objectMetadata.objectMetadataMapItem,
);
const restrictedFieldsColumnNames: string[] = restrictedFieldsIds
.map((fieldId) => fieldMetadataIdToColumnNamesMap.get(fieldId))
.filter(isDefined)
.flat();
const allColumnNames = [...fieldMetadataIdToColumnNamesMap.values()].flat();
const restrictedFieldsColumnNamesSet = new Set(restrictedFieldsColumnNames);
return Object.fromEntries(
allColumnNames.map((columnName) => [
columnName,
!restrictedFieldsColumnNamesSet.has(columnName),
]),
);
};