Fix send email error when empty connected account (#10005)
- Fix send email error when empty connected account - Add a global util to valid uuid - Add an util to check if object is workflow related
This commit is contained in:
@ -1,8 +1,7 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { isWorkflowRelatedObjectMetadata } from '@/object-metadata/utils/isWorkflowRelatedObjectMetadata';
|
||||||
import { isWorkflowSubObjectMetadata } from '@/object-metadata/utils/isWorkflowSubObjectMetadata';
|
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
@ -14,11 +13,7 @@ export const useFilteredObjectMetadataItems = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isWorkflowToBeFiltered = (nameSingular: string) => {
|
const isWorkflowToBeFiltered = (nameSingular: string) => {
|
||||||
return (
|
return !isWorkflowEnabled && isWorkflowRelatedObjectMetadata(nameSingular);
|
||||||
!isWorkflowEnabled &&
|
|
||||||
(nameSingular === CoreObjectNameSingular.Workflow ||
|
|
||||||
isWorkflowSubObjectMetadata(nameSingular))
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const activeObjectMetadataItems = objectMetadataItems.filter(
|
const activeObjectMetadataItems = objectMetadataItems.filter(
|
||||||
|
|||||||
@ -5,8 +5,7 @@ import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objec
|
|||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { isDefined } from 'twenty-shared';
|
import { isDefined } from 'twenty-shared';
|
||||||
|
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { isWorkflowRelatedObjectMetadata } from '@/object-metadata/utils/isWorkflowRelatedObjectMetadata';
|
||||||
import { isWorkflowSubObjectMetadata } from '@/object-metadata/utils/isWorkflowSubObjectMetadata';
|
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||||
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
|
||||||
@ -26,9 +25,7 @@ export const useObjectMetadataItem = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isWorkflowToBeFiltered =
|
const isWorkflowToBeFiltered =
|
||||||
!isWorkflowEnabled &&
|
!isWorkflowEnabled && isWorkflowRelatedObjectMetadata(objectNameSingular);
|
||||||
(objectNameSingular === CoreObjectNameSingular.Workflow ||
|
|
||||||
isWorkflowSubObjectMetadata(objectNameSingular));
|
|
||||||
|
|
||||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { isWorkflowSubObjectMetadata } from '@/object-metadata/utils/isWorkflowSubObjectMetadata';
|
||||||
|
import { CoreObjectNameSingular } from '../types/CoreObjectNameSingular';
|
||||||
|
|
||||||
|
export const isWorkflowRelatedObjectMetadata = (objectNameSingular: string) => {
|
||||||
|
return (
|
||||||
|
objectNameSingular === CoreObjectNameSingular.Workflow ||
|
||||||
|
isWorkflowSubObjectMetadata(objectNameSingular)
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,7 +1,6 @@
|
|||||||
import { FieldValidationDefinition } from '@/spreadsheet-import/types';
|
import { FieldValidationDefinition } from '@/spreadsheet-import/types';
|
||||||
import { isDefined } from 'twenty-shared';
|
import { isDefined, isValidUuid } from 'twenty-shared';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
import { isValidUuid } from '~/utils/isValidUuid';
|
|
||||||
import { absoluteUrlSchema } from '~/utils/validation-schemas/absoluteUrlSchema';
|
import { absoluteUrlSchema } from '~/utils/validation-schemas/absoluteUrlSchema';
|
||||||
|
|
||||||
export const getSpreadSheetFieldValidationDefinitions = (
|
export const getSpreadSheetFieldValidationDefinitions = (
|
||||||
|
|||||||
@ -16,9 +16,8 @@ import { WorkflowVariablesDropdown } from '@/workflow/workflow-variables/compone
|
|||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { isDefined } from 'twenty-shared';
|
import { isDefined, isValidUuid } from 'twenty-shared';
|
||||||
import { IconChevronDown, IconForbid, LightIconButton } from 'twenty-ui';
|
import { IconChevronDown, IconForbid, LightIconButton } from 'twenty-ui';
|
||||||
import { isValidUuid } from '~/utils/isValidUuid';
|
|
||||||
|
|
||||||
const StyledFormSelectContainer = styled(FormFieldInputInputContainer)`
|
const StyledFormSelectContainer = styled(FormFieldInputInputContainer)`
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
import { isValidUuid } from '~/utils/isValidUuid';
|
|
||||||
|
|
||||||
describe('isValidUuid', () => {
|
|
||||||
it('returns true if value is a valid UUID', () => {
|
|
||||||
expect(isValidUuid('bec09e27-4ecc-4a85-afc1-f2c0ace28bfa')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns false if value is not a valid UUID', () => {
|
|
||||||
expect(isValidUuid('123e4567-e89b-12d3-a456-42661417400')).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,15 +1,12 @@
|
|||||||
|
import { isValidUuid } from 'twenty-shared';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
WorkspaceQueryRunnerException,
|
WorkspaceQueryRunnerException,
|
||||||
WorkspaceQueryRunnerExceptionCode,
|
WorkspaceQueryRunnerExceptionCode,
|
||||||
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
|
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
|
||||||
|
|
||||||
export const assertIsValidUuid = (value: string) => {
|
export const assertIsValidUuid = (value: string) => {
|
||||||
const isValid =
|
if (!isValidUuid(value)) {
|
||||||
/^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i.test(
|
|
||||||
value,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isValid) {
|
|
||||||
throw new WorkspaceQueryRunnerException(
|
throw new WorkspaceQueryRunnerException(
|
||||||
`Value "${value}" is not a valid UUID`,
|
`Value "${value}" is not a valid UUID`,
|
||||||
WorkspaceQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
|
WorkspaceQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
|
||||||
|
|||||||
@ -11,4 +11,5 @@ export enum SendEmailActionExceptionCode {
|
|||||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||||
CONNECTED_ACCOUNT_NOT_FOUND = 'CONNECTED_ACCOUNT_NOT_FOUND',
|
CONNECTED_ACCOUNT_NOT_FOUND = 'CONNECTED_ACCOUNT_NOT_FOUND',
|
||||||
INVALID_EMAIL = 'INVALID_EMAIL',
|
INVALID_EMAIL = 'INVALID_EMAIL',
|
||||||
|
INVALID_CONNECTED_ACCOUNT_ID = 'INVALID_CONNECTED_ACCOUNT_ID',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
|
import { isDefined, isValidUuid } from 'twenty-shared';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { isDefined } from 'twenty-shared';
|
|
||||||
|
|
||||||
import { WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface';
|
import { WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface';
|
||||||
|
|
||||||
@ -36,6 +36,13 @@ export class SendEmailWorkflowAction implements WorkflowAction {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
private async getEmailClient(connectedAccountId: string) {
|
private async getEmailClient(connectedAccountId: string) {
|
||||||
|
if (!isValidUuid(connectedAccountId)) {
|
||||||
|
throw new SendEmailActionException(
|
||||||
|
`Connected Account ID is not a valid UUID`,
|
||||||
|
SendEmailActionExceptionCode.INVALID_CONNECTED_ACCOUNT_ID,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const { workspaceId } = this.scopedWorkspaceContextFactory.create();
|
const { workspaceId } = this.scopedWorkspaceContextFactory.create();
|
||||||
|
|
||||||
if (!workspaceId) {
|
if (!workspaceId) {
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { isValidUuid } from '../isValidUuid.util';
|
||||||
|
|
||||||
|
describe('isValidUuid', () => {
|
||||||
|
it('should return true for a valid UUID', () => {
|
||||||
|
expect(isValidUuid('123e4567-e89b-12d3-a456-426614174000')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for an invalid UUID', () => {
|
||||||
|
expect(isValidUuid('123e4567-e89b-12d3-a456-426614174000')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1 +1,2 @@
|
|||||||
export * from './capitalize.util';
|
export * from './capitalize.util';
|
||||||
|
export * from './isValidUuid.util';
|
||||||
|
|||||||
Reference in New Issue
Block a user