Skip to content
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

Fix race condition caused by incorrect date casted from serialized dashboard format #727

Merged
merged 1 commit into from
Dec 6, 2023
Merged
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
11 changes: 11 additions & 0 deletions src/dashboard/DashboardThunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { applicationGetConnectionUser, applicationIsStandalone } from '../application/ApplicationSelectors';
import { applicationGetLoggingSettings } from '../application/logging/LoggingSelectors';
import { NEODASH_VERSION, VERSION_TO_MIGRATE } from './DashboardReducer';
import { Date as Neo4jDate } from 'neo4j-driver-core/lib/temporal-types.js';

export const removePageThunk = (number) => (dispatch: any, getState: any) => {
try {
Expand Down Expand Up @@ -101,6 +102,16 @@
throw `Invalid dashboard version: ${dashboard.version}. Try restarting the application, or retrieve your cached dashboard using a debug report.`;
}

// Cast dashboard parameters from serialized format to correct types
Object.keys(dashboard.settings.parameters).forEach((key) => {
const value = dashboard.settings.parameters[key];

Check warning on line 107 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L106-L107

Added lines #L106 - L107 were not covered by tests

// Serialized Date to Neo4jDate
if (value && value.year && value.month && value.day) {
dashboard.settings.parameters[key] = new Neo4jDate(value.year, value.month, value.day);

Check warning on line 111 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L111

Added line #L111 was not covered by tests
}
});

// Reverse engineer the minimal set of fields from the selection loaded.
dashboard.pages.forEach((p) => {
p.reports.forEach((r) => {
Expand Down Expand Up @@ -133,29 +144,29 @@

export const saveDashboardToNeo4jThunk =
(driver, database, dashboard, date, user, onSuccess) => (dispatch: any, getState: any) => {
const state = getState();
const loggingSettings = applicationGetLoggingSettings(state);
const loguser = applicationGetConnectionUser(state);

Check warning on line 149 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L147-L149

Added lines #L147 - L149 were not covered by tests
const neodashMode = applicationIsStandalone(state) ? 'Standalone' : 'Editor';

try {
let { uuid } = dashboard;

Check warning on line 153 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L152-L153

Added lines #L152 - L153 were not covered by tests

// Dashboards pre-2.3.4 may not always have a UUID. If this is the case, generate one just before we save.
if (!dashboard.uuid) {
uuid = createUUID();
dashboard.uuid = uuid;
dispatch(setDashboardUuid(uuid));
createUUID();

Check warning on line 160 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L157-L160

Added lines #L157 - L160 were not covered by tests
}

const { title, version } = dashboard;

Check warning on line 163 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L163

Added line #L163 was not covered by tests

// Generate a cypher query to save the dashboard.
const query =
'MERGE (n:_Neodash_Dashboard {uuid: $uuid }) SET n.title = $title, n.version = $version, n.user = $user, n.content = $content, n.date = datetime($date) RETURN $uuid as uuid';

Check warning on line 167 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L167

Added line #L167 was not covered by tests

const parameters = {

Check warning on line 169 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L169

Added line #L169 was not covered by tests
uuid: uuid,
title: title,
version: version,
Expand All @@ -163,19 +174,19 @@
content: JSON.stringify(dashboard, null, 2),
date: date,
};
runCypherQuery(

Check warning on line 177 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L177

Added line #L177 was not covered by tests
driver,
database,
query,
parameters,
1,
() => {},
(records) => {

Check warning on line 184 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L183-L184

Added lines #L183 - L184 were not covered by tests
if (records && records[0] && records[0]._fields && records[0]._fields[0] && records[0]._fields[0] == uuid) {
dispatch(createNotificationThunk('🎉 Success!', 'Your current dashboard was saved to Neo4j.'));
onSuccess(uuid);

Check warning on line 187 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L186-L187

Added lines #L186 - L187 were not covered by tests
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 189 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L189

Added line #L189 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -191,15 +202,15 @@
)
);
}
} else {
dispatch(

Check warning on line 206 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L205-L206

Added lines #L205 - L206 were not covered by tests
createNotificationThunk(
'Unable to save dashboard',
`Do you have write access to the '${database}' database?`
)
);
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 213 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L213

Added line #L213 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -219,9 +230,9 @@
}
);
} catch (e) {
dispatch(createNotificationThunk('Unable to save dashboard to Neo4j', e));

Check warning on line 233 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L233

Added line #L233 was not covered by tests
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 235 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L235

Added line #L235 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand Down Expand Up @@ -274,9 +285,9 @@
};

export const loadDashboardFromNeo4jThunk = (driver, database, uuid, callback) => (dispatch: any, getState: any) => {
const state = getState();
const loggingSettings = applicationGetLoggingSettings(state);
const loguser = applicationGetConnectionUser(state);

Check warning on line 290 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L288-L290

Added lines #L288 - L290 were not covered by tests
const neodashMode = applicationIsStandalone(state) ? 'Standalone' : 'Editor';

try {
Expand Down Expand Up @@ -306,7 +317,7 @@
)
);
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 320 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L320

Added line #L320 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -325,8 +336,8 @@
} else {
callback(records[0]._fields[0]);
if (loggingSettings.loggingMode > '1') {
const dashboard = JSON.parse(records[0]._fields[0]);
dispatch(

Check warning on line 340 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L339-L340

Added lines #L339 - L340 were not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -348,7 +359,7 @@
} catch (e) {
dispatch(createNotificationThunk('Unable to load dashboard to Neo4j', e));
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 362 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L362

Added line #L362 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -366,22 +377,22 @@

export const loadDashboardFromNeo4jByNameThunk =
(driver, database, name, callback) => (dispatch: any, getState: any) => {
const loggingState = getState();
const loggingSettings = applicationGetLoggingSettings(loggingState);
const loguser = applicationGetConnectionUser(loggingState);

Check warning on line 382 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L380-L382

Added lines #L380 - L382 were not covered by tests
const neodashMode = applicationIsStandalone(loggingState) ? 'Standalone' : 'Editor';
try {

Check warning on line 384 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L384

Added line #L384 was not covered by tests
const query =
'MATCH (d:_Neodash_Dashboard) WHERE d.title = $name RETURN d.content as dashboard ORDER by d.date DESC LIMIT 1';
runCypherQuery(

Check warning on line 387 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L386-L387

Added lines #L386 - L387 were not covered by tests
driver,
database,
query,
{ name: name },
1,
(status) => {

Check warning on line 393 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L393

Added line #L393 was not covered by tests
if (status == QueryStatus.NO_DATA) {
dispatch(

Check warning on line 395 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L395

Added line #L395 was not covered by tests
createNotificationThunk(
'Unable to load dashboard.',
'A dashboard with the provided name could not be found.'
Expand All @@ -389,16 +400,16 @@
);
}
},
(records) => {

Check warning on line 403 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L403

Added line #L403 was not covered by tests
if (records.length == 0) {
dispatch(

Check warning on line 405 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L405

Added line #L405 was not covered by tests
createNotificationThunk(
'Unable to load dashboard.',
'A dashboard with the provided name could not be found.'
)
);
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 412 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L412

Added line #L412 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -414,13 +425,13 @@
)
);
}
return;

Check warning on line 428 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L428

Added line #L428 was not covered by tests
}

if (records[0].error) {
dispatch(createNotificationThunk('Unable to load dashboard.', records[0].error));

Check warning on line 432 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L432

Added line #L432 was not covered by tests
if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 434 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L434

Added line #L434 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -436,11 +447,11 @@
)
);
}
return;

Check warning on line 450 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L450

Added line #L450 was not covered by tests
}

if (loggingSettings.loggingMode > '1') {
dispatch(

Check warning on line 454 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L454

Added line #L454 was not covered by tests
createLogThunk(
driver,
loggingSettings.loggingDatabase,
Expand All @@ -456,27 +467,27 @@
)
);
}
callback(records[0]._fields[0]);

Check warning on line 470 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L470

Added line #L470 was not covered by tests
}
);
} catch (e) {
dispatch(createNotificationThunk('Unable to load dashboard from Neo4j', e));

Check warning on line 474 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L474

Added line #L474 was not covered by tests
}
};

export const loadDashboardListFromNeo4jThunk = (driver, database, callback) => (dispatch: any) => {
function setStatus(status) {

Check warning on line 479 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L479

Added line #L479 was not covered by tests
if (status == QueryStatus.NO_DATA) {
runCallback([]);

Check warning on line 481 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L481

Added line #L481 was not covered by tests
}
}
function runCallback(records) {

Check warning on line 484 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L484

Added line #L484 was not covered by tests
if (!records || !records[0] || !records[0]._fields) {
callback([]);
return;

Check warning on line 487 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L486-L487

Added lines #L486 - L487 were not covered by tests
}
const result = records.map((r, index) => {
return {

Check warning on line 490 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L489-L490

Added lines #L489 - L490 were not covered by tests
uuid: r._fields[0],
title: r._fields[1],
date: r._fields[2],
Expand All @@ -485,7 +496,7 @@
index: index,
};
});
callback(result);

Check warning on line 499 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L499

Added line #L499 was not covered by tests
}
try {
runCypherQuery(
Expand All @@ -494,8 +505,8 @@
'MATCH (n:_Neodash_Dashboard) RETURN n.uuid as uuid, n.title as title, toString(n.date) as date, n.user as author, n.version as version ORDER BY date DESC',
{},
1000,
(status) => setStatus(status),
(records) => runCallback(records)

Check warning on line 509 in src/dashboard/DashboardThunks.ts

View check run for this annotation

Codecov / codecov/patch

src/dashboard/DashboardThunks.ts#L508-L509

Added lines #L508 - L509 were not covered by tests
);
} catch (e) {
dispatch(createNotificationThunk('Unable to load dashboard list from Neo4j', e));
Expand Down
Loading