diff --git a/opencti-platform/opencti-graphql/src/manager/ingestionManager.ts b/opencti-platform/opencti-graphql/src/manager/ingestionManager.ts index 0d22d7c0bc77..4f9e3a143a07 100644 --- a/opencti-platform/opencti-graphql/src/manager/ingestionManager.ts +++ b/opencti-platform/opencti-graphql/src/manager/ingestionManager.ts @@ -431,7 +431,7 @@ export const processTaxiiResponse = async (context: AuthContext, ingestion: Basi // Reset the pagination cursor, and update date const state = { current_state_cursor: undefined, - added_after_start: addedLastHeader ? utcDate(addedLastHeader) : utcDate(), + added_after_start: addedLastHeader ? utcDate(addedLastHeader).toISOString() : now(), last_execution_date: now() }; const ingestionUpdate = await patchTaxiiIngestion(context, SYSTEM_USER, ingestion.internal_id, state); @@ -529,7 +529,7 @@ export const processCsvLines = async ( await reportExpectation(context, ingestionUser, work.id);// csv file ends = 1 operation done. logApp.info(`[OPENCTI-MODULE] INGESTION Csv - Sent: ${bundleCount} bundles for ${objectsInBundleCount} objects.`); - const state = { current_state_hash: hashedIncomingData, added_after_start: utcDate(addedLast), last_execution_date: now() }; + const state = { current_state_hash: hashedIncomingData, added_after_start: utcDate(addedLast).toISOString(), last_execution_date: now() }; await patchCsvIngestion(context, SYSTEM_USER, ingestion.internal_id, state); await updateBuiltInConnectorInfo(context, ingestion.user_id, ingestion.id, { state }); } diff --git a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts index c4220bf1b5d8..a3b6d853c2e0 100644 --- a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts +++ b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts @@ -1,4 +1,3 @@ -import type { Moment } from 'moment/moment'; import { type BasicStoreEntityIngestionTaxii, ENTITY_TYPE_INGESTION_TAXII } from './ingestion-types'; import { createEntity, deleteElementById, patchAttribute, updateAttribute } from '../../database/middleware'; import { listAllEntities, listEntitiesPaginated, storeLoadById } from '../../database/middleware-loader'; @@ -51,7 +50,7 @@ export const addIngestion = async (context: AuthContext, user: AuthUser, input: export interface TaxiiIngestionPatch { current_state_cursor?: string | undefined, last_execution_date?: string, - added_after_start?: Moment, + added_after_start?: string, } export const patchTaxiiIngestion = async (context: AuthContext, user: AuthUser, id: string, patch: TaxiiIngestionPatch) => { diff --git a/opencti-platform/opencti-graphql/src/schema/schema-attributes.ts b/opencti-platform/opencti-graphql/src/schema/schema-attributes.ts index 77d65d699c3e..1182ed041106 100644 --- a/opencti-platform/opencti-graphql/src/schema/schema-attributes.ts +++ b/opencti-platform/opencti-graphql/src/schema/schema-attributes.ts @@ -1,4 +1,5 @@ import * as R from 'ramda'; +import { GraphQLDateTime } from 'graphql-scalars'; import { RULE_PREFIX } from './general'; import { FunctionalError, UnsupportedError } from '../config/errors'; import type { AttributeDefinition, AttrType, ComplexAttributeWithMappings, MappingDefinition } from './attribute-definition'; @@ -20,7 +21,7 @@ export const depsKeysRegister = { // -- Utilities to manipulate AttributeDefinitions -- const isMandatoryAttributeDefinition = (schemaDef: AttributeDefinition) => schemaDef.mandatoryType === 'external' || schemaDef.mandatoryType === 'internal'; - +const isDateAttributeDefinition = (schemaDef: AttributeDefinition) => schemaDef.type === 'date'; const isNonFlatObjectAttributeDefinition = (schemaDef: AttributeDefinition) : schemaDef is ComplexAttributeWithMappings => { // handy typeguard return schemaDef.type === 'object' && schemaDef.format !== 'flat'; }; @@ -301,6 +302,13 @@ const validateInputAgainstSchema = (input: any, schemaDef: AttributeDefinition) if (isMandatory && R.isNil(input)) { throw FunctionalError(`Validation against schema failed on attribute [${schemaDef.name}]: this mandatory field cannot be nil`); } + if (isDateAttributeDefinition(schemaDef) && !R.isNil(input)) { + try { + GraphQLDateTime.parseValue(input); + } catch { + throw FunctionalError(`Validation against schema failed on attribute [${schemaDef.name}]: this date field is not in a valid format`); + } + } if (isNonFlatObjectAttributeDefinition(schemaDef)) { if (!isMandatory && R.isNil(input)) { diff --git a/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/ingestion-csv-test.ts b/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/ingestion-csv-test.ts index 0696854fe3c8..8f590442ab10 100644 --- a/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/ingestion-csv-test.ts +++ b/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/ingestion-csv-test.ts @@ -3,7 +3,7 @@ import gql from 'graphql-tag'; import { ADMIN_USER, queryAsAdmin, testContext, USER_PARTICIPATE } from '../../utils/testQuery'; import { queryAsAdminWithSuccess, queryAsUserIsExpectedForbidden } from '../../utils/testQueryHelper'; import { patchCsvIngestion } from '../../../src/modules/ingestion/ingestion-csv-domain'; -import { utcDate } from '../../../src/utils/format'; +import { now } from '../../../src/utils/format'; import { SYSTEM_USER } from '../../../src/utils/access'; describe('CSV ingestion resolver standard behavior', () => { @@ -156,7 +156,7 @@ describe('CSV ingestion resolver standard behavior', () => { it('should reset state of CSV feeds ingester', async () => { // shortcut to set a hash that is defined - const patch = { current_state_hash: 'bbbbbbbbbbbbbbbbbb', added_after_start: utcDate() }; + const patch = { current_state_hash: 'bbbbbbbbbbbbbbbbbb', added_after_start: now() }; const result = await patchCsvIngestion(testContext, SYSTEM_USER, singleColumnCsvFeedIngesterId, patch); expect(result.current_state_hash).toBe('bbbbbbbbbbbbbbbbbb'); diff --git a/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/report-test.js b/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/report-test.js index 732fe681e191..271b10297cdf 100644 --- a/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/report-test.js +++ b/opencti-platform/opencti-graphql/tests/02-integration/02-resolvers/report-test.js @@ -337,6 +337,25 @@ describe('Report resolver standard behavior', () => { }); expect(queryResult.data.reportEdit.fieldPatch.name).toEqual('Report - test'); }); + it('should update report with invalid published date fail', async () => { + const UPDATE_QUERY = gql` + mutation ReportEdit($id: ID!, $input: [EditInput]!) { + reportEdit(id: $id) { + fieldPatch(input: $input) { + id + name + description + published + } + } + } + `; + const queryResult = await queryAsAdmin({ + query: UPDATE_QUERY, + variables: { id: reportInternalId, input: { key: 'published', value: ['2025-02-01'] } }, + }); + expect(queryResult.errors).toBeDefined(); + }); it('should context patch report', async () => { const CONTEXT_PATCH_QUERY = gql` mutation ReportEdit($id: ID!, $input: EditContext) {