Merge main
This commit is contained in:
@@ -38,7 +38,7 @@ const { authorize, cannot } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
const {
|
||||
let {
|
||||
sort = "updatedAt",
|
||||
template,
|
||||
backlinkDocumentId,
|
||||
@@ -71,6 +71,7 @@ router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
where = { ...where, createdById };
|
||||
}
|
||||
|
||||
let documentIds = [];
|
||||
// if a specific collection is passed then we need to check auth to view it
|
||||
if (collectionId) {
|
||||
ctx.assertUuid(collectionId, "collection must be a UUID");
|
||||
@@ -81,6 +82,15 @@ router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
}).findByPk(collectionId);
|
||||
authorize(user, "read", collection);
|
||||
|
||||
// index sort is special because it uses the order of the documents in the
|
||||
// collection.documentStructure rather than a database column
|
||||
if (sort === "index") {
|
||||
documentIds = collection.documentStructure
|
||||
.map((node) => node.id)
|
||||
.slice(ctx.state.pagination.offset, ctx.state.pagination.limit);
|
||||
where = { ...where, id: documentIds };
|
||||
}
|
||||
|
||||
// otherwise, filter by all collections the user has access to
|
||||
} else {
|
||||
const collectionIds = await user.collectionIds();
|
||||
@@ -92,6 +102,12 @@ router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
where = { ...where, parentDocumentId };
|
||||
}
|
||||
|
||||
// Explicitly passing 'null' as the parentDocumentId allows listing documents
|
||||
// that have no parent document (aka they are at the root of the collection)
|
||||
if (parentDocumentId === null) {
|
||||
where = { ...where, parentDocumentId: { [Op.eq]: null } };
|
||||
}
|
||||
|
||||
if (backlinkDocumentId) {
|
||||
ctx.assertUuid(backlinkDocumentId, "backlinkDocumentId must be a UUID");
|
||||
|
||||
@@ -108,6 +124,10 @@ router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
};
|
||||
}
|
||||
|
||||
if (sort === "index") {
|
||||
sort = "updatedAt";
|
||||
}
|
||||
|
||||
// add the users starred state to the response by default
|
||||
const starredScope = { method: ["withStarred", user.id] };
|
||||
const collectionScope = { method: ["withCollection", user.id] };
|
||||
@@ -124,6 +144,14 @@ router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||
limit: ctx.state.pagination.limit,
|
||||
});
|
||||
|
||||
// index sort is special because it uses the order of the documents in the
|
||||
// collection.documentStructure rather than a database column
|
||||
if (documentIds.length) {
|
||||
documents.sort(
|
||||
(a, b) => documentIds.indexOf(a.id) - documentIds.indexOf(b.id)
|
||||
);
|
||||
}
|
||||
|
||||
const data = await Promise.all(
|
||||
documents.map((document) => presentDocument(document))
|
||||
);
|
||||
@@ -523,18 +551,27 @@ router.post("documents.restore", auth(), async (ctx) => {
|
||||
throw new NotFoundError();
|
||||
}
|
||||
|
||||
// Passing collectionId allows restoring to a different collection than the
|
||||
// document was originally within
|
||||
if (collectionId) {
|
||||
ctx.assertUuid(collectionId, "collectionId must be a uuid");
|
||||
authorize(user, "restore", document);
|
||||
|
||||
const collection = await Collection.scope({
|
||||
method: ["withMembership", user.id],
|
||||
}).findByPk(collectionId);
|
||||
authorize(user, "update", collection);
|
||||
|
||||
document.collectionId = collectionId;
|
||||
}
|
||||
|
||||
const collection = await Collection.scope({
|
||||
method: ["withMembership", user.id],
|
||||
}).findByPk(document.collectionId);
|
||||
|
||||
// if the collectionId was provided in the request and isn't valid then it will
|
||||
// be caught as a 403 on the authorize call below. Otherwise we're checking here
|
||||
// that the original collection still exists and advising to pass collectionId
|
||||
// if not.
|
||||
if (!collectionId) {
|
||||
ctx.assertPresent(collection, "collectionId is required");
|
||||
}
|
||||
|
||||
authorize(user, "update", collection);
|
||||
|
||||
if (document.deletedAt) {
|
||||
authorize(user, "restore", document);
|
||||
|
||||
@@ -910,7 +947,7 @@ router.post("documents.update", auth(), async (ctx) => {
|
||||
transaction = await sequelize.transaction();
|
||||
|
||||
if (publish) {
|
||||
await document.publish({ transaction });
|
||||
await document.publish(user.id, { transaction });
|
||||
} else {
|
||||
await document.save({ autosave, transaction });
|
||||
}
|
||||
@@ -1087,7 +1124,7 @@ router.post("documents.unpublish", auth(), async (ctx) => {
|
||||
|
||||
authorize(user, "unpublish", document);
|
||||
|
||||
await document.unpublish();
|
||||
await document.unpublish(user.id);
|
||||
|
||||
await Event.create({
|
||||
name: "documents.unpublish",
|
||||
|
||||
Reference in New Issue
Block a user