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({