feat: Collection admins (#5273

* Split permissions for reading documents from updating collection

* fix: Admins should have collection read permission, tests

* tsc

* Add admin option to permission selector

* Combine publish and create permissions, update -> createDocuments where appropriate

* Plural -> singular

* wip

* Quick version of collection structure loading, will revisit

* Remove documentIds method

* stash

* fixing tests to account for admin creation

* Add self-hosted migration

* fix: Allow groups to have admin permission

* Prefetch collection documents

* fix: Document explorer (move/publish) not working with async documents

* fix: Cannot re-parent document to collection by drag and drop

* fix: Cannot drag to import into collection item without admin permission

* Remove unused isEditor getter
This commit is contained in:
Tom Moor
2023-04-30 09:38:47 -04:00
committed by GitHub
parent 2942e9c78e
commit d8b4fef554
44 changed files with 799 additions and 535 deletions

View File

@@ -254,21 +254,17 @@ class Collection extends ParanoidModel {
model: Collection,
options: { transaction: Transaction }
) {
if (model.permission !== CollectionPermission.ReadWrite) {
return CollectionUser.findOrCreate({
where: {
collectionId: model.id,
userId: model.createdById,
},
defaults: {
permission: CollectionPermission.ReadWrite,
createdById: model.createdById,
},
transaction: options.transaction,
});
}
return undefined;
return CollectionUser.findOrCreate({
where: {
collectionId: model.id,
userId: model.createdById,
},
defaults: {
permission: CollectionPermission.Admin,
createdById: model.createdById,
},
transaction: options.transaction,
});
}
// associations
@@ -396,6 +392,17 @@ class Collection extends ParanoidModel {
});
}
/**
* Convenience method to return if a collection is considered private.
* This means that a membership is required to view it rather than just being
* a workspace member.
*
* @returns boolean
*/
get isPrivate() {
return !this.permission;
}
getDocumentTree = (documentId: string): NavigationNode | null => {
if (!this.documentStructure) {
return null;

View File

@@ -473,6 +473,25 @@ class Document extends ParanoidModel {
// instance methods
/**
* Whether this document is considered active or not. A document is active if
* it has not been archived or deleted.
*
* @returns boolean
*/
get isActive(): boolean {
return !this.archivedAt && !this.deletedAt;
}
/**
* Convenience method that returns whether this document is a draft.
*
* @returns boolean
*/
get isDraft(): boolean {
return !this.publishedAt;
}
get titleWithDefault(): string {
return this.title || "Untitled";
}

View File

@@ -380,8 +380,9 @@ class User extends ParanoidModel {
return collectionStubs
.filter(
(c) =>
c.permission === CollectionPermission.Read ||
c.permission === CollectionPermission.ReadWrite ||
Object.values(CollectionPermission).includes(
c.permission as CollectionPermission
) ||
c.memberships.length > 0 ||
c.collectionGroupMemberships.length > 0
)