From 973cceff79b2cc6dc5a55ec49c7f9540a78c77f1 Mon Sep 17 00:00:00 2001 From: Eduard Gert Date: Wed, 27 Mar 2024 16:09:58 +0100 Subject: [PATCH] Add setting to change dashboard view for regular users (#362) --- src/app/(dashboard)/peers/page.tsx | 8 +- src/app/(dashboard)/settings/page.tsx | 13 ++- src/contexts/GroupsProvider.tsx | 8 +- src/contexts/UsersProvider.tsx | 17 +++- src/interfaces/Account.ts | 1 + src/interfaces/Permission.ts | 3 + src/interfaces/User.ts | 3 + src/layouts/DashboardLayout.tsx | 6 +- src/layouts/Header.tsx | 5 +- src/modules/settings/PermissionsTab.tsx | 100 ++++++++++++++++++++++++ src/modules/users/ServiceUserModal.tsx | 6 +- 11 files changed, 159 insertions(+), 11 deletions(-) create mode 100644 src/interfaces/Permission.ts create mode 100644 src/modules/settings/PermissionsTab.tsx diff --git a/src/app/(dashboard)/peers/page.tsx b/src/app/(dashboard)/peers/page.tsx index 5aeb401b..5b4d75aa 100644 --- a/src/app/(dashboard)/peers/page.tsx +++ b/src/app/(dashboard)/peers/page.tsx @@ -17,11 +17,15 @@ import { SetupModalContent } from "@/modules/setup-netbird-modal/SetupModal"; const PeersTable = lazy(() => import("@/modules/peers/PeersTable")); export default function Peers() { - const { isUser } = useLoggedInUser(); + const { permission } = useLoggedInUser(); return ( - + {permission?.dashboard_view === "blocked" ? ( + + ) : ( + + )} ); } diff --git a/src/app/(dashboard)/settings/page.tsx b/src/app/(dashboard)/settings/page.tsx index 861e733b..a44333da 100644 --- a/src/app/(dashboard)/settings/page.tsx +++ b/src/app/(dashboard)/settings/page.tsx @@ -2,7 +2,12 @@ import { RestrictedAccess } from "@components/ui/RestrictedAccess"; import { VerticalTabs } from "@components/VerticalTabs"; -import { AlertOctagonIcon, FolderGit2Icon, ShieldIcon } from "lucide-react"; +import { + AlertOctagonIcon, + FolderGit2Icon, + LockIcon, + ShieldIcon, +} from "lucide-react"; import React, { useState } from "react"; import { useLoggedInUser } from "@/contexts/UsersProvider"; import PageContainer from "@/layouts/PageContainer"; @@ -10,6 +15,7 @@ import { useAccount } from "@/modules/account/useAccount"; import AuthenticationTab from "@/modules/settings/AuthenticationTab"; import DangerZoneTab from "@/modules/settings/DangerZoneTab"; import GroupsTab from "@/modules/settings/GroupsTab"; +import PermissionsTab from "@/modules/settings/PermissionsTab"; export default function NetBirdSettings() { const [tab, setTab] = useState("authentication"); @@ -28,6 +34,10 @@ export default function NetBirdSettings() { Groups + + + Permissions + Danger zone @@ -36,6 +46,7 @@ export default function NetBirdSettings() {
{account && } + {account && } {account && } {account && }
diff --git a/src/contexts/GroupsProvider.tsx b/src/contexts/GroupsProvider.tsx index c975cf0b..7402c1a1 100644 --- a/src/contexts/GroupsProvider.tsx +++ b/src/contexts/GroupsProvider.tsx @@ -20,9 +20,13 @@ const GroupContext = React.createContext( export default function GroupsProvider({ children }: Props) { const path = usePathname(); - const { isUser } = useLoggedInUser(); + const { permission } = useLoggedInUser(); - return {children}; + return path === "/peers" && permission.dashboard_view == "blocked" ? ( + <>{children} + ) : ( + {children} + ); } export function GroupsProviderContent({ children }: Props) { diff --git a/src/contexts/UsersProvider.tsx b/src/contexts/UsersProvider.tsx index 3c51478c..8a72c22d 100644 --- a/src/contexts/UsersProvider.tsx +++ b/src/contexts/UsersProvider.tsx @@ -1,6 +1,7 @@ import FullScreenLoading from "@components/ui/FullScreenLoading"; import useFetchApi from "@utils/api"; import React, { useMemo } from "react"; +import { Permission } from "@/interfaces/Permission"; import { User } from "@/interfaces/User"; type Props = { @@ -43,5 +44,19 @@ export const useLoggedInUser = () => { const isAdmin = loggedInUser ? loggedInUser?.role === "admin" : false; const isUser = !isOwner && !isAdmin; const isOwnerOrAdmin = isOwner || isAdmin; - return { loggedInUser, isOwner, isAdmin, isUser, isOwnerOrAdmin } as const; + + const permission = useMemo(() => { + return { + dashboard_view: loggedInUser?.permissions.dashboard_view || "blocked", + } as Permission; + }, [loggedInUser]); + + return { + loggedInUser, + isOwner, + isAdmin, + isUser, + isOwnerOrAdmin, + permission, + } as const; }; diff --git a/src/interfaces/Account.ts b/src/interfaces/Account.ts index d98a0f43..c9515054 100644 --- a/src/interfaces/Account.ts +++ b/src/interfaces/Account.ts @@ -10,5 +10,6 @@ export interface Account { jwt_groups_enabled: boolean; jwt_groups_claim_name: string; jwt_allow_groups: string[]; + regular_users_view_blocked: boolean; }; } diff --git a/src/interfaces/Permission.ts b/src/interfaces/Permission.ts new file mode 100644 index 00000000..5bf318ca --- /dev/null +++ b/src/interfaces/Permission.ts @@ -0,0 +1,3 @@ +export interface Permission { + dashboard_view: "limited" | "full" | "blocked"; +} diff --git a/src/interfaces/User.ts b/src/interfaces/User.ts index 04be6a40..84df502a 100644 --- a/src/interfaces/User.ts +++ b/src/interfaces/User.ts @@ -1,3 +1,5 @@ +import { Permission } from "@/interfaces/Permission"; + export interface User { id: string; email?: string; @@ -9,6 +11,7 @@ export interface User { is_service_user?: boolean; is_blocked?: boolean; last_login?: Date; + permissions: Permission; } export enum Role { diff --git a/src/layouts/DashboardLayout.tsx b/src/layouts/DashboardLayout.tsx index 5ed7ed10..f0247a64 100644 --- a/src/layouts/DashboardLayout.tsx +++ b/src/layouts/DashboardLayout.tsx @@ -42,7 +42,7 @@ function DashboardPageContent({ children }: { children: React.ReactNode }) { const { mobileNavOpen, toggleMobileNav } = useApplicationContext(); const isSm = useIsSm(); const isXs = useIsXs(); - const { isUser } = useLoggedInUser(); + const { permission } = useLoggedInUser(); const navOpenPageWidth = isSm ? "50%" : isXs ? "65%" : "80%"; const { bannerHeight } = useAnnouncement(); @@ -154,7 +154,9 @@ function DashboardPageContent({ children }: { children: React.ReactNode }) { height: `calc(100vh - ${headerHeight + bannerHeight}px)`, }} > - + {permission.dashboard_view !== "blocked" && ( + + )} {children} diff --git a/src/layouts/Header.tsx b/src/layouts/Header.tsx index e3c48fcf..60246417 100644 --- a/src/layouts/Header.tsx +++ b/src/layouts/Header.tsx @@ -40,7 +40,7 @@ export default function NavbarWithDropdown() { const { toggleMobileNav } = useApplicationContext(); const { bannerHeight } = useAnnouncement(); - const { isUser } = useLoggedInUser(); + const { permission } = useLoggedInUser(); return ( <> @@ -62,7 +62,8 @@ export default function NavbarWithDropdown() { + + +
+ + + Restrict dashboard for regular users + + } + helpText={ + "Access to the dashboard will be limited and regular users will not be able to view any peers." + } + /> +
+ + + ); +} diff --git a/src/modules/users/ServiceUserModal.tsx b/src/modules/users/ServiceUserModal.tsx index 77abb41b..cd5f5684 100644 --- a/src/modules/users/ServiceUserModal.tsx +++ b/src/modules/users/ServiceUserModal.tsx @@ -100,7 +100,11 @@ export function ServiceUserModalContent({ onSuccess }: ModalProps) { /> - +