diff --git a/opencti-platform/opencti-front/src/private/components/common/stix_observable_relations/StixObservableRelationCreationFromEntity.js b/opencti-platform/opencti-front/src/private/components/common/stix_observable_relations/StixObservableRelationCreationFromEntity.js index 083650de2b29..8c3bdf29bd34 100644 --- a/opencti-platform/opencti-front/src/private/components/common/stix_observable_relations/StixObservableRelationCreationFromEntity.js +++ b/opencti-platform/opencti-front/src/private/components/common/stix_observable_relations/StixObservableRelationCreationFromEntity.js @@ -24,7 +24,7 @@ import { ConnectionHandler } from 'relay-runtime'; import { commitMutation, QueryRenderer } from '../../../../relay/environment'; import inject18n from '../../../../components/i18n'; import { itemColor } from '../../../../utils/Colors'; -import { parse } from '../../../../utils/Time'; +import { dayStartDate, parse } from '../../../../utils/Time'; import { resolveRoles, resolveRelationsTypes, @@ -380,8 +380,8 @@ class StixObservableRelationCreationFromEntity extends Component { const initialValues = { relationship_type: defaultRelationshipType, role_played: 'Unknown', - first_seen: new Date(), - last_seen: new Date(), + first_seen: dayStartDate(), + last_seen: dayStartDate(), }; return ( { + const start = new Date(); + start.setHours(0, 0, 0, 0); + return start; +}; export const parse = (date) => moment(date); export const now = () => moment().format(); -export const dayAgo = () => moment() - .subtract(1, 'days') - .format(); - -export const monthsAgo = (number) => moment() - .subtract(number, 'months') - .format(); - -export const dateMonthsAgo = (date, number) => moment(date) - .subtract(number, 'months') - .format(); +export const dayAgo = () => moment().subtract(1, 'days').format(); -export const dateMonthsAfter = (date, number) => moment(date) - .add(number, 'months') - .format(); +export const monthsAgo = (number) => moment().subtract(number, 'months').format(); -export const yearsAgo = (number) => moment() - .subtract(number, 'years') - .format(); - -export const dayFormat = (data) => (data && data !== '-' ? parse(data).format(dayDateFormat) : ''); +export const yearsAgo = (number) => moment().subtract(number, 'years').format(); export const yearFormat = (data) => (data && data !== '-' ? parse(data).format(yearDateFormat) : ''); -export const currentYear = () => yearFormat(now()); - -export const timeDiff = (start, end) => parse(start).diff(parse(end)); - -export const timeFormat = (data) => (data && data !== '-' ? parse(data).format(timeDateFormat) : ''); - export const dateFormat = (data, specificFormat) => (data && data !== '-' ? parse(data).format(specificFormat || defaultDateFormat) : ''); - -export const dateToISO = (date) => { - const momentDate = parse(date); - return momentDate.isValid() ? momentDate.format() : 'invalid-date'; -}; - -export const dateFromNow = (dateString) => (dateString ? countdown(parse(dateString).toDate()).toString() : ''); - -export const convertToCountdown = (durationInMillis) => { - if (durationInMillis === null) return '-'; - const end = now(); - const start = moment(end).subtract(durationInMillis, 'ms'); - return countdown(start.toDate(), end.toDate()).toString(); -}; - -export const logDate = () => now().format('HH:mm:ss.SSS'); diff --git a/opencti-platform/opencti-graphql/src/database/grakn.js b/opencti-platform/opencti-graphql/src/database/grakn.js index bd7368f7ad2a..5e73cca49124 100644 --- a/opencti-platform/opencti-graphql/src/database/grakn.js +++ b/opencti-platform/opencti-graphql/src/database/grakn.js @@ -93,33 +93,19 @@ export const inferIndexFromConceptTypes = (types, parentType = null) => { return INDEX_STIX_ENTITIES; }; -export const now = () => { - // eslint-disable-next-line prettier/prettier - return moment() - .utc() - .toISOString(); -}; -export const graknNow = () => { - // eslint-disable-next-line prettier/prettier - return moment() - .utc() - .format(dateFormat); // Format that accept grakn -}; -export const prepareDate = date => { - // eslint-disable-next-line prettier/prettier - return moment(date) - .utc() - .format(dateFormat); -}; +export const utcDate = (date = undefined) => (date ? moment(date).utc() : moment().utc()); +export const now = () => utcDate().toISOString(); +export const graknNow = () => utcDate().format(dateFormat); // Format that accept grakn +export const prepareDate = date => utcDate(date).format(dateFormat); export const sinceNowInMinutes = lastModified => { - const utc = moment().utc(); - const diff = utc.diff(moment(lastModified)); + const diff = utcDate().diff(moment(lastModified)); const duration = moment.duration(diff); return Math.floor(duration.asMinutes()); }; -export const yearFormat = date => moment(date).format('YYYY'); -export const monthFormat = date => moment(date).format('YYYY-MM'); -export const dayFormat = date => moment(date).format('YYYY-MM-DD'); +export const yearFormat = date => utcDate(date).format('YYYY'); +export const monthFormat = date => utcDate(date).format('YYYY-MM'); +export const dayFormat = date => utcDate(date).format('YYYY-MM-DD'); + export const escape = chars => { const toEscape = chars && typeof chars === 'string'; if (toEscape) { @@ -1709,15 +1695,16 @@ export const createEntity = async (entity, type, opts = {}) => { // endregion // region mutation update -export const updateAttribute = async (id, type, input, wTx) => { +export const updateAttribute = async (id, type, input, wTx, options = {}) => { + const { forceUpdate = false } = options; const { key, value } = input; // value can be multi valued if (includes(key, readOnlyAttributes)) { throw new DatabaseError({ data: { details: `The field ${key} cannot be modified` } }); } - // --- 00 Need update? - const val = includes(key, multipleAttributes) ? value : head(value); const currentInstanceData = await loadEntityById(id, type); - if (equals(currentInstanceData[key], val)) { + const val = includes(key, multipleAttributes) ? value : head(value); + // --- 00 Need update? + if (!forceUpdate && equals(currentInstanceData[key], val)) { return id; } // --- 01 Get the current attribute types @@ -1761,17 +1748,17 @@ export const updateAttribute = async (id, type, input, wTx) => { const monthValue = monthFormat(head(value)); const yearValue = yearFormat(head(value)); const dayInput = { key: `${key}_day`, value: [dayValue] }; - await updateAttribute(id, type, dayInput, wTx); + await updateAttribute(id, type, dayInput, wTx, options); const monthInput = { key: `${key}_month`, value: [monthValue] }; - await updateAttribute(id, type, monthInput, wTx); + await updateAttribute(id, type, monthInput, wTx, options); const yearInput = { key: `${key}_year`, value: [yearValue] }; - await updateAttribute(id, type, yearInput, wTx); + await updateAttribute(id, type, yearInput, wTx, options); } // Update modified / updated_at if (currentInstanceData.parent_types.includes(TYPE_STIX_DOMAIN) && key !== 'modified' && key !== 'updated_at') { const today = now(); - await updateAttribute(id, type, { key: 'updated_at', value: [today] }, wTx); - await updateAttribute(id, type, { key: 'modified', value: [today] }, wTx); + await updateAttribute(id, type, { key: 'updated_at', value: [today] }, wTx, options); + await updateAttribute(id, type, { key: 'modified', value: [today] }, wTx, options); } // Update elasticsearch diff --git a/opencti-platform/opencti-graphql/src/domain/indicator.js b/opencti-platform/opencti-graphql/src/domain/indicator.js index 18f32c9f9e1f..34eb52855800 100644 --- a/opencti-platform/opencti-graphql/src/domain/indicator.js +++ b/opencti-platform/opencti-graphql/src/domain/indicator.js @@ -8,6 +8,7 @@ import { listEntities, loadEntityById, loadEntityByStixId, + now, TYPE_STIX_DOMAIN_ENTITY, TYPE_STIX_OBSERVABLE } from '../database/grakn'; @@ -117,7 +118,7 @@ export const addIndicator = async (user, indicator, createObservables = true) => const indicatorToCreate = pipe( assoc('main_observable_type', indicator.main_observable_type.toLowerCase()), assoc('score', indicator.score ? indicator.score : 50), - assoc('valid_from', indicator.valid_from ? indicator.valid_from : new Date()), + assoc('valid_from', indicator.valid_from ? indicator.valid_from : now()), assoc('valid_until', indicator.valid_until ? indicator.valid_until : await computeValidUntil(indicator)) )(indicator); // create the linked observables diff --git a/opencti-platform/opencti-graphql/src/migrations/1583491791006-report-published-utc.js b/opencti-platform/opencti-graphql/src/migrations/1583491791006-report-published-utc.js new file mode 100644 index 000000000000..c73351982898 --- /dev/null +++ b/opencti-platform/opencti-graphql/src/migrations/1583491791006-report-published-utc.js @@ -0,0 +1,42 @@ +import { filter, map } from 'ramda'; +import { Promise } from 'bluebird'; +import { findAll } from '../domain/report'; +import { dayFormat, executeWrite, updateAttribute } from '../database/grakn'; +import { logger } from '../config/conf'; + +export const up = async next => { + const reports = await findAll(); + // For each report we need to force update + if (reports && reports.edges) { + const reportNodes = map(report => report.node, reports.edges); + const reportsToModify = filter(r => { + const expectedPublishedDay = dayFormat(r.published); + const currentPublishedDay = r.published_day; + return expectedPublishedDay === currentPublishedDay; + }, reportNodes); + logger.info(`[MIGRATION] report-published-utc > ${reportsToModify.length} reports to modify`); + await Promise.map( + reportsToModify, + report => { + return executeWrite(wTx => { + return updateAttribute( + report.id, + 'Report', + { + key: 'published', + value: [report.published] + }, + wTx, + { forceUpdate: true } // Need to force update because the impact is on sub dates of published + ); + }); + }, + { concurrency: 3 } + ); + } + next(); +}; + +export const down = async next => { + next(); +};