Skip to content

[backend] validate date inputs format in validateInputAgainstSchema (#10881) #10984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 });
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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';
};
Expand Down Expand Up @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down