From de51e653fc92079e02ee6227d5964c2eeb232ebf Mon Sep 17 00:00:00 2001 From: martmull Date: Tue, 9 Jul 2024 14:55:05 +0200 Subject: [PATCH] Authorize 0 depth (#6171) Authorize depth 0 ![image](https://github.com/twentyhq/twenty/assets/29927851/2e82eaba-01b4-440f-8412-d2878007a3b1) ![image](https://github.com/twentyhq/twenty/assets/29927851/f0137671-20dc-4e44-97b8-7a8e4c583493) ## Edit ### Depth = 0 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, ... ]} ``` ### Depth = 1 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" } }, "messageParticipants": [ { "id": "20202020-0f2a-49d8-8aa2-ec8786153a0b", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-2b8a-405d-8f42-e820ca921421", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7" }, { "id": "20202020-fc7d-4ad8-9aea-b78bcbf79cdd", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-04c8-4f24-93f2-764948e95014", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7" } ], "calendarEventParticipants": [ { "id": "da8f47c3-8055-49ad-b7e4-9c9d5bbc1ecc", "handle": "christoph.calisto@linkedin.com", "displayName": "Christoph Calisto", "isOrganizer": true, "responseStatus": "ACCEPTED", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "calendarEventId": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": null } ], "pointOfContactForOpportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" } } ] }, ... ]} ``` ### Depth = 2 ``` { "data": { "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "accountOwner": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" }, "activityTargets": [], "favorites": [], "attachments": [], "timelineActivities": [], "people": [ { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, { "id": "20202020-ac73-4797-824e-87a1f5aea9e0", "email": "sylvie.palmer@linkedin.com", "jobTitle": "", "phone": "+33780123456", "city": "Los Angeles", "avatarUrl": "", "position": 2, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Sylvie", "lastName": "Palmer" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } } ], "opportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" } } ] }, "pointOfContactForOpportunities": [ { "id": "20202020-be10-412b-a663-16bd3c2228e1", "name": "Opportunity 1", "closeDate": "2024-07-08T16:08:50.018Z", "probability": "0.5", "stage": "NEW", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "pointOfContactId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "amount": { "amountMicros": 100000, "currencyCode": "USD" }, "favorites": [], "activityTargets": [], "attachments": [], "timelineActivities": [], "pointOfContact": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "company": { "id": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": "Linkedin", "domainName": "linkedin.com", "address": "", "employees": null, "idealCustomerProfile": false, "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "accountOwnerId": null, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" }, "annualRecurringRevenue": { "amountMicros": null, "currencyCode": "" } } } ], "messageParticipants": [ { "id": "20202020-0f2a-49d8-8aa2-ec8786153a0b", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-2b8a-405d-8f42-e820ca921421", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7", "message": { "id": "20202020-2b8a-405d-8f42-e820ca921421", "headerMessageId": "99ef24a8-2b8a-405d-8f42-e820ca921421", "direction": "outgoing", "subject": "Meeting Request", "text": "Hello, \n I hope this email finds you well. I am writing to request a meeting. I believe it would be beneficial for both parties to collaborate and explore potential opportunities. Would you be available for a meeting sometime next week? Please let me know your availability, and I will arrange a suitable time. \n Looking forward to your response.\n Best regards", "receivedAt": "2024-07-08T16:08:50.022Z", "createdAt": "2024-07-08T16:08:50.022Z", "updatedAt": "2024-07-08T16:08:50.022Z", "messageThreadId": "20202020-8bfa-453b-b99b-bc435a7d4da8" }, "person": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "workspaceMember": { "id": "20202020-0687-4c41-b707-ed1bfca972a7", "colorScheme": "Light", "locale": "en", "avatarUrl": "", "userEmail": "tim@apple.dev", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "name": { "firstName": "Tim", "lastName": "Apple" } } }, { "id": "20202020-fc7d-4ad8-9aea-b78bcbf79cdd", "role": "from", "handle": "outgoing", "displayName": "Christoph", "createdAt": "2024-07-08T16:08:50.028Z", "updatedAt": "2024-07-08T16:08:50.028Z", "messageId": "20202020-04c8-4f24-93f2-764948e95014", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": "20202020-0687-4c41-b707-ed1bfca972a7", "message": { "id": "20202020-04c8-4f24-93f2-764948e95014", "headerMessageId": "8f804a9a-04c8-4f24-93f2-764948e95014", "direction": "outgoing", "subject": "Inquiry Regarding Topic", "text": "Good Morning,\n I am writing to inquire about information. Could you please provide me with details regarding this topic? \n Your assistance in this matter would be greatly appreciated. Thank you in advance for your prompt response. \n Best regards,Tim", "receivedAt": "2024-07-08T16:08:50.022Z", "createdAt": "2024-07-08T16:08:50.022Z", "updatedAt": "2024-07-08T16:08:50.022Z", "messageThreadId": "20202020-634a-4fde-aa7c-28a0eaf203ca" }, "person": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } }, "workspaceMember": { "id": "20202020-0687-4c41-b707-ed1bfca972a7", "colorScheme": "Light", "locale": "en", "avatarUrl": "", "userEmail": "tim@apple.dev", "userId": "20202020-9e3b-46d4-a556-88b9ddc2b034", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "name": { "firstName": "Tim", "lastName": "Apple" } } } ], "calendarEventParticipants": [ { "id": "da8f47c3-8055-49ad-b7e4-9c9d5bbc1ecc", "handle": "christoph.calisto@linkedin.com", "displayName": "Christoph Calisto", "isOrganizer": true, "responseStatus": "ACCEPTED", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "calendarEventId": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "personId": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "workspaceMemberId": null, "workspaceMember": null, "calendarEvent": { "id": "86083141-1c0e-494c-a1b6-85b1c6fefaa5", "title": "Meeting with Christoph", "isCanceled": false, "isFullDay": false, "startsAt": "2024-07-08T08:00:50.030Z", "endsAt": "2024-07-08T09:00:50.030Z", "externalCreatedAt": "2024-07-08T16:08:50.030Z", "externalUpdatedAt": "2024-07-08T16:08:50.030Z", "description": "Discuss project progress", "location": "Seattle", "iCalUID": "event1@calendar.com", "conferenceSolution": "Zoom", "recurringEventExternalId": "recurring1", "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "conferenceLink": { "label": "https://zoom.us/j/1234567890", "url": "https://zoom.us/j/1234567890" } }, "person": { "id": "20202020-1c0e-494c-a1b6-85b1c6fefaa5", "email": "christoph.calisto@linkedin.com", "jobTitle": "", "phone": "+33789012345", "city": "Seattle", "avatarUrl": "", "position": 1, "createdAt": "2024-07-08T16:08:50.011Z", "updatedAt": "2024-07-08T16:08:50.011Z", "companyId": "20202020-3ec3-4fe3-8997-b76aa0bfa408", "name": { "firstName": "Christoph", "lastName": "Callisto" }, "linkedinLink": { "label": "", "url": "" }, "xLink": { "label": "", "url": "" } } } ] }, ... ]} ``` --- .../api/__mocks__/object-metadata-item.mock.ts | 2 +- .../utils/__tests__/compute-depth.utils.spec.ts | 14 ++++++++------ .../query-builder/utils/compute-depth.utils.ts | 2 +- .../map-field-metadata-to-graphql-query.utils.ts | 6 +++--- .../utils/__tests__/parameters.utils.spec.ts | 2 +- .../open-api/utils/parameters.utils.ts | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts index 8767507e5..f4722d2ca 100644 --- a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts +++ b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts @@ -75,7 +75,7 @@ const fieldMultiSelectMock = { ], }; -const fieldRelationMock = { +export const fieldRelationMock = { name: 'fieldRelation', type: FieldMetadataType.RELATION, fromRelationMetadata: { diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/compute-depth.utils.spec.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/compute-depth.utils.spec.ts index cf68056a3..7a2f51f18 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/compute-depth.utils.spec.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/__tests__/compute-depth.utils.spec.ts @@ -1,12 +1,14 @@ import { computeDepth } from 'src/engine/api/rest/core/query-builder/utils/compute-depth.utils'; describe('computeDepth', () => { - it('should compute depth from query', () => { - const request: any = { - query: { depth: '1' }, - }; + [0, 1, 2].forEach((depth) => { + it('should compute depth from query', () => { + const request: any = { + query: { depth: `${depth}` }, + }; - expect(computeDepth(request)).toEqual(1); + expect(computeDepth(request)).toEqual(depth); + }); }); it('should return default depth if missing', () => { @@ -19,7 +21,7 @@ describe('computeDepth', () => { expect(() => computeDepth(request)).toThrow(); - request.query.depth = '0'; + request.query.depth = '-1'; expect(() => computeDepth(request)).toThrow(); }); diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/compute-depth.utils.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/compute-depth.utils.ts index 6fdee1b30..ecd5060cf 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/compute-depth.utils.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/compute-depth.utils.ts @@ -2,7 +2,7 @@ import { BadRequestException } from '@nestjs/common'; import { Request } from 'express'; -const ALLOWED_DEPTH_VALUES = [1, 2]; +const ALLOWED_DEPTH_VALUES = [0, 1, 2]; export const computeDepth = (request: Request): number | undefined => { if (!request.query.depth) { diff --git a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts index c7112e0df..7fc970082 100644 --- a/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts +++ b/packages/twenty-server/src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils.ts @@ -9,7 +9,7 @@ export const mapFieldMetadataToGraphqlQuery = ( field, maxDepthForRelations = DEFAULT_DEPTH_VALUE, ): string | undefined => { - if (maxDepthForRelations <= 0) { + if (maxDepthForRelations < 0) { return ''; } @@ -32,6 +32,7 @@ export const mapFieldMetadataToGraphqlQuery = ( if (fieldIsSimpleValue) { return field.name; } else if ( + maxDepthForRelations > 0 && fieldType === FieldMetadataType.RELATION && field.toRelationMetadata?.relationType === RelationMetadataType.ONE_TO_MANY ) { @@ -45,7 +46,6 @@ export const mapFieldMetadataToGraphqlQuery = ( { id ${(relationMetadataItem?.fields ?? []) - .filter((field) => field.type !== FieldMetadataType.RELATION) .map((field) => mapFieldMetadataToGraphqlQuery( objectMetadataItems, @@ -56,6 +56,7 @@ export const mapFieldMetadataToGraphqlQuery = ( .join('\n')} }`; } else if ( + maxDepthForRelations > 0 && fieldType === FieldMetadataType.RELATION && field.fromRelationMetadata?.relationType === RelationMetadataType.ONE_TO_MANY @@ -72,7 +73,6 @@ export const mapFieldMetadataToGraphqlQuery = ( node { id ${(relationMetadataItem?.fields ?? []) - .filter((field) => field.type !== FieldMetadataType.RELATION) .map((field) => mapFieldMetadataToGraphqlQuery( objectMetadataItems, diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts index fd1cf3dde..f91da6a75 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/parameters.utils.spec.ts @@ -68,7 +68,7 @@ describe('computeParameters', () => { required: false, schema: { type: 'integer', - enum: [1, 2], + enum: [0, 1, 2], }, }); }); diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts index de9644207..56034403a 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/parameters.utils.ts @@ -59,7 +59,7 @@ export const computeDepthParameters = (): OpenAPIV3_1.ParameterObject => { required: false, schema: { type: 'integer', - enum: [1, 2], + enum: [0, 1, 2], }, }; };