Skip to content

Commit

Permalink
[api/frontend] Fix the timezone usage and migrate report published da…
Browse files Browse the repository at this point in the history
…te (#551)

* [api] Fix of timezone for day/month/year sub dates
* [api/front] Fixing front date usage and introduce migration for reports publish date
  • Loading branch information
richard-julien authored Mar 7, 2020
1 parent 2a5bda8 commit 992ad43
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 (
<QueryRenderer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,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 {
resolveRelationsTypes,
resolveRoles,
Expand Down Expand Up @@ -481,8 +481,8 @@ class StixRelationCreationFromEntity extends Component {
relationship_type: defaultRelationshipType,
weight: 1,
role_played: '',
first_seen: new Date(),
last_seen: new Date(),
first_seen: dayStartDate(),
last_seen: dayStartDate(),
description: '',
killChainPhases: [],
markingDefinitions: [],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import * as PropTypes from 'prop-types';
import { Formik, Form } from 'formik';
import { Form, Formik } from 'formik';
import { withStyles } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import Typography from '@material-ui/core/Typography';
Expand All @@ -10,14 +10,14 @@ import MenuItem from '@material-ui/core/MenuItem';
import Fab from '@material-ui/core/Fab';
import { Add, Close } from '@material-ui/icons';
import {
compose, pluck, evolve, path,
compose, evolve, path, pluck,
} from 'ramda';
import * as Yup from 'yup';
import graphql from 'babel-plugin-relay/macro';
import { ConnectionHandler } from 'relay-runtime';
import { parse } from '../../../utils/Time';
import { dayStartDate, parse } from '../../../utils/Time';
import inject18n from '../../../components/i18n';
import { QueryRenderer, commitMutation } from '../../../relay/environment';
import { commitMutation, QueryRenderer } from '../../../relay/environment';
import TextField from '../../../components/TextField';
import DatePickerField from '../../../components/DatePickerField';
import SelectField from '../../../components/SelectField';
Expand Down Expand Up @@ -193,7 +193,7 @@ class ReportCreation extends Component {
<Formik
initialValues={{
name: '',
published: new Date(),
published: dayStartDate(),
description: '',
report_class: '',
createdByRef: '',
Expand Down
55 changes: 9 additions & 46 deletions opencti-platform/opencti-front/src/utils/Time.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,29 @@
import moment from 'moment-timezone';
import countdown from 'countdown';

const dayDateFormat = 'MMMM Do YYYY';
const timeDateFormat = 'HH:mm:ss';
const defaultDateFormat = 'YYYY-MM-DD';
const yearDateFormat = 'YYYY';

export const ONE_MINUTE = 60 * 1000;
export const FIVE_SECONDS = 5000;
export const TEN_SECONDS = FIVE_SECONDS * 2;
export const ONE_SECOND = 1000;

export const dayStartDate = () => {
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');
51 changes: 19 additions & 32 deletions opencti-platform/opencti-graphql/src/database/grakn.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion opencti-platform/opencti-graphql/src/domain/indicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
listEntities,
loadEntityById,
loadEntityByStixId,
now,
TYPE_STIX_DOMAIN_ENTITY,
TYPE_STIX_OBSERVABLE
} from '../database/grakn';
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
};

0 comments on commit 992ad43

Please sign in to comment.