fix: Outdated updatedBy returned in document mutations (#7223)

* fix: Outdated updatedBy information returned in document mutations

* tsc

* Update delete mutations to match
This commit is contained in:
Tom Moor
2024-07-10 20:41:30 -04:00
committed by GitHub
parent 0d0932a6f6
commit e7d3dac36c
8 changed files with 94 additions and 88 deletions
+1 -1
View File
@@ -244,7 +244,7 @@ async function provisionFirstCollection(team: Team, user: User) {
document.content = await DocumentHelper.toJSON(document);
await document.publish(collection.createdById, collection.id, {
await document.publish(user, collection.id, {
transaction,
});
}
+1 -1
View File
@@ -152,7 +152,7 @@ export default async function documentCreator({
throw new Error("Collection ID is required to publish");
}
await document.publish(user.id, collectionId, { transaction });
await document.publish(user, collectionId, { transaction });
await Event.create(
{
name: "documents.publish",
+2 -1
View File
@@ -110,7 +110,7 @@ export default async function documentUpdater({
if (!document.collectionId) {
document.collectionId = cId;
}
await document.publish(user.id, cId, { transaction });
await document.publish(user, cId, { transaction });
await Event.create(
{
@@ -121,6 +121,7 @@ export default async function documentUpdater({
);
} else if (changed) {
document.lastModifiedById = user.id;
document.updatedBy = user;
await document.save({ transaction });
await Event.create(event, { transaction });
+4 -4
View File
@@ -40,7 +40,7 @@ describe("#delete", () => {
test("should soft delete and set last modified", async () => {
const document = await buildDocument();
const user = await buildUser();
await document.delete(user.id);
await document.delete(user);
const newDocument = await Document.findByPk(document.id, {
paranoid: false,
@@ -54,7 +54,7 @@ describe("#delete", () => {
template: true,
});
const user = await buildUser();
await document.delete(user.id);
await document.delete(user);
const newDocument = await Document.findByPk(document.id, {
paranoid: false,
});
@@ -67,7 +67,7 @@ describe("#delete", () => {
archivedAt: new Date(),
});
const user = await buildUser();
await document.delete(user.id);
await document.delete(user);
const newDocument = await Document.findByPk(document.id, {
paranoid: false,
});
@@ -78,7 +78,7 @@ describe("#delete", () => {
it("should delete draft without collection", async () => {
const user = await buildUser();
const document = await buildDraftDocument();
await document.delete(user.id);
await document.delete(user);
const deletedDocument = await Document.findByPk(document.id, {
paranoid: false,
});
+50 -50
View File
@@ -808,37 +808,8 @@ class Document extends ParanoidModel<
return findAllChildDocumentIds(this.id);
};
archiveWithChildren = async (
userId: string,
options?: FindOptions<Document>
) => {
const archivedAt = new Date();
// Helper to archive all child documents for a document
const archiveChildren = async (parentDocumentId: string) => {
const childDocuments = await (
this.constructor as typeof Document
).findAll({
where: {
parentDocumentId,
},
});
for (const child of childDocuments) {
await archiveChildren(child.id);
child.archivedAt = archivedAt;
child.lastModifiedById = userId;
await child.save(options);
}
};
await archiveChildren(this.id);
this.archivedAt = archivedAt;
this.lastModifiedById = userId;
return this.save(options);
};
publish = async (
userId: string,
user: User,
collectionId: string,
{ transaction }: SaveOptions<Document>
) => {
@@ -890,7 +861,8 @@ class Document extends ParanoidModel<
)
);
this.lastModifiedById = userId;
this.lastModifiedById = user.id;
this.updatedBy = user;
this.publishedAt = new Date();
return this.save({ transaction });
};
@@ -911,9 +883,8 @@ class Document extends ParanoidModel<
return false;
};
unpublish = async (userId: string) => {
// If the document is already a draft then calling unpublish should act like
// a regular save
unpublish = async (user: User) => {
// If the document is already a draft then calling unpublish should act like save
if (!this.publishedAt) {
return this.save();
}
@@ -934,15 +905,17 @@ class Document extends ParanoidModel<
// unpublishing a document converts the ownership to yourself, so that it
// will appear in your drafts rather than the original creators
this.createdById = userId;
this.lastModifiedById = userId;
this.createdById = user.id;
this.lastModifiedById = user.id;
this.createdBy = user;
this.updatedBy = user;
this.publishedAt = null;
return this.save();
};
// Moves a document from being visible to the team within a collection
// to the archived area, where it can be subsequently restored.
archive = async (userId: string) => {
archive = async (user: User) => {
await this.sequelize.transaction(async (transaction: Transaction) => {
const collection = this.collectionId
? await Collection.findByPk(this.collectionId, {
@@ -957,12 +930,12 @@ class Document extends ParanoidModel<
}
});
await this.archiveWithChildren(userId);
await this.archiveWithChildren(user);
return this;
};
// Restore an archived document back to being visible to the team
unarchive = async (userId: string) => {
unarchive = async (user: User) => {
await this.sequelize.transaction(async (transaction: Transaction) => {
const collection = this.collectionId
? await Collection.findByPk(this.collectionId, {
@@ -997,13 +970,14 @@ class Document extends ParanoidModel<
}
this.archivedAt = null;
this.lastModifiedById = userId;
this.lastModifiedById = user.id;
this.updatedBy = user;
await this.save();
return this;
};
// Delete a document, archived or otherwise.
delete = (userId: string) =>
delete = (user: User) =>
this.sequelize.transaction(async (transaction: Transaction) => {
if (!this.archivedAt && !this.template && this.collectionId) {
// delete any children and remove from the document structure
@@ -1025,15 +999,10 @@ class Document extends ParanoidModel<
},
transaction,
});
await this.update(
{
lastModifiedById: userId,
},
{
transaction,
}
);
return this;
this.lastModifiedById = user.id;
this.updatedBy = user;
return this.save({ transaction });
});
getTimestamp = () => Math.round(new Date(this.updatedAt).getTime() / 1000);
@@ -1098,6 +1067,37 @@ class Document extends ParanoidModel<
children,
};
};
private archiveWithChildren = async (
user: User,
options?: FindOptions<Document>
) => {
const archivedAt = new Date();
// Helper to archive all child documents for a document
const archiveChildren = async (parentDocumentId: string) => {
const childDocuments = await (
this.constructor as typeof Document
).findAll({
where: {
parentDocumentId,
},
});
for (const child of childDocuments) {
await archiveChildren(child.id);
child.archivedAt = archivedAt;
child.lastModifiedById = user.id;
child.updatedBy = user;
await child.save(options);
}
};
await archiveChildren(this.id);
this.archivedAt = archivedAt;
this.lastModifiedById = user.id;
this.updatedBy = user;
return this.save(options);
};
}
export default Document;
+29 -24
View File
@@ -87,7 +87,7 @@ describe("#documents.info", () => {
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.info", {
body: {
token: user.getJwtToken(),
@@ -433,7 +433,7 @@ describe("#documents.info", () => {
teamId: document.teamId,
userId: user.id,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.info", {
body: {
shareId: share.id,
@@ -607,7 +607,7 @@ describe("#documents.export", () => {
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.export", {
body: {
token: user.getJwtToken(),
@@ -1638,7 +1638,7 @@ describe("#documents.search", () => {
text: "search term",
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.search", {
body: {
token: user.getJwtToken(),
@@ -1658,7 +1658,7 @@ describe("#documents.search", () => {
text: "search term",
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.search", {
body: {
token: user.getJwtToken(),
@@ -1938,7 +1938,7 @@ describe("#documents.archived", () => {
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.archived", {
body: {
token: user.getJwtToken(),
@@ -1955,7 +1955,7 @@ describe("#documents.archived", () => {
userId: user.id,
teamId: user.teamId,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/documents.archived", {
body: {
token: user.getJwtToken(),
@@ -1975,7 +1975,7 @@ describe("#documents.archived", () => {
teamId: user.teamId,
collectionId: collection.id,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.archived", {
body: {
token: user.getJwtToken(),
@@ -2009,7 +2009,7 @@ describe("#documents.deleted", () => {
userId: user.id,
teamId: user.teamId,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/documents.deleted", {
body: {
token: user.getJwtToken(),
@@ -2041,9 +2041,9 @@ describe("#documents.deleted", () => {
collectionId: null,
});
await Promise.all([
document.delete(user.id),
draftDocument.delete(user.id),
otherUserDraft.delete(user2.id),
document.delete(user),
draftDocument.delete(user),
otherUserDraft.delete(user2),
]);
const res = await server.post("/api/documents.deleted", {
body: {
@@ -2067,7 +2067,7 @@ describe("#documents.deleted", () => {
teamId: user.teamId,
collectionId: collection.id,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/documents.deleted", {
body: {
token: user.getJwtToken(),
@@ -2476,7 +2476,7 @@ describe("#documents.restore", () => {
userId: user.id,
teamId: user.teamId,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/documents.restore", {
body: {
token: user.getJwtToken(),
@@ -2560,7 +2560,7 @@ describe("#documents.restore", () => {
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.restore", {
body: {
token: user.getJwtToken(),
@@ -2584,8 +2584,8 @@ describe("#documents.restore", () => {
collectionId: document.collectionId,
parentDocumentId: document.id,
});
await childDocument.archive(user.id);
await document.archive(user.id);
await childDocument.archive(user);
await document.archive(user);
const res = await server.post("/api/documents.restore", {
body: {
token: user.getJwtToken(),
@@ -3286,7 +3286,7 @@ describe("#documents.update", () => {
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.update", {
body: {
token: user.getJwtToken(),
@@ -3594,9 +3594,10 @@ describe("#documents.archive", () => {
});
it("should allow archiving document", async () => {
const user = await buildUser();
const admin = await buildAdmin();
const user = await buildUser({ teamId: admin.teamId });
const document = await buildDocument({
userId: user.id,
userId: admin.id,
teamId: user.teamId,
});
const res = await server.post("/api/documents.archive", {
@@ -3800,6 +3801,8 @@ describe("#documents.unpublish", () => {
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
expect(body.data.publishedAt).toBeNull();
expect(body.data.createdBy.id).toEqual(user.id);
expect(body.data.updatedBy.id).toEqual(user.id);
const reloaded = await Document.unscoped().findByPk(document.id);
expect(reloaded!.createdById).toEqual(user.id);
@@ -3816,7 +3819,7 @@ describe("#documents.unpublish", () => {
teamId: user.teamId,
parentDocumentId: document.id,
});
await child.archive(user.id);
await child.archive(user);
const res = await server.post("/api/documents.unpublish", {
body: {
token: user.getJwtToken(),
@@ -3827,6 +3830,7 @@ describe("#documents.unpublish", () => {
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
expect(body.data.publishedAt).toBeNull();
expect(body.data.updatedBy.id).toEqual(user.id);
});
it("should unpublish another users document", async () => {
@@ -3850,6 +3854,7 @@ describe("#documents.unpublish", () => {
expect(res.status).toEqual(200);
expect(body.data.id).toEqual(document.id);
expect(body.data.publishedAt).toBeNull();
expect(body.data.updatedBy.id).toEqual(user.id);
const reloaded = await Document.unscoped().findByPk(document.id);
expect(reloaded!.createdById).toEqual(user.id);
@@ -3876,7 +3881,7 @@ describe("#documents.unpublish", () => {
userId: user.id,
teamId: user.teamId,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/documents.unpublish", {
body: {
token: user.getJwtToken(),
@@ -3892,7 +3897,7 @@ describe("#documents.unpublish", () => {
userId: user.id,
teamId: user.teamId,
});
await document.archive(user.id);
await document.archive(user);
const res = await server.post("/api/documents.unpublish", {
body: {
token: user.getJwtToken(),
@@ -4496,7 +4501,7 @@ describe("#documents.empty_trash", () => {
userId: user.id,
teamId: user.teamId,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/documents.empty_trash", {
body: {
+5 -5
View File
@@ -681,7 +681,7 @@ router.post(
if (document.deletedAt) {
authorize(user, "restore", document);
// restore a previously deleted document
await document.unarchive(user.id);
await document.unarchive(user);
await Event.createFromContext(ctx, {
name: "documents.restore",
documentId: document.id,
@@ -693,7 +693,7 @@ router.post(
} else if (document.archivedAt) {
authorize(user, "unarchive", document);
// restore a previously archived document
await document.unarchive(user.id);
await document.unarchive(user);
await Event.createFromContext(ctx, {
name: "documents.unarchive",
documentId: document.id,
@@ -1182,7 +1182,7 @@ router.post(
});
authorize(user, "archive", document);
await document.archive(user.id);
await document.archive(user);
await Event.createFromContext(ctx, {
name: "documents.archive",
documentId: document.id,
@@ -1230,7 +1230,7 @@ router.post(
authorize(user, "delete", document);
await document.delete(user.id);
await document.delete(user);
await Event.createFromContext(ctx, {
name: "documents.delete",
documentId: document.id,
@@ -1271,7 +1271,7 @@ router.post(
);
}
await document.unpublish(user.id);
await document.unpublish(user);
await Event.createFromContext(ctx, {
name: "documents.unpublish",
documentId: document.id,
+2 -2
View File
@@ -111,7 +111,7 @@ describe("#shares.list", () => {
teamId: user.teamId,
userId: user.id,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/shares.list", {
body: {
token: user.getJwtToken(),
@@ -966,7 +966,7 @@ describe("#shares.revoke", () => {
teamId: user.teamId,
userId: user.id,
});
await document.delete(user.id);
await document.delete(user);
const res = await server.post("/api/shares.revoke", {
body: {
token: user.getJwtToken(),