Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Access Control Groups & various UI / UX improvements #415

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ jobs:
with:
only_warn: 1
skip: package-lock.json,*.svg
ignore_words_list: mappin
ignore_words_list: mappin, allTime
17 changes: 10 additions & 7 deletions src/app/(dashboard)/access-control/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import SkeletonTable from "@components/skeletons/SkeletonTable";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon } from "lucide-react";
import React, { lazy, Suspense } from "react";
Expand All @@ -20,6 +21,9 @@ const AccessControlTable = lazy(
export default function AccessControlPage() {
const { data: policies, isLoading } = useFetchApi<Policy[]>("/policies");

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<GroupsProvider>
Expand All @@ -31,12 +35,7 @@ export default function AccessControlPage() {
icon={<AccessControlIcon size={14} />}
/>
</Breadcrumbs>

<h1>
{policies && policies.length > 1
? `${policies.length} Access Control Policies`
: "Access Control Policies"}
</h1>
<h1 ref={headingRef}>Access Control Policies</h1>
<Paragraph>
Create rules to manage access in your network and define what peers
can connect.
Expand All @@ -57,7 +56,11 @@ export default function AccessControlPage() {
<RestrictedAccess page={"Access Control"}>
<PoliciesProvider>
<Suspense fallback={<SkeletonTable />}>
<AccessControlTable isLoading={isLoading} policies={policies} />
<AccessControlTable
isLoading={isLoading}
policies={policies}
headingTarget={portalTarget}
/>
</Suspense>
</PoliciesProvider>
</RestrictedAccess>
Expand Down
16 changes: 10 additions & 6 deletions src/app/(dashboard)/activity/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Breadcrumbs from "@components/Breadcrumbs";
import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon } from "lucide-react";
import React from "react";
Expand All @@ -15,6 +16,9 @@ import ActivityTable from "@/modules/activity/ActivityTable";
export default function Activity() {
const { data: events, isLoading } = useFetchApi<ActivityEvent[]>("/events");

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<div className={"p-default py-6"}>
Expand All @@ -25,11 +29,7 @@ export default function Activity() {
icon={<ActivityIcon size={13} />}
/>
</Breadcrumbs>
<h1>
{events && events.length > 1
? `${events.length} Activity Events`
: "Activity Events"}
</h1>
<h1 ref={headingRef}>Activity Events</h1>
<Paragraph>
Here you can see all the account and network activity events.
</Paragraph>
Expand All @@ -48,7 +48,11 @@ export default function Activity() {
</Paragraph>
</div>
<RestrictedAccess page={"Activity"}>
<ActivityTable events={events} isLoading={isLoading} />
<ActivityTable
events={events}
isLoading={isLoading}
headingTarget={portalTarget}
/>
</RestrictedAccess>
</PageContainer>
);
Expand Down
11 changes: 6 additions & 5 deletions src/app/(dashboard)/dns/nameservers/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import SkeletonTable from "@components/skeletons/SkeletonTable";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon, ServerIcon } from "lucide-react";
import React, { lazy, Suspense } from "react";
Expand All @@ -20,6 +21,9 @@ export default function NameServers() {
const { data: nameserverGroups, isLoading } =
useFetchApi<NameserverGroup[]>("/dns/nameservers");

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<div className={"p-default py-6"}>
Expand All @@ -36,11 +40,7 @@ export default function NameServers() {
icon={<ServerIcon size={13} />}
/>
</Breadcrumbs>
<h1>
{nameserverGroups && nameserverGroups.length > 1
? `${nameserverGroups.length} Nameservers`
: "Nameservers"}
</h1>
<h1 ref={headingRef}>Nameservers</h1>
<Paragraph>
Add nameservers for domain name resolution in your NetBird network.
</Paragraph>
Expand All @@ -62,6 +62,7 @@ export default function NameServers() {
<NameserverGroupTable
nameserverGroups={nameserverGroups}
isLoading={isLoading}
headingTarget={portalTarget}
/>
</Suspense>
</RestrictedAccess>
Expand Down
11 changes: 6 additions & 5 deletions src/app/(dashboard)/network-routes/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import SkeletonTable from "@components/skeletons/SkeletonTable";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon } from "lucide-react";
import React, { lazy, Suspense } from "react";
Expand All @@ -23,6 +24,9 @@ export default function NetworkRoutes() {
const { data: routes, isLoading } = useFetchApi<Route[]>("/routes");
const groupedRoutes = useGroupedRoutes({ routes });

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<RoutesProvider>
Expand All @@ -35,11 +39,7 @@ export default function NetworkRoutes() {
icon={<NetworkRoutesIcon size={13} />}
/>
</Breadcrumbs>
<h1>
{groupedRoutes && groupedRoutes.length > 1
? `${groupedRoutes.length} Network Routes`
: "Network Routes"}
</h1>
<h1 ref={headingRef}>Network Routes</h1>
<Paragraph>
Network routes allow you to access other networks like LANs and
VPCs without installing NetBird on every resource.
Expand All @@ -65,6 +65,7 @@ export default function NetworkRoutes() {
isLoading={isLoading}
groupedRoutes={groupedRoutes}
routes={routes}
headingTarget={portalTarget}
/>
</Suspense>
</RestrictedAccess>
Expand Down
44 changes: 15 additions & 29 deletions src/app/(dashboard)/peer/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Separator from "@components/Separator";
import FullScreenLoading from "@components/ui/FullScreenLoading";
import LoginExpiredBadge from "@components/ui/LoginExpiredBadge";
import TextWithTooltip from "@components/ui/TextWithTooltip";
import { getOperatingSystem } from "@hooks/useOperatingSystem";
import useRedirect from "@hooks/useRedirect";
import { IconCloudLock, IconInfoCircle } from "@tabler/icons-react";
import useFetchApi from "@utils/api";
Expand Down Expand Up @@ -54,15 +55,12 @@ import PeerProvider, { usePeer } from "@/contexts/PeerProvider";
import RoutesProvider from "@/contexts/RoutesProvider";
import { useLoggedInUser } from "@/contexts/UsersProvider";
import { useHasChanges } from "@/hooks/useHasChanges";
import { getOperatingSystem } from "@/hooks/useOperatingSystem";
import { OperatingSystem } from "@/interfaces/OperatingSystem";
import type { Peer } from "@/interfaces/Peer";
import PageContainer from "@/layouts/PageContainer";
import { AddExitNodeButton } from "@/modules/exit-node/AddExitNodeButton";
import { useHasExitNodes } from "@/modules/exit-node/useHasExitNodes";
import useGroupHelper from "@/modules/groups/useGroupHelper";
import AddRouteDropdownButton from "@/modules/peer/AddRouteDropdownButton";
import PeerRoutesTable from "@/modules/peer/PeerRoutesTable";
import { AccessiblePeersSection } from "@/modules/peer/AccessiblePeersSection";
import { PeerNetworkRoutesSection } from "@/modules/peer/PeerNetworkRoutesSection";

export default function PeerPage() {
const queryParameter = useSearchParams();
Expand All @@ -72,7 +70,7 @@ export default function PeerPage() {
useRedirect("/peers", false, !peerId);

return peer && !isLoading ? (
<PeerProvider peer={peer}>
<PeerProvider peer={peer} key={peerId}>
<PeerOverview />
</PeerProvider>
) : (
Expand Down Expand Up @@ -133,7 +131,6 @@ function PeerOverview() {
};

const { isUser } = useLoggedInUser();
const hasExitNodes = useHasExitNodes(peer);

return (
<PageContainer>
Expand Down Expand Up @@ -336,30 +333,19 @@ function PeerOverview() {
</div>
</div>

<Separator />

{isLinux && !isUser ? (
<div className={"px-8 py-6"}>
<div className={"max-w-6xl"}>
<div className={"flex justify-between items-center"}>
<div>
<h2>Network Routes</h2>
<Paragraph>
Access other networks without installing NetBird on every
resource.
</Paragraph>
</div>
<div className={"inline-flex gap-4 justify-end"}>
<div className={"gap-4 flex"}>
<AddExitNodeButton peer={peer} firstTime={!hasExitNodes} />
<AddRouteDropdownButton />
</div>
</div>
</div>
<PeerRoutesTable peer={peer} />
</div>
</div>
<>
<Separator />
<PeerNetworkRoutesSection peer={peer} />
</>
) : null}

{peer?.id && (
<>
<Separator />
<AccessiblePeersSection peerID={peer.id} />
</>
)}
</RoutesProvider>
</PageContainer>
);
Expand Down
16 changes: 10 additions & 6 deletions src/app/(dashboard)/posture-checks/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import SkeletonTable from "@components/skeletons/SkeletonTable";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon, ShieldCheck } from "lucide-react";
import React, { lazy, Suspense } from "react";
Expand All @@ -21,6 +22,9 @@ export default function PostureChecksPage() {
const { data: postureChecks, isLoading } =
useFetchApi<PostureCheck[]>("/posture-checks");

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<GroupsProvider>
Expand All @@ -38,17 +42,16 @@ export default function PostureChecksPage() {
icon={<ShieldCheck size={15} />}
/>
</Breadcrumbs>
<h1>
{postureChecks && postureChecks.length > 1
? `${postureChecks.length} Posture Checks`
: "Posture Checks"}
</h1>
<h1 ref={headingRef}>Posture Checks</h1>
<Paragraph>
Use posture checks to further restrict access in your network.
</Paragraph>
<Paragraph>
Learn more about
<InlineLink href={"https://docs.netbird.io/how-to/manage-posture-checks"} target={"_blank"}>
<InlineLink
href={"https://docs.netbird.io/how-to/manage-posture-checks"}
target={"_blank"}
>
Posture Checks
<ExternalLinkIcon size={12} />
</InlineLink>
Expand All @@ -60,6 +63,7 @@ export default function PostureChecksPage() {
<PoliciesProvider>
<Suspense fallback={<SkeletonTable />}>
<PostureCheckTable
headingTarget={portalTarget}
isLoading={isLoading}
postureChecks={postureChecks}
/>
Expand Down
11 changes: 6 additions & 5 deletions src/app/(dashboard)/setup-keys/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import SkeletonTable from "@components/skeletons/SkeletonTable";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon } from "lucide-react";
import React, { lazy, Suspense, useMemo } from "react";
Expand Down Expand Up @@ -38,6 +39,9 @@ export default function SetupKeys() {
});
}, [setupKeys, groups]);

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<div className={"p-default py-6"}>
Expand All @@ -48,11 +52,7 @@ export default function SetupKeys() {
icon={<SetupKeysIcon size={13} />}
/>
</Breadcrumbs>
<h1>
{setupKeys && setupKeys.length > 1
? `${setupKeys.length} Setup Keys`
: "Setup Keys"}
</h1>
<h1 ref={headingRef}>Setup Keys</h1>
<Paragraph>
Setup keys are pre-authentication keys that allow to register new
machines in your network.
Expand All @@ -74,6 +74,7 @@ export default function SetupKeys() {
<RestrictedAccess page={"Setup Keys"}>
<Suspense fallback={<SkeletonTable />}>
<SetupKeysTable
headingTarget={portalTarget}
setupKeys={setupKeysWithGroups}
isLoading={isLoading}
/>
Expand Down
16 changes: 10 additions & 6 deletions src/app/(dashboard)/team/service-users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import InlineLink from "@components/InlineLink";
import Paragraph from "@components/Paragraph";
import SkeletonTable from "@components/skeletons/SkeletonTable";
import { RestrictedAccess } from "@components/ui/RestrictedAccess";
import { usePortalElement } from "@hooks/usePortalElement";
import { IconSettings2 } from "@tabler/icons-react";
import useFetchApi from "@utils/api";
import { ExternalLinkIcon } from "lucide-react";
Expand All @@ -22,6 +23,9 @@ export default function ServiceUsers() {
"/users?service_user=true",
);

const { ref: headingRef, portalTarget } =
usePortalElement<HTMLHeadingElement>();

return (
<PageContainer>
<div className={"p-default py-6"}>
Expand All @@ -38,11 +42,7 @@ export default function ServiceUsers() {
icon={<IconSettings2 size={17} />}
/>
</Breadcrumbs>
<h1>
{users && users.length > 1
? `${users.length} Service Users`
: "Service Users"}
</h1>
<h1 ref={headingRef}>Service Users</h1>
<Paragraph>
Use service users to create API tokens and avoid losing automated
access.
Expand All @@ -61,7 +61,11 @@ export default function ServiceUsers() {
</div>
<RestrictedAccess page={"Service Users"}>
<Suspense fallback={<SkeletonTable />}>
<ServiceUsersTable users={users} isLoading={isLoading} />
<ServiceUsersTable
users={users}
isLoading={isLoading}
headingTarget={portalTarget}
/>
</Suspense>
</RestrictedAccess>
</PageContainer>
Expand Down
Loading
Loading