diff --git a/app/scenes/Document/components/Header.js b/app/scenes/Document/components/Header.js index 259f455d..0804bf15 100644 --- a/app/scenes/Document/components/Header.js +++ b/app/scenes/Document/components/Header.js @@ -79,7 +79,6 @@ function DocumentHeader({ const isNew = document.isNewDocument; const isTemplate = document.isTemplate; const can = policies.abilities(document.id); - const canShareDocument = auth.team && auth.team.sharing && can.share; const canToggleEmbeds = auth.team && auth.team.documentEmbeds; const canEdit = can.update && !isEditing; @@ -171,7 +170,7 @@ function DocumentHeader({ )} - {!isEditing && canShareDocument && (!isMobile || !isTemplate) && ( + {!isEditing && (!isMobile || !isTemplate) && ( diff --git a/app/scenes/Document/components/SharePopover.js b/app/scenes/Document/components/SharePopover.js index ca3160d5..d4aa4712 100644 --- a/app/scenes/Document/components/SharePopover.js +++ b/app/scenes/Document/components/SharePopover.js @@ -27,12 +27,17 @@ type Props = {| function SharePopover({ document, share, sharedParent, onSubmit }: Props) { const { t } = useTranslation(); - const { policies, shares } = useStores(); + const { policies, shares, auth } = useStores(); const { showToast } = useToasts(); const [isCopied, setIsCopied] = React.useState(false); const timeout = React.useRef(); const can = policies.abilities(share ? share.id : ""); - const canPublish = can.update && !document.isTemplate; + const documentAbilities = policies.abilities(document.id); + const canPublish = + can.update && + !document.isTemplate && + auth.team?.sharing && + documentAbilities.share; const isPubliclyShared = (share && share.published) || sharedParent; React.useEffect(() => { @@ -102,7 +107,7 @@ function SharePopover({ document, share, sharedParent, onSubmit }: Props) { )} - {canPublish && ( + {canPublish ? ( + ) : ( + {t("Only team members with permission can view")} )} - {share && share.published && ( + + {canPublish && share?.published && ( { @@ -534,10 +534,20 @@ async function loadDocument({ document = share.document; } - // "published" === on the public internet. So if the share isn't published - // then we must have permission to read the document + // If the user has access to read the document, we can just update + // the last access date and return the document without additional checks. + const canReadDocument = can(user, "read", document); + if (canReadDocument) { + await share.update({ lastAccessedAt: new Date() }); + + return { document, share, collection }; + } + + // "published" === on the public internet. + // We already know that there's either no logged in user or the user doesn't + // have permission to read the document, so we can throw an error. if (!share.published) { - authorize(user, "read", document); + throw new AuthorizationError(); } // It is possible to disable sharing at the collection so we must check diff --git a/server/api/documents.test.js b/server/api/documents.test.js index e43609d6..c10c4b7c 100644 --- a/server/api/documents.test.js +++ b/server/api/documents.test.js @@ -235,6 +235,27 @@ describe("#documents.info", () => { expect(res.status).toEqual(403); }); + it("should return document from shareId if public sharing is disabled but the user has permission to read", async () => { + const { document, collection, team, user } = await seed(); + const share = await buildShare({ + documentId: document.id, + teamId: document.teamId, + userId: user.id, + }); + + team.sharing = false; + await team.save(); + + collection.sharing = false; + await collection.save(); + + const res = await server.post("/api/documents.info", { + body: { token: user.getJwtToken(), shareId: share.id }, + }); + + expect(res.status).toEqual(200); + }); + it("should not return document from revoked shareId", async () => { const { document, user } = await seed(); const share = await buildShare({