Policies refactor, guest roles (#6732)
This commit is contained in:
@@ -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
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
•
|
||||
<Link
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user