* fix: Admins have permission to see existence of all collections (in settings) * fix: Current user filtered from suggestions. As an admin managing other collections this is limiting * test
271 lines
6.3 KiB
TypeScript
271 lines
6.3 KiB
TypeScript
import invariant from "invariant";
|
|
import some from "lodash/some";
|
|
import {
|
|
CollectionPermission,
|
|
DocumentPermission,
|
|
TeamPreference,
|
|
} from "@shared/types";
|
|
import { Document, Revision, User, Team } from "@server/models";
|
|
import { allow, _cannot as cannot, _can as can } from "./cancan";
|
|
import { and, isTeamAdmin, isTeamModel, isTeamMutable, or } from "./utils";
|
|
|
|
allow(User, "createDocument", Team, (actor, document) =>
|
|
and(
|
|
//
|
|
!actor.isGuest,
|
|
!actor.isViewer,
|
|
isTeamModel(actor, document),
|
|
isTeamMutable(actor)
|
|
)
|
|
);
|
|
|
|
allow(User, "read", Document, (actor, document) =>
|
|
and(
|
|
isTeamModel(actor, document),
|
|
or(
|
|
includesMembership(document, [
|
|
DocumentPermission.Read,
|
|
DocumentPermission.ReadWrite,
|
|
DocumentPermission.Admin,
|
|
]),
|
|
and(!!document?.isDraft, actor.id === document?.createdById),
|
|
can(actor, "readDocument", document?.collection)
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, ["listRevisions", "listViews"], Document, (actor, document) =>
|
|
or(
|
|
and(can(actor, "read", document), !actor.isGuest),
|
|
and(can(actor, "update", document), actor.isGuest)
|
|
)
|
|
);
|
|
|
|
allow(User, "download", Document, (actor, document) =>
|
|
and(
|
|
can(actor, "read", document),
|
|
or(
|
|
and(!actor.isGuest, !actor.isViewer),
|
|
!!actor.team.getPreference(TeamPreference.ViewersCanExport)
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, "comment", Document, (actor, document) =>
|
|
and(
|
|
// TODO: We'll introduce a separate permission for commenting
|
|
or(
|
|
and(can(actor, "read", document), !actor.isGuest),
|
|
and(can(actor, "update", document), actor.isGuest)
|
|
),
|
|
isTeamMutable(actor),
|
|
!!document?.isActive,
|
|
!document?.template
|
|
)
|
|
);
|
|
|
|
allow(
|
|
User,
|
|
["star", "unstar", "subscribe", "unsubscribe"],
|
|
Document,
|
|
(actor, document) =>
|
|
and(
|
|
//
|
|
can(actor, "read", document),
|
|
!document?.template
|
|
)
|
|
);
|
|
|
|
allow(User, "share", Document, (actor, document) =>
|
|
and(
|
|
can(actor, "read", document),
|
|
isTeamMutable(actor),
|
|
!!document?.isActive,
|
|
!document?.template,
|
|
or(!document?.collection, can(actor, "share", document?.collection))
|
|
)
|
|
);
|
|
|
|
allow(User, "update", Document, (actor, document) =>
|
|
and(
|
|
can(actor, "read", document),
|
|
isTeamMutable(actor),
|
|
!!document?.isActive,
|
|
or(
|
|
includesMembership(document, [
|
|
DocumentPermission.ReadWrite,
|
|
DocumentPermission.Admin,
|
|
]),
|
|
or(
|
|
can(actor, "updateDocument", document?.collection),
|
|
and(!!document?.isDraft && actor.id === document?.createdById)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, "publish", Document, (actor, document) =>
|
|
and(
|
|
//
|
|
can(actor, "update", document),
|
|
!!document?.isDraft
|
|
)
|
|
);
|
|
|
|
allow(User, ["manageUsers", "duplicate"], Document, (actor, document) =>
|
|
and(
|
|
can(actor, "update", document),
|
|
or(
|
|
includesMembership(document, [DocumentPermission.Admin]),
|
|
can(actor, "updateDocument", document?.collection),
|
|
!!document?.isDraft && actor.id === document?.createdById
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, "move", Document, (actor, document) =>
|
|
and(
|
|
can(actor, "update", document),
|
|
or(
|
|
can(actor, "updateDocument", document?.collection),
|
|
and(!!document?.isDraft && actor.id === document?.createdById)
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, "createChildDocument", Document, (actor, document) =>
|
|
and(
|
|
can(actor, "update", document),
|
|
or(
|
|
includesMembership(document, [DocumentPermission.Admin]),
|
|
can(actor, "readDocument", document?.collection)
|
|
),
|
|
!document?.isDraft,
|
|
!document?.template
|
|
)
|
|
);
|
|
|
|
allow(User, ["updateInsights", "pin", "unpin"], Document, (actor, document) =>
|
|
and(
|
|
can(actor, "update", document),
|
|
can(actor, "update", document?.collection),
|
|
!document?.isDraft,
|
|
!document?.template,
|
|
!actor.isGuest
|
|
)
|
|
);
|
|
|
|
allow(User, "pinToHome", Document, (actor, document) =>
|
|
and(
|
|
//
|
|
isTeamAdmin(actor, document),
|
|
isTeamMutable(actor),
|
|
!document?.isDraft,
|
|
!document?.template,
|
|
!!document?.isActive
|
|
)
|
|
);
|
|
|
|
allow(User, "delete", Document, (actor, document) =>
|
|
and(
|
|
isTeamModel(actor, document),
|
|
isTeamMutable(actor),
|
|
!document?.isDeleted,
|
|
or(
|
|
can(actor, "unarchive", document),
|
|
can(actor, "update", document),
|
|
!document?.collection
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, ["restore", "permanentDelete"], Document, (actor, document) =>
|
|
and(
|
|
isTeamModel(actor, document),
|
|
!actor.isGuest,
|
|
!!document?.isDeleted,
|
|
or(
|
|
includesMembership(document, [
|
|
DocumentPermission.ReadWrite,
|
|
DocumentPermission.Admin,
|
|
]),
|
|
can(actor, "updateDocument", document?.collection),
|
|
and(!!document?.isDraft && actor.id === document?.createdById),
|
|
!document?.collection
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, "archive", Document, (actor, document) =>
|
|
and(
|
|
!document?.template,
|
|
!document?.isDraft,
|
|
!!document?.isActive,
|
|
can(actor, "update", document),
|
|
or(
|
|
includesMembership(document, [DocumentPermission.Admin]),
|
|
can(actor, "updateDocument", document?.collection)
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(User, "unarchive", Document, (actor, document) =>
|
|
and(
|
|
!document?.template,
|
|
!document?.isDraft,
|
|
!document?.isDeleted,
|
|
!!document?.archivedAt,
|
|
can(actor, "read", document),
|
|
or(
|
|
includesMembership(document, [
|
|
DocumentPermission.ReadWrite,
|
|
DocumentPermission.Admin,
|
|
]),
|
|
can(actor, "updateDocument", document?.collection),
|
|
and(!!document?.isDraft && actor.id === document?.createdById)
|
|
)
|
|
)
|
|
);
|
|
|
|
allow(
|
|
Document,
|
|
"restore",
|
|
Revision,
|
|
(document, revision) => document.id === revision?.documentId
|
|
);
|
|
|
|
allow(User, "unpublish", Document, (user, document) => {
|
|
if (
|
|
!document ||
|
|
user.isGuest ||
|
|
user.isViewer ||
|
|
!document.isActive ||
|
|
document.isDraft
|
|
) {
|
|
return false;
|
|
}
|
|
invariant(
|
|
document.collection,
|
|
"collection is missing, did you forget to include in the query scope?"
|
|
);
|
|
if (cannot(user, "updateDocument", document.collection)) {
|
|
return false;
|
|
}
|
|
return user.teamId === document.teamId;
|
|
});
|
|
|
|
function includesMembership(
|
|
document: Document | null,
|
|
permissions: (DocumentPermission | CollectionPermission)[]
|
|
) {
|
|
if (!document) {
|
|
return false;
|
|
}
|
|
|
|
invariant(
|
|
document.memberships,
|
|
"document memberships should be preloaded, did you forget withMembership scope?"
|
|
);
|
|
return some(document.memberships, (m) => permissions.includes(m.permission));
|
|
}
|