Skip to content
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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"ip-cidr": "^3.1.0",
"js-cookie": "^3.0.5",
"lodash": "^4.17.21",
"lucide-react": "^0.479.0",
"lucide-react": "^0.481.0",
"next": "^14.2.28",
"next-themes": "^0.2.1",
"punycode": "^2.3.1",
Expand Down
12 changes: 6 additions & 6 deletions src/app/(dashboard)/peer/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,19 @@ const PeerGeneralInformation = () => {
* Detect if there are changes in the peer information, if there are changes, then enable the save button.
*/
const { hasChanges, updateRef: updateHasChangedRef } = useHasChanges([
name,
ssh,
selectedGroups,
loginExpiration,
inactivityExpiration,
]);

const updatePeer = async () => {
const updatePeer = async (newName?: string) => {
let batchCall: Promise<any>[] = [];
const groupCalls = getAllGroupCalls();

if (permission.peers.update) {
const updateRequest = update({
name,
name: newName ?? name,
ssh,
loginExpiration,
inactivityExpiration,
Expand All @@ -187,7 +186,6 @@ const PeerGeneralInformation = () => {
mutate("/peers/" + peer.id);
mutate("/groups");
updateHasChangedRef([
name,
ssh,
selectedGroups,
loginExpiration,
Expand Down Expand Up @@ -229,8 +227,10 @@ const PeerGeneralInformation = () => {
</ModalTrigger>
<EditNameModal
onSuccess={(newName) => {
setName(newName);
setShowEditNameModal(false);
updatePeer(newName).then(() => {
setName(newName);
setShowEditNameModal(false);
});
}}
peer={peer}
initialName={name}
Expand Down
7 changes: 7 additions & 0 deletions src/app/(dashboard)/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
AlertOctagonIcon,
FolderGit2Icon,
LockIcon,
MonitorSmartphoneIcon,
NetworkIcon,
ShieldIcon,
} from "lucide-react";
Expand All @@ -16,6 +17,7 @@ import { useLoggedInUser } from "@/contexts/UsersProvider";
import PageContainer from "@/layouts/PageContainer";
import { useAccount } from "@/modules/account/useAccount";
import AuthenticationTab from "@/modules/settings/AuthenticationTab";
import ClientSettingsTab from "@/modules/settings/ClientSettingsTab";
import DangerZoneTab from "@/modules/settings/DangerZoneTab";
import GroupsTab from "@/modules/settings/GroupsTab";
import NetworkSettingsTab from "@/modules/settings/NetworkSettingsTab";
Expand Down Expand Up @@ -63,6 +65,10 @@ export default function NetBirdSettings() {
<NetworkIcon size={14} />
Networks
</VerticalTabs.Trigger>
<VerticalTabs.Trigger value="clients">
<MonitorSmartphoneIcon size={14} />
Clients
</VerticalTabs.Trigger>
</>
)}

Expand All @@ -77,6 +83,7 @@ export default function NetBirdSettings() {
{account && <PermissionsTab account={account} />}
{account && <GroupsTab account={account} />}
{account && <NetworkSettingsTab account={account} />}
{account && <ClientSettingsTab account={account} />}
{account && <DangerZoneTab account={account} />}
</div>
</RestrictedAccess>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface Props extends React.HTMLAttributes<HTMLDivElement>, BadgeVariants {
children: React.ReactNode;
className?: string;
useHover?: boolean;
disabled?: boolean;
}

const variants = cva("", {
Expand Down Expand Up @@ -53,6 +54,7 @@ export default function Badge({
className,
variant = "blue",
useHover = false,
disabled = false,
...props
}: Readonly<Props>) {
return (
Expand All @@ -61,6 +63,7 @@ export default function Badge({
"relative z-10 cursor-inherit whitespace-nowrap rounded-md text-[12px] py-1.5 px-3 font-normal flex gap-1.5 items-center justify-center transition-all",
className,
variants({ variant, hover: useHover ? variant : "none" }),
disabled && "cursor-not-allowed opacity-50 select-none",
)}
{...props}
>
Expand Down
10 changes: 9 additions & 1 deletion src/components/ui/InputDomain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type Props = {
onError?: (error: boolean) => void;
error?: string;
disabled?: boolean;
preventLeadingAndTrailingDots?: boolean;
allowWildcard?: boolean;
};
enum ActionType {
ADD = "ADD",
Expand All @@ -40,6 +42,8 @@ export default function InputDomain({
onRemove,
onError,
disabled,
preventLeadingAndTrailingDots,
allowWildcard = true,
}: Readonly<Props>) {
const [name, setName] = useState(value?.name || "");

Expand All @@ -52,7 +56,11 @@ export default function InputDomain({
if (name == "") {
return "";
}
const valid = validator.isValidDomain(name);
const valid = validator.isValidDomain(name, {
allowOnlyTld: true,
allowWildcard,
preventLeadingAndTrailingDots,
});
if (!valid) {
return "Please enter a valid domain, e.g. example.com or intra.example.com";
}
Expand Down
5 changes: 2 additions & 3 deletions src/hooks/useRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ export const useRedirect = (
const intervalRef = useRef<NodeJS.Timeout | null>(null);

useEffect(() => {
// If redirect is disabled or the url is already in the callback urls or the url is the current path then do not redirect
if (!enable || callBackUrls.current.includes(url) || url === currentPath)
return;
// If redirect is disabled or the url is already in the callback urls then do not redirect
if (!enable || callBackUrls.current.includes(url)) return;

const performRedirect = () => {
if (!isRedirecting.current) {
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export interface Account {
regular_users_view_blocked: boolean;
routing_peer_dns_resolution_enabled: boolean;
dns_domain: string;
lazy_connection_enabled: boolean;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import Badge from "@components/Badge";
import { IconCirclePlus } from "@tabler/icons-react";
import { ShieldCheck } from "lucide-react";
import React from "react";
import { usePermissions } from "@/contexts/PermissionsProvider";
import { Policy } from "@/interfaces/Policy";

type Props = {
policy: Policy;
};
export default function AccessControlPostureCheckCell({ policy }: Props) {
const { permission } = usePermissions();

const isDisabled = !permission.policies.create || !permission.policies.update;

return policy.source_posture_checks &&
policy.source_posture_checks.length > 0 ? (
<div className={"flex"}>
Expand All @@ -18,7 +23,14 @@ export default function AccessControlPostureCheckCell({ policy }: Props) {
</div>
) : (
<div className={"flex"}>
<Badge variant={"gray"} useHover={true}>
<Badge
variant={"gray"}
useHover={!isDisabled}
onClick={(e) => {
if (isDisabled) e.stopPropagation();
}}
disabled={isDisabled}
>
<IconCirclePlus size={14} />
Add Posture Check
</Badge>
Expand Down
9 changes: 7 additions & 2 deletions src/modules/access-control/table/AccessControlTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import DataTableRefreshButton from "@components/table/DataTableRefreshButton";
import { DataTableRowsPerPage } from "@components/table/DataTableRowsPerPage";
import GetStartedTest from "@components/ui/GetStartedTest";
import type { ColumnDef, SortingState } from "@tanstack/react-table";
import { removeAllSpaces } from "@utils/helpers";
import { ExternalLinkIcon, PlusCircle } from "lucide-react";
import { usePathname } from "next/navigation";
import React, { useState } from "react";
Expand Down Expand Up @@ -37,16 +38,20 @@ type Props = {

export const AccessControlTableColumns: ColumnDef<Policy>[] = [
{
accessorKey: "name",
id: "name",
accessorFn: (row) => removeAllSpaces(row?.name),
header: ({ column }) => {
return <DataTableHeader column={column}>Name</DataTableHeader>;
},
sortingFn: "text",
filterFn: "fuzzy",
cell: ({ cell }) => <AccessControlNameCell policy={cell.row.original} />,
},
{
accessorKey: "description",
id: "description",
accessorFn: (row) => removeAllSpaces(row?.description),
sortingFn: "text",
filterFn: "fuzzy",
},
{
id: "enabled",
Expand Down
2 changes: 2 additions & 0 deletions src/modules/dns-nameservers/NameserverModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ export function NameserverModalContent({
{domains.map((domain, i) => {
return (
<InputDomain
preventLeadingAndTrailingDots={true}
allowWildcard={false}
key={domain.id}
value={domain}
onChange={(d) =>
Expand Down
6 changes: 3 additions & 3 deletions src/modules/groups/useGroupHelper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useApiCall } from "@utils/api";
import { isEmpty } from "lodash";
import { isEmpty, orderBy } from "lodash";
import { useMemo, useState } from "react";
import { useSWRConfig } from "swr";
import { useGroups } from "@/contexts/GroupsProvider";
Expand All @@ -20,13 +20,13 @@ export default function useGroupHelper({ initial = [], peer }: Props) {
const initialGroups = useMemo(() => {
if (!initial) return [];
const isArrayOfStrings = initial.every((item) => typeof item === "string");
if (!isArrayOfStrings) return initial as Group[];
if (!isArrayOfStrings) return orderBy(initial as Group[], ["name"]);
const foundGroups = initial
.map((id) => {
return groups?.find((g) => g.id === id);
})
.filter((g) => g !== undefined) as Group[];
return foundGroups ?? [];
return orderBy(foundGroups, ["name"]) ?? [];
}, [groups, initial]);

const [selectedGroups, setSelectedGroups] = useState<Group[]>(initialGroups);
Expand Down
2 changes: 1 addition & 1 deletion src/modules/networks/resources/NetworkResourceModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export function ResourceModalContent({
<ResourceSingleAddressInput value={address} onChange={setAddress} />

<div>
<Label>Assigned Groups</Label>
<Label>Destination Groups</Label>
<HelpText>
Add this resource to groups and use them as destinations when
creating policies
Expand Down
7 changes: 6 additions & 1 deletion src/modules/posture-checks/table/PostureCheckTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ export default function PostureCheckTable({
<Button
variant={"primary"}
className={"ml-auto"}
disabled={!permission.policies.create}
disabled={
!permission.policies.create || !permission.policies.update
}
onClick={() => {
setCurrentRow(undefined);
setPostureCheckModal(true);
Expand Down Expand Up @@ -176,6 +178,9 @@ export default function PostureCheckTable({
<Button
variant={"primary"}
className={"ml-auto"}
disabled={
!permission.policies.create || !permission.policies.update
}
onClick={() => setPostureCheckModal(true)}
>
<IconCirclePlus size={16} />
Expand Down
Loading