feat: Always show share button (#2469)
This is to enable the share page also for internal team members. closes #2444
This commit is contained in:
@ -79,7 +79,6 @@ function DocumentHeader({
|
|||||||
const isNew = document.isNewDocument;
|
const isNew = document.isNewDocument;
|
||||||
const isTemplate = document.isTemplate;
|
const isTemplate = document.isTemplate;
|
||||||
const can = policies.abilities(document.id);
|
const can = policies.abilities(document.id);
|
||||||
const canShareDocument = auth.team && auth.team.sharing && can.share;
|
|
||||||
const canToggleEmbeds = auth.team && auth.team.documentEmbeds;
|
const canToggleEmbeds = auth.team && auth.team.documentEmbeds;
|
||||||
const canEdit = can.update && !isEditing;
|
const canEdit = can.update && !isEditing;
|
||||||
|
|
||||||
@ -171,7 +170,7 @@ function DocumentHeader({
|
|||||||
<TemplatesMenu document={document} />
|
<TemplatesMenu document={document} />
|
||||||
</Action>
|
</Action>
|
||||||
)}
|
)}
|
||||||
{!isEditing && canShareDocument && (!isMobile || !isTemplate) && (
|
{!isEditing && (!isMobile || !isTemplate) && (
|
||||||
<Action>
|
<Action>
|
||||||
<ShareButton document={document} />
|
<ShareButton document={document} />
|
||||||
</Action>
|
</Action>
|
||||||
|
@ -27,12 +27,17 @@ type Props = {|
|
|||||||
|
|
||||||
function SharePopover({ document, share, sharedParent, onSubmit }: Props) {
|
function SharePopover({ document, share, sharedParent, onSubmit }: Props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { policies, shares } = useStores();
|
const { policies, shares, auth } = useStores();
|
||||||
const { showToast } = useToasts();
|
const { showToast } = useToasts();
|
||||||
const [isCopied, setIsCopied] = React.useState(false);
|
const [isCopied, setIsCopied] = React.useState(false);
|
||||||
const timeout = React.useRef<?TimeoutID>();
|
const timeout = React.useRef<?TimeoutID>();
|
||||||
const can = policies.abilities(share ? share.id : "");
|
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;
|
const isPubliclyShared = (share && share.published) || sharedParent;
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -102,7 +107,7 @@ function SharePopover({ document, share, sharedParent, onSubmit }: Props) {
|
|||||||
</Notice>
|
</Notice>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{canPublish && (
|
{canPublish ? (
|
||||||
<SwitchWrapper>
|
<SwitchWrapper>
|
||||||
<Switch
|
<Switch
|
||||||
id="published"
|
id="published"
|
||||||
@ -132,8 +137,11 @@ function SharePopover({ document, share, sharedParent, onSubmit }: Props) {
|
|||||||
</SwitchText>
|
</SwitchText>
|
||||||
</SwitchLabel>
|
</SwitchLabel>
|
||||||
</SwitchWrapper>
|
</SwitchWrapper>
|
||||||
|
) : (
|
||||||
|
<HelpText>{t("Only team members with permission can view")}</HelpText>
|
||||||
)}
|
)}
|
||||||
{share && share.published && (
|
|
||||||
|
{canPublish && share?.published && (
|
||||||
<SwitchWrapper>
|
<SwitchWrapper>
|
||||||
<Switch
|
<Switch
|
||||||
id="includeChildDocuments"
|
id="includeChildDocuments"
|
||||||
|
@ -36,7 +36,7 @@ import { sequelize } from "../sequelize";
|
|||||||
import pagination from "./middlewares/pagination";
|
import pagination from "./middlewares/pagination";
|
||||||
|
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
const { authorize, cannot } = policy;
|
const { authorize, cannot, can } = policy;
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("documents.list", auth(), pagination(), async (ctx) => {
|
router.post("documents.list", auth(), pagination(), async (ctx) => {
|
||||||
@ -534,10 +534,20 @@ async function loadDocument({
|
|||||||
document = share.document;
|
document = share.document;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "published" === on the public internet. So if the share isn't published
|
// If the user has access to read the document, we can just update
|
||||||
// then we must have permission to read the document
|
// 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) {
|
if (!share.published) {
|
||||||
authorize(user, "read", document);
|
throw new AuthorizationError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is possible to disable sharing at the collection so we must check
|
// It is possible to disable sharing at the collection so we must check
|
||||||
|
@ -235,6 +235,27 @@ describe("#documents.info", () => {
|
|||||||
expect(res.status).toEqual(403);
|
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 () => {
|
it("should not return document from revoked shareId", async () => {
|
||||||
const { document, user } = await seed();
|
const { document, user } = await seed();
|
||||||
const share = await buildShare({
|
const share = await buildShare({
|
||||||
|
Reference in New Issue
Block a user