Policies refactor, guest roles (#6732)

This commit is contained in:
Tom Moor
2024-03-31 18:28:35 -06:00
committed by GitHub
parent ceb7ae1514
commit c27cd945a7
46 changed files with 901 additions and 1032 deletions

View File

@@ -432,7 +432,8 @@ export const copyDocumentAsMarkdown = createAction({
name: ({ t }) => t("Copy as Markdown"),
section: DocumentSection,
keywords: "clipboard",
visible: ({ activeDocumentId }) => !!activeDocumentId,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).download,
perform: ({ stores, activeDocumentId, t }) => {
const document = activeDocumentId
? stores.documents.get(activeDocumentId)
@@ -856,7 +857,7 @@ export const openDocumentHistory = createAction({
icon: <HistoryIcon />,
visible: ({ activeDocumentId, stores }) => {
const can = stores.policies.abilities(activeDocumentId ?? "");
return !!activeDocumentId && can.read && !can.restore;
return !!activeDocumentId && can.listRevisions;
},
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
@@ -883,7 +884,7 @@ export const openDocumentInsights = createAction({
return (
!!activeDocumentId &&
can.read &&
can.listViews &&
!document?.isTemplate &&
!document?.isDeleted
);

View File

@@ -47,7 +47,8 @@ const AuthenticatedLayout: React.FC = ({ children }: Props) => {
const { ui, auth } = useStores();
const location = useLocation();
const layoutRef = React.useRef<HTMLDivElement>(null);
const can = usePolicy(ui.activeCollectionId);
const can = usePolicy(ui.activeDocumentId);
const canCollection = usePolicy(ui.activeCollectionId);
const team = useCurrentTeam();
const documentContext = useLocalStore<DocumentContextValue>(() => ({
editor: null,
@@ -69,7 +70,7 @@ const AuthenticatedLayout: React.FC = ({ children }: Props) => {
return;
}
const { activeCollectionId } = ui;
if (!activeCollectionId || !can.createDocument) {
if (!activeCollectionId || !canCollection.createDocument) {
return;
}
history.push(newDocumentPath(activeCollectionId));
@@ -88,15 +89,18 @@ const AuthenticatedLayout: React.FC = ({ children }: Props) => {
</Fade>
);
const showHistory = !!matchPath(location.pathname, {
path: matchDocumentHistory,
});
const showInsights = !!matchPath(location.pathname, {
path: matchDocumentInsights,
});
const showHistory =
!!matchPath(location.pathname, {
path: matchDocumentHistory,
}) && can.listRevisions;
const showInsights =
!!matchPath(location.pathname, {
path: matchDocumentInsights,
}) && can.listViews;
const showComments =
!showInsights &&
!showHistory &&
can.comment &&
ui.activeDocumentId &&
ui.commentsExpanded.includes(ui.activeDocumentId) &&
team.getPreference(TeamPreference.Commenting);

View File

@@ -25,6 +25,7 @@ import isCloudHosted from "~/utils/isCloudHosted";
import lazy from "~/utils/lazyWithRetry";
import { settingsPath } from "~/utils/routeHelpers";
import useCurrentTeam from "./useCurrentTeam";
import useCurrentUser from "./useCurrentUser";
import usePolicy from "./usePolicy";
const ApiKeys = lazy(() => import("~/scenes/Settings/ApiKeys"));
@@ -54,6 +55,7 @@ export type ConfigItem = {
};
const useSettingsConfig = () => {
const user = useCurrentUser();
const team = useCurrentTeam();
const can = usePolicy(team);
const { t } = useTranslation();
@@ -122,7 +124,7 @@ const useSettingsConfig = () => {
name: t("Members"),
path: settingsPath("members"),
component: Members,
enabled: true,
enabled: can.listUsers,
group: t("Workspace"),
icon: UserIcon,
},
@@ -130,7 +132,7 @@ const useSettingsConfig = () => {
name: t("Groups"),
path: settingsPath("groups"),
component: Groups,
enabled: true,
enabled: can.listGroups,
group: t("Workspace"),
icon: GroupIcon,
},
@@ -138,7 +140,7 @@ const useSettingsConfig = () => {
name: t("Templates"),
path: settingsPath("templates"),
component: Templates,
enabled: true,
enabled: can.update,
group: t("Workspace"),
icon: ShapesIcon,
},
@@ -146,7 +148,7 @@ const useSettingsConfig = () => {
name: t("Shared Links"),
path: settingsPath("shares"),
component: Shares,
enabled: true,
enabled: can.listShares,
group: t("Workspace"),
icon: GlobeIcon,
},
@@ -211,7 +213,7 @@ const useSettingsConfig = () => {
enabled:
enabledInDeployment &&
hasSettings &&
(plugin.config.adminOnly === false || can.update),
(plugin.config.roles?.includes(user.role) || can.update),
icon: plugin.icon,
} as ConfigItem;

View File

@@ -312,7 +312,7 @@ function DocumentMenu({
actionToMenuItem(permanentlyDeleteDocument, context),
]}
/>
{(showDisplayOptions || showToggleEmbeds) && (
{(showDisplayOptions || showToggleEmbeds) && can.update && (
<>
<Separator />
<DisplayOptions>
@@ -332,7 +332,7 @@ function DocumentMenu({
/>
</Style>
)}
{showDisplayOptions && !isMobile && can.update && (
{showDisplayOptions && !isMobile && (
<Style>
<ToggleMenuItem
width={26}

View File

@@ -79,6 +79,13 @@ class User extends ParanoidModel {
return this.role === UserRole.Admin;
}
/**
* Whether the user is a member (editor).
*/
get isMember(): boolean {
return this.role === UserRole.Member;
}
/**
* Whether the user is a viewer.
*/
@@ -86,6 +93,13 @@ class User extends ParanoidModel {
return this.role === UserRole.Viewer;
}
/**
* Whether the user is a guest.
*/
get isGuest(): boolean {
return this.role === UserRole.Guest;
}
/**
* Whether the user has been recently active. Recently is currently defined
* as within the last 5 minutes.

View File

@@ -119,7 +119,6 @@ export default abstract class Model {
try {
this[key] = data[key];
} catch (error) {
// Temporary as isViewer and isAdmin properties changed to getters
Logger.warn(`Error setting ${key} on model`, error);
}
}

View File

@@ -55,7 +55,10 @@ function TitleDocumentMeta({ to, document, revision, ...rest }: Props) {
</CommentLink>
</>
)}
{totalViewers && !document.isDraft && !document.isTemplate ? (
{totalViewers &&
can.listViews &&
!document.isDraft &&
!document.isTemplate ? (
<Wrapper>
&nbsp;&nbsp;
<Link

View File

@@ -248,7 +248,9 @@ function DocumentHeader({
{!isPublishing && isSaving && user?.separateEditMode && (
<Status>{t("Saving")}</Status>
)}
{!isDeleted && !isRevision && <Collaborators document={document} />}
{!isDeleted && !isRevision && can.listViews && (
<Collaborators document={document} />
)}
{(isEditing || !user?.separateEditMode) && !isTemplate && isNew && (
<Action>
<TemplatesMenu

View File

@@ -62,6 +62,8 @@ function PeopleTable({ canManage, ...rest }: Props) {
<Badge primary>{t("Admin")}</Badge>
) : row.original.isViewer ? (
<Badge>{t("Viewer")}</Badge>
) : row.original.isGuest ? (
<Badge yellow>{t("Guest")}</Badge>
) : (
<Badge>{t("Editor")}</Badge>
)}

View File

@@ -1,11 +1,12 @@
import React from "react";
import { UserRole } from "@shared/types";
interface Plugin {
id: string;
config: {
name: string;
description: string;
adminOnly?: boolean;
roles?: UserRole[];
deployments?: string[];
};
settings: React.FC;