fix: workspace settings access validation updated (#5606)
This commit is contained in:
parent
f155a13929
commit
c14d20c2e0
3 changed files with 57 additions and 33 deletions
|
|
@ -1,34 +1,51 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ReactNode } from "react";
|
import { FC, ReactNode } from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
// components
|
// components
|
||||||
import { AppHeader } from "@/components/core";
|
import { AppHeader } from "@/components/core";
|
||||||
// local components
|
// local components
|
||||||
import { WorkspaceSettingHeader } from "./header";
|
import { WorkspaceSettingHeader } from "./header";
|
||||||
import { MobileWorkspaceSettingsTabs } from "./mobile-header-tabs";
|
import { MobileWorkspaceSettingsTabs } from "./mobile-header-tabs";
|
||||||
import { WorkspaceSettingsSidebar } from "./sidebar";
|
import { WorkspaceSettingsSidebar } from "./sidebar";
|
||||||
|
import { NotAuthorizedView } from "@/components/auth-screens";
|
||||||
|
import { useUserPermissions } from "@/hooks/store";
|
||||||
|
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||||
|
|
||||||
export interface IWorkspaceSettingLayout {
|
export interface IWorkspaceSettingLayout {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WorkspaceSettingLayout(props: IWorkspaceSettingLayout) {
|
const WorkspaceSettingLayout: FC<IWorkspaceSettingLayout> = observer((props) => {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
|
||||||
|
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
|
||||||
|
|
||||||
|
// derived values
|
||||||
|
const isWorkspaceAdmin = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AppHeader header={<WorkspaceSettingHeader />} />
|
<AppHeader header={<WorkspaceSettingHeader />} />
|
||||||
<MobileWorkspaceSettingsTabs />
|
<MobileWorkspaceSettingsTabs />
|
||||||
<div className="inset-y-0 flex flex-row vertical-scrollbar scrollbar-lg h-full w-full overflow-y-auto">
|
<div className="inset-y-0 flex flex-row vertical-scrollbar scrollbar-lg h-full w-full overflow-y-auto">
|
||||||
<div className="px-page-x !pr-0 py-page-y flex-shrink-0 overflow-y-hidden sm:hidden hidden md:block lg:block">
|
{workspaceUserInfo && !isWorkspaceAdmin ? (
|
||||||
<WorkspaceSettingsSidebar />
|
<NotAuthorizedView section="settings" />
|
||||||
</div>
|
) : (
|
||||||
<div className="flex flex-col relative w-full overflow-hidden">
|
<>
|
||||||
<div className="w-full h-full overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-page-x md:px-9 py-page-y">
|
<div className="px-page-x !pr-0 py-page-y flex-shrink-0 overflow-y-hidden sm:hidden hidden md:block lg:block">
|
||||||
{children}
|
<WorkspaceSettingsSidebar />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="flex flex-col relative w-full overflow-hidden">
|
||||||
|
<div className="w-full h-full overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-page-x md:px-9 py-page-y">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
export default WorkspaceSettingLayout;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export const WORKSPACE_SETTINGS = {
|
||||||
key: "general",
|
key: "general",
|
||||||
label: "General",
|
label: "General",
|
||||||
href: `/settings`,
|
href: `/settings`,
|
||||||
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST],
|
access: [EUserPermissions.ADMIN],
|
||||||
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/`,
|
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/`,
|
||||||
Icon: SettingIcon,
|
Icon: SettingIcon,
|
||||||
},
|
},
|
||||||
|
|
@ -17,7 +17,7 @@ export const WORKSPACE_SETTINGS = {
|
||||||
key: "members",
|
key: "members",
|
||||||
label: "Members",
|
label: "Members",
|
||||||
href: `/settings/members`,
|
href: `/settings/members`,
|
||||||
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
access: [EUserPermissions.ADMIN],
|
||||||
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/members/`,
|
highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/members/`,
|
||||||
Icon: SettingIcon,
|
Icon: SettingIcon,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ import { IWorkspace } from "@plane/types";
|
||||||
import { Avatar, Loader, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Avatar, Loader, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
import { GOD_MODE_URL, cn } from "@/helpers/common.helper";
|
import { GOD_MODE_URL, cn } from "@/helpers/common.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useAppTheme, useUser, useUserProfile, useWorkspace } from "@/hooks/store";
|
import { useAppTheme, useUser, useUserPermissions, useUserProfile, useWorkspace } from "@/hooks/store";
|
||||||
|
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
|
||||||
import { WorkspaceLogo } from "../logo";
|
import { WorkspaceLogo } from "../logo";
|
||||||
|
|
||||||
// Static Data
|
// Static Data
|
||||||
|
|
@ -25,12 +26,14 @@ const userLinks = (workspaceSlug: string) => [
|
||||||
name: "Workspace invites",
|
name: "Workspace invites",
|
||||||
href: "/invitations",
|
href: "/invitations",
|
||||||
icon: Mails,
|
icon: Mails,
|
||||||
|
access: [EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "settings",
|
key: "settings",
|
||||||
name: "Workspace settings",
|
name: "Workspace settings",
|
||||||
href: `/${workspaceSlug}/settings`,
|
href: `/${workspaceSlug}/settings`,
|
||||||
icon: Settings,
|
icon: Settings,
|
||||||
|
access: [EUserPermissions.ADMIN],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -46,6 +49,7 @@ export const SidebarDropdown = observer(() => {
|
||||||
signOut,
|
signOut,
|
||||||
} = useUser();
|
} = useUser();
|
||||||
const { updateUserProfile } = useUserProfile();
|
const { updateUserProfile } = useUserProfile();
|
||||||
|
const { allowPermissions } = useUserPermissions();
|
||||||
|
|
||||||
const isUserInstanceAdmin = false;
|
const isUserInstanceAdmin = false;
|
||||||
const { currentWorkspace: activeWorkspace, workspaces } = useWorkspace();
|
const { currentWorkspace: activeWorkspace, workspaces } = useWorkspace();
|
||||||
|
|
@ -168,7 +172,7 @@ export const SidebarDropdown = observer(() => {
|
||||||
alt="Workspace Logo"
|
alt="Workspace Logo"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
workspace?.name?.charAt(0) ?? "..."
|
(workspace?.name?.charAt(0) ?? "...")
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<h5
|
<h5
|
||||||
|
|
@ -207,24 +211,27 @@ export const SidebarDropdown = observer(() => {
|
||||||
Create workspace
|
Create workspace
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Link>
|
</Link>
|
||||||
{userLinks(workspaceSlug?.toString() ?? "").map((link, index) => (
|
{userLinks(workspaceSlug?.toString() ?? "").map(
|
||||||
<Link
|
(link, index) =>
|
||||||
key={link.key}
|
allowPermissions(link.access, EUserPermissionsLevel.WORKSPACE) && (
|
||||||
href={link.href}
|
<Link
|
||||||
className="w-full"
|
key={link.key}
|
||||||
onClick={() => {
|
href={link.href}
|
||||||
if (index > 0) handleItemClick();
|
className="w-full"
|
||||||
}}
|
onClick={() => {
|
||||||
>
|
if (index > 0) handleItemClick();
|
||||||
<Menu.Item
|
}}
|
||||||
as="div"
|
>
|
||||||
className="flex items-center gap-2 rounded px-2 py-1 text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80"
|
<Menu.Item
|
||||||
>
|
as="div"
|
||||||
<link.icon className="h-4 w-4 flex-shrink-0" />
|
className="flex items-center gap-2 rounded px-2 py-1 text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80"
|
||||||
{link.name}
|
>
|
||||||
</Menu.Item>
|
<link.icon className="h-4 w-4 flex-shrink-0" />
|
||||||
</Link>
|
{link.name}
|
||||||
))}
|
</Menu.Item>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full px-4 py-2">
|
<div className="w-full px-4 py-2">
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue