Skip to content

Commit

Permalink
feat: soft delete (#642)
Browse files Browse the repository at this point in the history
* feat(api): set deletedAt in all data models + update lastRefresh to fetch also data related to deletedAt

* feat(app,dashboard): remove deleted items when necessary

* fix: clean

* fix: fix

Co-authored-by: Raphaël Huchet <[email protected]>
  • Loading branch information
arnaudambro and rap2hpoutre authored Apr 26, 2022
1 parent 03c4075 commit 2998209
Show file tree
Hide file tree
Showing 24 changed files with 257 additions and 45 deletions.
21 changes: 19 additions & 2 deletions api/src/controllers/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -69,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.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;
return next(error);
}
const { limit, page, lastRefresh } = req.query;
const { limit, page, lastRefresh, after, withDeleted } = req.query;

const query = {
where: { organisation: req.user.organisation },
Expand All @@ -88,7 +91,15 @@ 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)) } }];
}
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)) };
}

const sortDoneOrCancel = (a, b) => {
if (!a.dueAt) return -1;
Expand All @@ -107,6 +118,7 @@ router.get(
"organisation",
"createdAt",
"updatedAt",
"deletedAt",
// Specific fields that are not encrypted
"status",
"dueAt",
Expand Down Expand Up @@ -168,6 +180,7 @@ router.put(
organisation: action.organisation,
createdAt: action.createdAt,
updatedAt: action.updatedAt,
deletedAt: data.deletedAt,
status: action.status,
dueAt: action.dueAt,
completedAt: action.completedAt,
Expand Down Expand Up @@ -196,6 +209,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 });
Expand Down
21 changes: 18 additions & 3 deletions api/src/controllers/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ router.post(
organisation: data.organisation,
createdAt: data.createdAt,
updatedAt: data.updatedAt,
deletedAt: data.deletedAt,
},
});
})
Expand All @@ -56,12 +57,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.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;
return next(error);
}
const { limit, page, lastRefresh } = req.query;
const { limit, page, lastRefresh, after, withDeleted } = req.query;

const query = {
where: { organisation: req.user.organisation },
Expand All @@ -71,11 +74,19 @@ 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)) } }];
}
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)) };
}

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 });
})
Expand Down Expand Up @@ -119,6 +130,7 @@ router.put(
organisation: newComment.organisation,
createdAt: newComment.createdAt,
updatedAt: newComment.updatedAt,
deletedAt: newComment.deletedAt,
},
});
})
Expand All @@ -141,6 +153,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 });
})
Expand Down
13 changes: 11 additions & 2 deletions api/src/controllers/organisation.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,24 @@ 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;
return next(error);
}

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, 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 === "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)) };
}

const places = await Place.count(query);
Expand Down
21 changes: 18 additions & 3 deletions api/src/controllers/passage.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ router.post(
organisation: data.organisation,
createdAt: data.createdAt,
updatedAt: data.updatedAt,
deletedAt: data.deletedAt,
},
});
})
Expand All @@ -56,12 +57,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.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;
return next(error);
}
const { limit, page, lastRefresh } = req.query;
const { limit, page, lastRefresh, after, withDeleted } = req.query;

const query = {
where: { organisation: req.user.organisation },
Expand All @@ -71,11 +74,19 @@ 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)) } }];
}
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)) };
}

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 });
})
Expand Down Expand Up @@ -120,6 +131,7 @@ router.put(
organisation: newPassage.organisation,
createdAt: newPassage.createdAt,
updatedAt: newPassage.updatedAt,
deletedAt: newPassage.deletedAt,
},
});
})
Expand All @@ -142,6 +154,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 });
})
Expand Down
21 changes: 18 additions & 3 deletions api/src/controllers/person.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ router.post(
organisation: p.organisation,
createdAt: p.createdAt,
updatedAt: p.updatedAt,
deletedAt: p.deletedAt,
})),
});
})
Expand Down Expand Up @@ -190,6 +191,7 @@ router.post(
organisation: data.organisation,
createdAt: data.createdAt,
updatedAt: data.updatedAt,
deletedAt: data.deletedAt,
},
});
})
Expand All @@ -204,12 +206,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.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;
return next(error);
}
const { limit, page, lastRefresh } = req.query;
const { limit, page, lastRefresh, after, withDeleted } = req.query;

const query = {
where: { organisation: req.user.organisation },
Expand All @@ -218,11 +222,19 @@ 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)) } }];
}
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)) };
}

const data = await Person.findAll({
...query,
attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt"],
attributes: ["_id", "encrypted", "encryptedEntityKey", "organisation", "createdAt", "updatedAt", "deletedAt"],
});

return res.status(200).send({
Expand Down Expand Up @@ -272,6 +284,7 @@ router.put(
organisation: newPerson.organisation,
createdAt: newPerson.createdAt,
updatedAt: newPerson.updatedAt,
deletedAt: newPerson.deletedAt,
},
});
})
Expand All @@ -294,6 +307,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 });
})
Expand Down
21 changes: 18 additions & 3 deletions api/src/controllers/place.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ router.post(
organisation: data.organisation,
createdAt: data.createdAt,
updatedAt: data.updatedAt,
deletedAt: data.deletedAt,
},
});
})
Expand All @@ -55,12 +56,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.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;
return next(error);
}
const { limit, page, lastRefresh } = req.query;
const { limit, page, lastRefresh, after, withDeleted } = req.query;

const query = {
where: { organisation: req.user.organisation },
Expand All @@ -70,11 +73,19 @@ 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)) } }];
}
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)) };
}

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 });
})
Expand Down Expand Up @@ -115,6 +126,7 @@ router.put(
organisation: place.organisation,
createdAt: place.createdAt,
updatedAt: place.updatedAt,
deletedAt: place.deletedAt,
},
});
})
Expand All @@ -137,6 +149,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 });
})
Expand Down
Loading

0 comments on commit 2998209

Please sign in to comment.