From 7bf5c4e5330cabebdb8ce2795a0582f270e72735 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 10 Jun 2024 20:38:23 -0400 Subject: [PATCH] Add `manage` permission to documents (#7003) --- app/components/InputSelectPermission.tsx | 9 +++++---- .../Collection/CollectionMemberList.tsx | 8 ++++---- .../Sharing/Collection/SharePopover.tsx | 8 ++++---- .../Document/DocumentMemberListItem.tsx | 4 ++++ .../Sharing/Document/SharePopover.tsx | 8 ++++++-- .../emails/templates/DocumentSharedEmail.tsx | 2 +- server/policies/document.ts | 18 +++++++++++++++--- shared/i18n/locales/en_US/translation.json | 5 +++-- shared/types.ts | 1 + 9 files changed, 43 insertions(+), 20 deletions(-) diff --git a/app/components/InputSelectPermission.tsx b/app/components/InputSelectPermission.tsx index 9bdb0509c..cb861823d 100644 --- a/app/components/InputSelectPermission.tsx +++ b/app/components/InputSelectPermission.tsx @@ -23,15 +23,16 @@ function InputSelectPermission( ref={ref} label={t("Permission")} options={[ - { - label: t("Can edit"), - value: CollectionPermission.ReadWrite, - }, { label: t("View only"), value: CollectionPermission.Read, }, { + label: t("Can edit"), + value: CollectionPermission.ReadWrite, + }, + { + divider: true, label: t("No access"), value: EmptySelectValue, }, diff --git a/app/components/Sharing/Collection/CollectionMemberList.tsx b/app/components/Sharing/Collection/CollectionMemberList.tsx index 637d3b7ba..0fd046dc1 100644 --- a/app/components/Sharing/Collection/CollectionMemberList.tsx +++ b/app/components/Sharing/Collection/CollectionMemberList.tsx @@ -53,16 +53,16 @@ function CollectionMemberList({ collection, invitedInSession }: Props) { () => [ { - label: t("Admin"), - value: CollectionPermission.Admin, + label: t("View only"), + value: CollectionPermission.Read, }, { label: t("Can edit"), value: CollectionPermission.ReadWrite, }, { - label: t("View only"), - value: CollectionPermission.Read, + label: t("Manage"), + value: CollectionPermission.Admin, }, { divider: true, diff --git a/app/components/Sharing/Collection/SharePopover.tsx b/app/components/Sharing/Collection/SharePopover.tsx index c20ddc2a2..6e0e37aad 100644 --- a/app/components/Sharing/Collection/SharePopover.tsx +++ b/app/components/Sharing/Collection/SharePopover.tsx @@ -229,16 +229,16 @@ function SharePopover({ collection, visible, onRequestClose }: Props) { () => [ { - label: t("Admin"), - value: CollectionPermission.Admin, + label: t("View only"), + value: CollectionPermission.Read, }, { label: t("Can edit"), value: CollectionPermission.ReadWrite, }, { - label: t("View only"), - value: CollectionPermission.Read, + label: t("Manage"), + value: CollectionPermission.Admin, }, ] as Permission[], [t] diff --git a/app/components/Sharing/Document/DocumentMemberListItem.tsx b/app/components/Sharing/Document/DocumentMemberListItem.tsx index 0fce616a0..02d81baad 100644 --- a/app/components/Sharing/Document/DocumentMemberListItem.tsx +++ b/app/components/Sharing/Document/DocumentMemberListItem.tsx @@ -51,6 +51,10 @@ const DocumentMemberListItem = ({ label: t("Can edit"), value: DocumentPermission.ReadWrite, }, + { + label: t("Manage"), + value: DocumentPermission.Admin, + }, { divider: true, label: t("Remove"), diff --git a/app/components/Sharing/Document/SharePopover.tsx b/app/components/Sharing/Document/SharePopover.tsx index 06fd60f60..81877f787 100644 --- a/app/components/Sharing/Document/SharePopover.tsx +++ b/app/components/Sharing/Document/SharePopover.tsx @@ -202,13 +202,17 @@ function SharePopover({ const permissions = React.useMemo( () => [ + { + label: t("View only"), + value: DocumentPermission.Read, + }, { label: t("Can edit"), value: DocumentPermission.ReadWrite, }, { - label: t("View only"), - value: DocumentPermission.Read, + label: t("Manage"), + value: DocumentPermission.Admin, }, ] as Permission[], [t] diff --git a/server/emails/templates/DocumentSharedEmail.tsx b/server/emails/templates/DocumentSharedEmail.tsx index 4dcd4d628..23d646165 100644 --- a/server/emails/templates/DocumentSharedEmail.tsx +++ b/server/emails/templates/DocumentSharedEmail.tsx @@ -73,7 +73,7 @@ View Document: ${teamUrl}${document.path} const documentUrl = `${teamUrl}${document.path}?ref=notification-email`; const permission = - membership.permission === DocumentPermission.ReadWrite ? "edit" : "view"; + membership.permission === DocumentPermission.Read ? "view" : "edit"; return ( includesMembership(document, [ DocumentPermission.Read, DocumentPermission.ReadWrite, + DocumentPermission.Admin, ]), and(!!document?.isDraft, actor.id === document?.createdById), can(actor, "readDocument", document?.collection) @@ -93,7 +94,10 @@ allow(User, "update", Document, (actor, document) => isTeamMutable(actor), !!document?.isActive, or( - includesMembership(document, [DocumentPermission.ReadWrite]), + includesMembership(document, [ + DocumentPermission.ReadWrite, + DocumentPermission.Admin, + ]), or( can(actor, "updateDocument", document?.collection), and(!!document?.isDraft && actor.id === document?.createdById) @@ -115,6 +119,7 @@ allow(User, ["move", "duplicate", "manageUsers"], Document, (actor, document) => !actor.isGuest, can(actor, "update", document), or( + includesMembership(document, [DocumentPermission.Admin]), can(actor, "updateDocument", document?.collection), and(!!document?.isDraft && actor.id === document?.createdById) ) @@ -124,6 +129,7 @@ allow(User, ["move", "duplicate", "manageUsers"], Document, (actor, document) => allow(User, "createChildDocument", Document, (actor, document) => and( can(actor, "update", document), + can(actor, "read", document?.collection), !document?.isDraft, !document?.template, !actor.isGuest @@ -171,7 +177,10 @@ allow(User, ["restore", "permanentDelete"], Document, (actor, document) => !actor.isGuest, !!document?.isDeleted, or( - includesMembership(document, [DocumentPermission.ReadWrite]), + includesMembership(document, [ + DocumentPermission.ReadWrite, + DocumentPermission.Admin, + ]), or( can(actor, "updateDocument", document?.collection), and(!!document?.isDraft && actor.id === document?.createdById) @@ -202,7 +211,10 @@ allow(User, "unarchive", Document, (actor, document) => and( can(actor, "read", document), or( - includesMembership(document, [DocumentPermission.ReadWrite]), + includesMembership(document, [ + DocumentPermission.ReadWrite, + DocumentPermission.Admin, + ]), or( can(actor, "updateDocument", document?.collection), and(!!document?.isDraft && actor.id === document?.createdById) diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index fa2f7a223..e02beeadd 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -251,8 +251,8 @@ "Select a color": "Select a color", "Search": "Search", "Permission": "Permission", - "Can edit": "Can edit", "View only": "View only", + "Can edit": "Can edit", "No access": "No access", "Default access": "Default access", "Change Language": "Change Language", @@ -267,7 +267,7 @@ "Documents": "Documents", "Results": "Results", "No results for {{query}}": "No results for {{query}}", - "Admin": "Admin", + "Manage": "Manage", "Invite": "Invite", "{{ userName }} was added to the collection": "{{ userName }} was added to the collection", "{{ count }} people added to the collection": "{{ count }} people added to the collection", @@ -632,6 +632,7 @@ "No people left to add": "No people left to add", "Active <1> ago": "Active <1> ago", "Never signed in": "Never signed in", + "Admin": "Admin", "{{userName}} was removed from the group": "{{userName}} was removed from the group", "Add and remove members to the {{groupName}} group. Members of the group will have access to any collections this group has been added to.": "Add and remove members to the {{groupName}} group. Members of the group will have access to any collections this group has been added to.", "Add people": "Add people", diff --git a/shared/types.ts b/shared/types.ts index 949043d6b..6349f4df3 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -107,6 +107,7 @@ export enum CollectionPermission { export enum DocumentPermission { Read = "read", ReadWrite = "read_write", + Admin = "admin", } export type IntegrationSettings = T extends IntegrationType.Embed