From b88fe8fbfc5a3c6f1599fa1fa1874c0f95404282 Mon Sep 17 00:00:00 2001 From: Arnaud AMBROSELLI Date: Mon, 25 Apr 2022 14:34:54 +0200 Subject: [PATCH 1/4] feat(api): set deletedAt in all data models + update lastRefresh to fetch also data related to deletedAt --- api/src/controllers/action.js | 12 +++++- api/src/controllers/comment.js | 12 +++++- api/src/controllers/organisation.js | 7 +++- api/src/controllers/passage.js | 12 +++++- api/src/controllers/person.js | 14 ++++++- api/src/controllers/place.js | 12 +++++- api/src/controllers/relPersonPlace.js | 18 +++++++-- api/src/controllers/report.js | 12 +++++- api/src/controllers/territory.js | 11 ++++- api/src/controllers/territoryObservation.js | 12 +++++- .../db/migrations/2022-04-25_soft-delete.js | 40 +++++++++++++++++++ api/src/db/migrations/index.js | 1 + api/src/models/action.js | 2 +- api/src/models/comment.js | 2 +- api/src/models/passage.js | 2 +- api/src/models/person.js | 2 +- api/src/models/place.js | 2 +- api/src/models/relPersonPlace.js | 2 +- api/src/models/report.js | 2 +- api/src/models/territory.js | 2 +- api/src/models/territoryObservation.js | 2 +- 21 files changed, 152 insertions(+), 29 deletions(-) create mode 100644 api/src/db/migrations/2022-04-25_soft-delete.js diff --git a/api/src/controllers/action.js b/api/src/controllers/action.js index 9d0f681d5..473ba729f 100644 --- a/api/src/controllers/action.js +++ b/api/src/controllers/action.js @@ -52,6 +52,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, status: data.status, dueAt: data.dueAt, completedAt: data.completedAt, @@ -88,7 +89,10 @@ router.get( const total = await Action.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const sortDoneOrCancel = (a, b) => { if (!a.dueAt) return -1; @@ -107,6 +111,7 @@ router.get( "organisation", "createdAt", "updatedAt", + "deletedAt", // Specific fields that are not encrypted "status", "dueAt", @@ -168,6 +173,7 @@ router.put( organisation: action.organisation, createdAt: action.createdAt, updatedAt: action.updatedAt, + deletedAt: data.deletedAt, status: action.status, dueAt: action.dueAt, completedAt: action.completedAt, @@ -196,6 +202,10 @@ router.delete( }, }); if (!action) return res.status(200).send({ ok: true }); + + action.set({ encrypted: null, encryptedEntityKey: null }); + await action.save(); + await action.destroy(); res.status(200).send({ ok: true }); diff --git a/api/src/controllers/comment.js b/api/src/controllers/comment.js index 649584e35..30d1b0b94 100644 --- a/api/src/controllers/comment.js +++ b/api/src/controllers/comment.js @@ -42,6 +42,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -71,11 +72,14 @@ router.get( const total = await Comment.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await Comment.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -119,6 +123,7 @@ router.put( organisation: newComment.organisation, createdAt: newComment.createdAt, updatedAt: newComment.updatedAt, + deletedAt: newComment.deletedAt, }, }); }) @@ -141,6 +146,9 @@ router.delete( const comment = await Comment.findOne(query); if (!comment) return res.status(200).send({ ok: true }); + comment.set({ encrypted: null, encryptedEntityKey: null }); + await comment.save(); + await comment.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/controllers/organisation.js b/api/src/controllers/organisation.js index 33e6f4995..dba09bc42 100644 --- a/api/src/controllers/organisation.js +++ b/api/src/controllers/organisation.js @@ -38,14 +38,17 @@ router.get( } const query = { where: { organisation: req.query.organisation } }; - if (Number(req.query.lastRefresh)) { - query.where.updatedAt = { [Op.gte]: new Date(Number(req.query.lastRefresh)) }; + const { lastRefresh } = req.query; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; } const places = await Place.count(query); const relsPersonPlace = await RelPersonPlace.count(query); const actions = await Action.count(query); const persons = await Person.count(query); + console.log(query, new Date(Number(lastRefresh)), persons); const comments = await Comment.count(query); const passages = await Passage.count(query); const reports = await Report.count(query); diff --git a/api/src/controllers/passage.js b/api/src/controllers/passage.js index 565840bb6..685044ea2 100644 --- a/api/src/controllers/passage.js +++ b/api/src/controllers/passage.js @@ -42,6 +42,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -71,11 +72,14 @@ router.get( const total = await Passage.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await Passage.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -120,6 +124,7 @@ router.put( organisation: newPassage.organisation, createdAt: newPassage.createdAt, updatedAt: newPassage.updatedAt, + deletedAt: newPassage.deletedAt, }, }); }) @@ -142,6 +147,9 @@ router.delete( const passage = await Passage.findOne(query); if (!passage) return res.status(200).send({ ok: true }); + passage.set({ encrypted: null, encryptedEntityKey: null }); + await passage.save(); + await passage.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/controllers/person.js b/api/src/controllers/person.js index 27366716f..b2cc0f5b1 100644 --- a/api/src/controllers/person.js +++ b/api/src/controllers/person.js @@ -153,6 +153,7 @@ router.post( organisation: p.organisation, createdAt: p.createdAt, updatedAt: p.updatedAt, + deletedAt: p.deletedAt, })), }); }) @@ -190,6 +191,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -218,13 +220,18 @@ router.get( const total = await Person.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await Person.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); + console.log({ data }); + return res.status(200).send({ ok: true, hasMore: data.length === Number(limit), @@ -272,6 +279,7 @@ router.put( organisation: newPerson.organisation, createdAt: newPerson.createdAt, updatedAt: newPerson.updatedAt, + deletedAt: newPerson.deletedAt, }, }); }) @@ -294,6 +302,8 @@ router.delete( let person = await Person.findOne(query); if (!person) return res.status(404).send({ ok: false, error: "Not Found" }); + person.set({ encrypted: null, encryptedEntityKey: null }); + await person.save(); await person.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/controllers/place.js b/api/src/controllers/place.js index de63e3d2c..d69f5b4be 100644 --- a/api/src/controllers/place.js +++ b/api/src/controllers/place.js @@ -41,6 +41,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -70,11 +71,14 @@ router.get( const total = await Place.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await Place.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -115,6 +119,7 @@ router.put( organisation: place.organisation, createdAt: place.createdAt, updatedAt: place.updatedAt, + deletedAt: place.deletedAt, }, }); }) @@ -137,6 +142,9 @@ router.delete( const place = await Place.findOne(query); if (!place) return res.status(404).send({ ok: false, error: "Not Found" }); + place.set({ encrypted: null, encryptedEntityKey: null }); + await place.save(); + await place.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/controllers/relPersonPlace.js b/api/src/controllers/relPersonPlace.js index 643a1461f..37482501b 100644 --- a/api/src/controllers/relPersonPlace.js +++ b/api/src/controllers/relPersonPlace.js @@ -42,6 +42,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -71,11 +72,14 @@ router.get( const total = await RelPersonPlace.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await RelPersonPlace.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -93,7 +97,15 @@ router.delete( error.status = 400; return next(error); } - await RelPersonPlace.destroy({ where: { _id: req.params._id, organisation: req.user.organisation } }); + const query = { where: { _id: req.params._id, organisation: req.user.organisation } }; + + const relPersonPlace = await RelPersonPlace.findOne(query); + if (!relPersonPlace) return res.status(404).send({ ok: false, error: "Not Found" }); + + relPersonPlace.set({ encrypted: null, encryptedEntityKey: null }); + await relPersonPlace.save(); + + await relPersonPlace.destroy(); res.status(200).send({ ok: true }); }) ); diff --git a/api/src/controllers/report.js b/api/src/controllers/report.js index cf79cf9de..c71b90a4f 100644 --- a/api/src/controllers/report.js +++ b/api/src/controllers/report.js @@ -30,11 +30,14 @@ router.get( const total = await Report.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await Report.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -72,6 +75,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -111,6 +115,7 @@ router.put( organisation: report.organisation, createdAt: report.createdAt, updatedAt: report.updatedAt, + deletedAt: report.deletedAt, }, }); }) @@ -133,6 +138,9 @@ router.delete( const report = await Report.findOne(query); if (!report) return res.status(200).send({ ok: true }); + report.set({ encrypted: null, encryptedEntityKey: null }); + await report.save(); + await report.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/controllers/territory.js b/api/src/controllers/territory.js index 1475474fc..45f49e133 100644 --- a/api/src/controllers/territory.js +++ b/api/src/controllers/territory.js @@ -40,6 +40,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -69,11 +70,14 @@ router.get( const total = await Territory.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await Territory.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -129,6 +133,9 @@ router.delete( const territory = await Territory.findOne(query); if (!territory) return res.status(404).send({ ok: false, error: "Not Found" }); + territory.set({ encrypted: null, encryptedEntityKey: null }); + await territory.save(); + await territory.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/controllers/territoryObservation.js b/api/src/controllers/territoryObservation.js index 06592a016..715c375f6 100644 --- a/api/src/controllers/territoryObservation.js +++ b/api/src/controllers/territoryObservation.js @@ -39,6 +39,7 @@ router.post( organisation: data.organisation, createdAt: data.createdAt, updatedAt: data.updatedAt, + deletedAt: data.deletedAt, }, }); }) @@ -68,11 +69,14 @@ router.get( const total = await TerritoryObservation.count(query); if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; - if (lastRefresh) query.where.updatedAt = { [Op.gte]: new Date(Number(lastRefresh)) }; + if (lastRefresh) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + query.paranoid = false; + } const data = await TerritoryObservation.findAll({ ...query, - attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"], + attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); return res.status(200).send({ ok: true, data, hasMore: data.length === Number(limit), total }); }) @@ -116,6 +120,7 @@ router.put( organisation: newTerritoryObservation.organisation, createdAt: newTerritoryObservation.createdAt, updatedAt: newTerritoryObservation.updatedAt, + deletedAt: newTerritoryObservation.deletedAt, }, }); }) @@ -138,6 +143,9 @@ router.delete( let observation = await TerritoryObservation.findOne(query); if (!observation) return res.status(404).send({ ok: false, error: "Not Found" }); + observation.set({ encrypted: null, encryptedEntityKey: null }); + await observation.save(); + await observation.destroy(); res.status(200).send({ ok: true }); }) diff --git a/api/src/db/migrations/2022-04-25_soft-delete.js b/api/src/db/migrations/2022-04-25_soft-delete.js new file mode 100644 index 000000000..ce038f5df --- /dev/null +++ b/api/src/db/migrations/2022-04-25_soft-delete.js @@ -0,0 +1,40 @@ +const sequelize = require("../sequelize"); + +(async () => { + await sequelize.query(` + ALTER TABLE "mano"."Action" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."Person" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."Comment" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."Place" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."Passage" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."RelPersonPlace" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."Report" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."Territory" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); + await sequelize.query(` + ALTER TABLE "mano"."TerritoryObservation" + ADD COLUMN IF NOT EXISTS "deletedAt" timestamp with time zone + `); +})(); diff --git a/api/src/db/migrations/index.js b/api/src/db/migrations/index.js index ee45714be..d345c6998 100644 --- a/api/src/db/migrations/index.js +++ b/api/src/db/migrations/index.js @@ -17,3 +17,4 @@ require("./2022-03-16-migrating"); require("./2022-03-17_user_healthcare_professional.js"); require("./2022-03-21-debug-app-dashboard-user.js"); require("./2022-03-29_add_consultations_columns.js"); +require("./2022-04-25_soft-delete.js"); diff --git a/api/src/models/action.js b/api/src/models/action.js index f1e430d9b..b3fab8909 100644 --- a/api/src/models/action.js +++ b/api/src/models/action.js @@ -16,6 +16,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -Action.init(schema, { sequelize, modelName: "Action", freezeTableName: true }); +Action.init(schema, { sequelize, modelName: "Action", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Action; diff --git a/api/src/models/comment.js b/api/src/models/comment.js index 3049e9a9a..53b685006 100644 --- a/api/src/models/comment.js +++ b/api/src/models/comment.js @@ -11,6 +11,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -Comment.init(schema, { sequelize, modelName: "Comment", freezeTableName: true }); +Comment.init(schema, { sequelize, modelName: "Comment", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Comment; diff --git a/api/src/models/passage.js b/api/src/models/passage.js index a7b74f772..7cc1bba4c 100644 --- a/api/src/models/passage.js +++ b/api/src/models/passage.js @@ -11,6 +11,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -Passage.init(schema, { sequelize, modelName: "Passage", freezeTableName: true }); +Passage.init(schema, { sequelize, modelName: "Passage", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Passage; diff --git a/api/src/models/person.js b/api/src/models/person.js index 65b8ec1c4..96d6ff0e7 100644 --- a/api/src/models/person.js +++ b/api/src/models/person.js @@ -11,6 +11,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -Person.init(schema, { sequelize, modelName: "Person", freezeTableName: true }); +Person.init(schema, { sequelize, modelName: "Person", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Person; diff --git a/api/src/models/place.js b/api/src/models/place.js index 9923af8d8..3bc4d2dda 100644 --- a/api/src/models/place.js +++ b/api/src/models/place.js @@ -12,6 +12,6 @@ const schema = { class Place extends Model {} -Place.init(schema, { sequelize, modelName: "Place", freezeTableName: true }); +Place.init(schema, { sequelize, modelName: "Place", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Place; diff --git a/api/src/models/relPersonPlace.js b/api/src/models/relPersonPlace.js index bb85d8d21..7bb949459 100644 --- a/api/src/models/relPersonPlace.js +++ b/api/src/models/relPersonPlace.js @@ -10,6 +10,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -RelPersonPlace.init(schema, { sequelize, modelName: "RelPersonPlace", freezeTableName: true }); +RelPersonPlace.init(schema, { sequelize, modelName: "RelPersonPlace", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = RelPersonPlace; diff --git a/api/src/models/report.js b/api/src/models/report.js index 226b91902..72a700231 100644 --- a/api/src/models/report.js +++ b/api/src/models/report.js @@ -10,6 +10,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -Report.init(schema, { sequelize, modelName: "Report", freezeTableName: true }); +Report.init(schema, { sequelize, modelName: "Report", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Report; diff --git a/api/src/models/territory.js b/api/src/models/territory.js index 6bf5227a0..6de8cb5b0 100644 --- a/api/src/models/territory.js +++ b/api/src/models/territory.js @@ -10,6 +10,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -Territory.init(schema, { sequelize, modelName: "Territory", freezeTableName: true }); +Territory.init(schema, { sequelize, modelName: "Territory", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = Territory; diff --git a/api/src/models/territoryObservation.js b/api/src/models/territoryObservation.js index 64d9ff5b9..0a202131d 100644 --- a/api/src/models/territoryObservation.js +++ b/api/src/models/territoryObservation.js @@ -10,6 +10,6 @@ const schema = { encryptedEntityKey: { type: DataTypes.TEXT }, }; -TerritoryObservation.init(schema, { sequelize, modelName: "TerritoryObservation", freezeTableName: true }); +TerritoryObservation.init(schema, { sequelize, modelName: "TerritoryObservation", freezeTableName: true, timestamps: true, paranoid: true }); module.exports = TerritoryObservation; From 283e7f0751e6a8cd1e647955421716e13d0420c3 Mon Sep 17 00:00:00 2001 From: Arnaud AMBROSELLI Date: Mon, 25 Apr 2022 14:40:32 +0200 Subject: [PATCH 2/4] feat(app,dashboard): remove deleted items when necessary --- app/src/services/dataManagement.js | 3 ++- dashboard/src/services/dataManagement.js | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/services/dataManagement.js b/app/src/services/dataManagement.js index 2d5899bad..e2feaf8b4 100644 --- a/app/src/services/dataManagement.js +++ b/app/src/services/dataManagement.js @@ -5,6 +5,7 @@ export const mergeNewUpdatedData = (newData, oldData) => { const oldDataIds = oldData.map((p) => p._id); const updatedItems = newData.filter((p) => oldDataIds.includes(p._id)); const newItems = newData.filter((p) => !oldDataIds.includes(p._id)); + const deletedItemsIds = newData.filter((p) => !!p.deletedAt).map((p) => p._id); return [ ...newItems, ...oldData.map((person) => { @@ -12,7 +13,7 @@ export const mergeNewUpdatedData = (newData, oldData) => { if (updatedItem) return updatedItem; return person; }), - ]; + ].filter((p) => !deletedItemsIds.includes(p._id)); }; export const MMKV = new MMKVStorage.Loader().initialize(); diff --git a/dashboard/src/services/dataManagement.js b/dashboard/src/services/dataManagement.js index 3919ca887..a59e905ae 100644 --- a/dashboard/src/services/dataManagement.js +++ b/dashboard/src/services/dataManagement.js @@ -6,6 +6,8 @@ export const mergeNewUpdatedData = (newData, oldData) => { const oldDataIds = oldData.map((p) => p._id); const updatedItems = newData.filter((p) => oldDataIds.includes(p._id)); const newItems = newData.filter((p) => !oldDataIds.includes(p._id)); + const deletedItemsIds = newData.filter((p) => !!p.deletedAt).map((p) => p._id); + return [ ...newItems, ...oldData.map((person) => { @@ -13,7 +15,7 @@ export const mergeNewUpdatedData = (newData, oldData) => { if (updatedItem) return updatedItem; return person; }), - ]; + ].filter((p) => !deletedItemsIds.includes(p._id)); }; // export const useStorage = (key, defaultValue) => { From 76ee90bbe304eb41cf9965c24b2270ce3ba65d59 Mon Sep 17 00:00:00 2001 From: Arnaud AMBROSELLI Date: Mon, 25 Apr 2022 15:25:06 +0200 Subject: [PATCH 3/4] fix: clean --- api/src/controllers/action.js | 13 ++++++++++--- api/src/controllers/comment.js | 11 ++++++++--- api/src/controllers/organisation.js | 10 +++++++--- api/src/controllers/passage.js | 11 ++++++++--- api/src/controllers/person.js | 13 ++++++++----- api/src/controllers/place.js | 11 ++++++++--- api/src/controllers/relPersonPlace.js | 11 ++++++++--- api/src/controllers/report.js | 11 ++++++++--- api/src/controllers/territory.js | 11 ++++++++--- api/src/controllers/territoryObservation.js | 11 ++++++++--- app/src/components/Loader.js | 2 +- app/src/services/dataManagement.js | 17 +++++++++++++++-- dashboard/src/services/dataManagement.js | 10 ++++++++-- 13 files changed, 105 insertions(+), 37 deletions(-) diff --git a/api/src/controllers/action.js b/api/src/controllers/action.js index 473ba729f..f23ce52f3 100644 --- a/api/src/controllers/action.js +++ b/api/src/controllers/action.js @@ -70,12 +70,14 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.updatedAfter); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.deletedAfter); } catch (e) { const error = new Error(`Invalid request in action get: ${e}`); error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -90,8 +92,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const sortDoneOrCancel = (a, b) => { diff --git a/api/src/controllers/comment.js b/api/src/controllers/comment.js index 30d1b0b94..e62f4025d 100644 --- a/api/src/controllers/comment.js +++ b/api/src/controllers/comment.js @@ -62,7 +62,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -73,8 +73,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await Comment.findAll({ diff --git a/api/src/controllers/organisation.js b/api/src/controllers/organisation.js index dba09bc42..f0a5f1317 100644 --- a/api/src/controllers/organisation.js +++ b/api/src/controllers/organisation.js @@ -40,15 +40,19 @@ router.get( const query = { where: { organisation: req.query.organisation } }; const { lastRefresh } = req.query; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const places = await Place.count(query); const relsPersonPlace = await RelPersonPlace.count(query); const actions = await Action.count(query); const persons = await Person.count(query); - console.log(query, new Date(Number(lastRefresh)), persons); const comments = await Comment.count(query); const passages = await Passage.count(query); const reports = await Report.count(query); diff --git a/api/src/controllers/passage.js b/api/src/controllers/passage.js index 685044ea2..79e7f0132 100644 --- a/api/src/controllers/passage.js +++ b/api/src/controllers/passage.js @@ -62,7 +62,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -73,8 +73,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await Passage.findAll({ diff --git a/api/src/controllers/person.js b/api/src/controllers/person.js index b2cc0f5b1..9497b11f8 100644 --- a/api/src/controllers/person.js +++ b/api/src/controllers/person.js @@ -211,7 +211,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -221,8 +221,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await Person.findAll({ @@ -230,8 +235,6 @@ router.get( attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"], }); - console.log({ data }); - return res.status(200).send({ ok: true, hasMore: data.length === Number(limit), diff --git a/api/src/controllers/place.js b/api/src/controllers/place.js index d69f5b4be..f27872357 100644 --- a/api/src/controllers/place.js +++ b/api/src/controllers/place.js @@ -61,7 +61,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -72,8 +72,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await Place.findAll({ diff --git a/api/src/controllers/relPersonPlace.js b/api/src/controllers/relPersonPlace.js index 37482501b..7e20f5122 100644 --- a/api/src/controllers/relPersonPlace.js +++ b/api/src/controllers/relPersonPlace.js @@ -62,7 +62,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -73,8 +73,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await RelPersonPlace.findAll({ diff --git a/api/src/controllers/report.js b/api/src/controllers/report.js index c71b90a4f..9952d59c5 100644 --- a/api/src/controllers/report.js +++ b/api/src/controllers/report.js @@ -23,7 +23,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation } }; @@ -31,8 +31,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await Report.findAll({ diff --git a/api/src/controllers/territory.js b/api/src/controllers/territory.js index 45f49e133..00d82d3a0 100644 --- a/api/src/controllers/territory.js +++ b/api/src/controllers/territory.js @@ -60,7 +60,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -71,8 +71,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await Territory.findAll({ diff --git a/api/src/controllers/territoryObservation.js b/api/src/controllers/territoryObservation.js index 715c375f6..b3235ad7b 100644 --- a/api/src/controllers/territoryObservation.js +++ b/api/src/controllers/territoryObservation.js @@ -59,7 +59,7 @@ router.get( error.status = 400; return next(error); } - const { limit, page, lastRefresh } = req.query; + const { limit, page, lastRefresh, after, withDeleted } = req.query; const query = { where: { organisation: req.user.organisation }, @@ -70,8 +70,13 @@ router.get( if (limit) query.limit = Number(limit); if (page) query.offset = Number(page) * limit; if (lastRefresh) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }, { deletedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; - query.paranoid = false; + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; + } + if (withDeleted === true) query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted) { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + } else if (after && !isNaN(Number(after))) { + query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } const data = await TerritoryObservation.findAll({ diff --git a/app/src/components/Loader.js b/app/src/components/Loader.js index 570565b1c..481f57893 100644 --- a/app/src/components/Loader.js +++ b/app/src/components/Loader.js @@ -55,7 +55,7 @@ const mergeItems = (oldItems, newItems) => { const Loader = () => { const [picture, setPicture] = useState([picture1, picture3, picture2][randomIntFromInterval(0, 2)]); - const [lastRefresh, setLastRefresh] = useStorage('last-refresh', 0); + const [lastRefresh, setLastRefresh] = useStorage('last-refresh--cache-version-2022-04-25', null); const [loading, setLoading] = useRecoilState(loadingState); const [progress, setProgress] = useRecoilState(progressState); const [fullScreen, setFullScreen] = useRecoilState(loaderFullScreenState); diff --git a/app/src/services/dataManagement.js b/app/src/services/dataManagement.js index e2feaf8b4..c015022b7 100644 --- a/app/src/services/dataManagement.js +++ b/app/src/services/dataManagement.js @@ -29,12 +29,25 @@ export function clearCache() { } // Get data from cache or fetch from server. -export async function getData({ collectionName, data = [], isInitialization = false, setProgress = () => {}, setBatchData = null, lastRefresh = 0 }) { +export async function getData({ + collectionName, + data = [], + isInitialization = false, + setProgress = () => {}, + setBatchData = null, + lastRefresh = null, +}) { if (isInitialization) { data = (await MMKV.getMapAsync(collectionName)) || []; } - const response = await API.get({ path: `/${collectionName}`, batch: 1000, setProgress, query: { lastRefresh }, setBatchData }); + const response = await API.get({ + path: `/${collectionName}`, + batch: 1000, + setProgress, + query: { after: lastRefresh, withDeleted: Boolean(lastRefresh) }, + setBatchData, + }); if (!response.ok) throw { message: `Error getting ${collectionName} data`, response }; // avoid sending data if no new data, to avoid big useless `map` calculations in selectors diff --git a/dashboard/src/services/dataManagement.js b/dashboard/src/services/dataManagement.js index a59e905ae..4864a23f5 100644 --- a/dashboard/src/services/dataManagement.js +++ b/dashboard/src/services/dataManagement.js @@ -39,9 +39,15 @@ export async function getData({ isInitialization = false, setProgress = () => {}, setBatchData = null, - lastRefresh = 0, + lastRefresh = null, }) { - const response = await API.get({ path: `/${collectionName}`, batch: 1000, setProgress, query: { lastRefresh }, setBatchData }); + const response = await API.get({ + path: `/${collectionName}`, + batch: 1000, + setProgress, + query: { after: lastRefresh, withDeleted: Boolean(lastRefresh) }, + setBatchData, + }); if (!response.ok) console.log({ message: `Error getting ${collectionName} data`, response }); if (response.ok && response.decryptedData && response.decryptedData.length) { data = mergeNewUpdatedData(response.decryptedData, data); From d3c5122cd0dfac2dea727183381c3cbc5f0c87c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Huchet?= Date: Tue, 26 Apr 2022 10:10:26 +0200 Subject: [PATCH 4/4] fix: fix --- api/src/controllers/action.js | 10 +++++----- api/src/controllers/comment.js | 8 +++++--- api/src/controllers/organisation.js | 10 ++++++---- api/src/controllers/passage.js | 8 +++++--- api/src/controllers/person.js | 8 +++++--- api/src/controllers/place.js | 8 +++++--- api/src/controllers/relPersonPlace.js | 8 +++++--- api/src/controllers/report.js | 8 +++++--- api/src/controllers/territory.js | 8 +++++--- api/src/controllers/territoryObservation.js | 8 +++++--- 10 files changed, 51 insertions(+), 33 deletions(-) diff --git a/api/src/controllers/action.js b/api/src/controllers/action.js index f23ce52f3..c2956f8cb 100644 --- a/api/src/controllers/action.js +++ b/api/src/controllers/action.js @@ -70,8 +70,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); - z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.updatedAfter); - z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.deletedAfter); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in action get: ${e}`); error.status = 400; @@ -94,9 +94,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/comment.js b/api/src/controllers/comment.js index e62f4025d..5302203cb 100644 --- a/api/src/controllers/comment.js +++ b/api/src/controllers/comment.js @@ -57,6 +57,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in comment get: ${e}`); error.status = 400; @@ -75,9 +77,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/organisation.js b/api/src/controllers/organisation.js index f0a5f1317..a2be34172 100644 --- a/api/src/controllers/organisation.js +++ b/api/src/controllers/organisation.js @@ -31,6 +31,8 @@ router.get( try { z.string().regex(looseUuidRegex).parse(req.query.organisation); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in stats get: ${e}`); error.status = 400; @@ -38,13 +40,13 @@ router.get( } const query = { where: { organisation: req.query.organisation } }; - const { lastRefresh } = req.query; + const { lastRefresh, after, withDeleted } = req.query; if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/passage.js b/api/src/controllers/passage.js index 79e7f0132..4d821e696 100644 --- a/api/src/controllers/passage.js +++ b/api/src/controllers/passage.js @@ -57,6 +57,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in passage get: ${e}`); error.status = 400; @@ -75,9 +77,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/person.js b/api/src/controllers/person.js index 9497b11f8..61af85ab8 100644 --- a/api/src/controllers/person.js +++ b/api/src/controllers/person.js @@ -206,6 +206,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in person get: ${e}`); error.status = 400; @@ -223,9 +225,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/place.js b/api/src/controllers/place.js index f27872357..2872a84b9 100644 --- a/api/src/controllers/place.js +++ b/api/src/controllers/place.js @@ -56,6 +56,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in place get: ${e}`); error.status = 400; @@ -74,9 +76,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/relPersonPlace.js b/api/src/controllers/relPersonPlace.js index 7e20f5122..6cc55ec87 100644 --- a/api/src/controllers/relPersonPlace.js +++ b/api/src/controllers/relPersonPlace.js @@ -57,6 +57,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in relPersonPlace get: ${e}`); error.status = 400; @@ -75,9 +77,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/report.js b/api/src/controllers/report.js index 9952d59c5..7607d0638 100644 --- a/api/src/controllers/report.js +++ b/api/src/controllers/report.js @@ -18,6 +18,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in report get: ${e}`); error.status = 400; @@ -33,9 +35,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/territory.js b/api/src/controllers/territory.js index 00d82d3a0..c0cae656e 100644 --- a/api/src/controllers/territory.js +++ b/api/src/controllers/territory.js @@ -55,6 +55,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in territory get: ${e}`); error.status = 400; @@ -73,9 +75,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; } diff --git a/api/src/controllers/territoryObservation.js b/api/src/controllers/territoryObservation.js index b3235ad7b..d010b3185 100644 --- a/api/src/controllers/territoryObservation.js +++ b/api/src/controllers/territoryObservation.js @@ -54,6 +54,8 @@ router.get( z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.limit); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.page); z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.lastRefresh); + z.optional(z.enum(["true", "false"])).parse(req.query.withDeleted); + z.optional(z.string().regex(positiveIntegerRegex)).parse(req.query.after); } catch (e) { const error = new Error(`Invalid request in observation get: ${e}`); error.status = 400; @@ -72,9 +74,9 @@ router.get( if (lastRefresh) { query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(lastRefresh)) } }]; } - if (withDeleted === true) query.paranoid = false; - if (after && !isNaN(Number(after)) && withDeleted) { - query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(deletedAfter)) } }]; + if (withDeleted === "true") query.paranoid = false; + if (after && !isNaN(Number(after)) && withDeleted === "true") { + query.where[Op.or] = [{ updatedAt: { [Op.gte]: new Date(Number(after)) } }, { deletedAt: { [Op.gte]: new Date(Number(after)) } }]; } else if (after && !isNaN(Number(after))) { query.where.updatedAt = { [Op.gte]: new Date(Number(after)) }; }