Update libraries to resolve critical security findings

This commit is contained in:
grokdesigns 2025-04-08 12:51:06 -07:00
parent 787a172a7c
commit 7fd1652a71
5 changed files with 1061 additions and 1513 deletions

2472
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -40,12 +40,13 @@
"@radix-ui/react-switch": "1.1.2", "@radix-ui/react-switch": "1.1.2",
"@radix-ui/react-tabs": "1.1.2", "@radix-ui/react-tabs": "1.1.2",
"@radix-ui/react-toast": "1.2.4", "@radix-ui/react-toast": "1.2.4",
"@react-email/components": "0.0.31", "@react-email/components": "0.0.36",
"@react-email/render": "^1.0.6",
"@react-email/tailwind": "1.0.4", "@react-email/tailwind": "1.0.4",
"@tanstack/react-table": "8.20.6", "@tanstack/react-table": "8.20.6",
"axios": "1.7.9", "axios": "1.8.4",
"better-sqlite3": "11.7.0", "better-sqlite3": "11.7.0",
"canvas-confetti": "^1.9.3", "canvas-confetti": "1.9.3",
"class-variance-authority": "0.7.1", "class-variance-authority": "0.7.1",
"clsx": "2.1.1", "clsx": "2.1.1",
"cmdk": "1.0.4", "cmdk": "1.0.4",
@ -64,7 +65,7 @@
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"lucide-react": "0.469.0", "lucide-react": "0.469.0",
"moment": "2.30.1", "moment": "2.30.1",
"next": "15.1.3", "next": "15.2.4",
"next-themes": "0.4.4", "next-themes": "0.4.4",
"node-cache": "5.1.2", "node-cache": "5.1.2",
"node-fetch": "3.3.2", "node-fetch": "3.3.2",
@ -105,14 +106,14 @@
"@types/swagger-ui-express": "^4.1.8", "@types/swagger-ui-express": "^4.1.8",
"@types/ws": "8.5.13", "@types/ws": "8.5.13",
"@types/yargs": "17.0.33", "@types/yargs": "17.0.33",
"drizzle-kit": "0.30.1", "drizzle-kit": "0.30.6",
"esbuild": "0.24.2", "esbuild": "0.25.2",
"esbuild-node-externals": "1.16.0", "esbuild-node-externals": "1.18.0",
"postcss": "^8", "postcss": "^8",
"react-email": "3.0.4", "react-email": "4.0.5",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tsc-alias": "1.8.10", "tsc-alias": "1.8.10",
"tsx": "4.19.2", "tsx": "4.19.3",
"typescript": "^5", "typescript": "^5",
"yargs": "17.7.2" "yargs": "17.7.2"
}, },

View file

@ -62,13 +62,11 @@ const createSiteFormSchema = z
.object({ .object({
name: z name: z
.string() .string()
.min(2, { .min(2, { message: "Name must be at least 2 characters." })
message: "Name must be at least 2 characters."
})
.max(30, { .max(30, {
message: "Name must not be longer than 30 characters." message: "Name must not be longer than 30 characters."
}), }),
method: z.string(), method: z.enum(["newt", "wireguard", "local"]),
copied: z.boolean() copied: z.boolean()
}) })
.refine( .refine(
@ -86,6 +84,15 @@ const createSiteFormSchema = z
type CreateSiteFormValues = z.infer<typeof createSiteFormSchema>; type CreateSiteFormValues = z.infer<typeof createSiteFormSchema>;
type SiteType = "newt" | "wireguard" | "local";
interface TunnelTypeOption {
id: SiteType;
title: string;
description: string;
disabled?: boolean;
}
type Commands = { type Commands = {
mac: Record<string, string[]>; mac: Record<string, string[]>;
linux: Record<string, string[]>; linux: Record<string, string[]>;
@ -99,7 +106,9 @@ export default function Page() {
const { orgId } = useParams(); const { orgId } = useParams();
const router = useRouter(); const router = useRouter();
const [tunnelTypes, setTunnelTypes] = useState<any>([ const [tunnelTypes, setTunnelTypes] = useState<
ReadonlyArray<TunnelTypeOption>
>([
{ {
id: "newt", id: "newt",
title: "Newt Tunnel (Recommended)", title: "Newt Tunnel (Recommended)",
@ -310,22 +319,15 @@ PersistentKeepalive = 5`;
} }
}; };
const form = useForm({ const form = useForm<CreateSiteFormValues>({
resolver: zodResolver(createSiteFormSchema), resolver: zodResolver(createSiteFormSchema),
defaultValues: { defaultValues: { name: "", copied: false, method: "newt" }
name: "",
copied: false,
method: "newt"
}
}); });
async function onSubmit(data: CreateSiteFormValues) { async function onSubmit(data: CreateSiteFormValues) {
setCreateLoading(true); setCreateLoading(true);
let payload: CreateSiteBody = { let payload: CreateSiteBody = { name: data.name, type: data.method };
name: data.name,
type: data.method
};
if (data.method == "wireguard") { if (data.method == "wireguard") {
if (!siteDefaults || !wgConfig) { if (!siteDefaults || !wgConfig) {
@ -454,10 +456,7 @@ PersistentKeepalive = 5`;
setTunnelTypes((prev: any) => { setTunnelTypes((prev: any) => {
return prev.map((item: any) => { return prev.map((item: any) => {
return { return { ...item, disabled: false };
...item,
disabled: false
};
}); });
}); });
} }
@ -532,9 +531,8 @@ PersistentKeepalive = 5`;
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
<FormDescription> <FormDescription>
This is the This is the display
display name for the name for the site.
site.
</FormDescription> </FormDescription>
</FormItem> </FormItem>
)} )}
@ -558,12 +556,10 @@ PersistentKeepalive = 5`;
<SettingsSectionBody> <SettingsSectionBody>
<StrategySelect <StrategySelect
options={tunnelTypes} options={tunnelTypes}
defaultValue={ defaultValue={form.getValues("method")}
form.getValues("method") as string onChange={(value) => {
} form.setValue("method", value);
onChange={(value) => }}
form.setValue("method", value)
}
cols={3} cols={3}
/> />
</SettingsSectionBody> </SettingsSectionBody>

View file

@ -38,7 +38,7 @@ export default function SupporterMessage({ tier }: { tier: string }) {
<path d="M12 .587l3.668 7.431 8.2 1.192-5.934 5.782 1.4 8.168L12 18.896l-7.334 3.864 1.4-8.168L.132 9.21l8.2-1.192z" /> <path d="M12 .587l3.668 7.431 8.2 1.192-5.934 5.782 1.4 8.168L12 18.896l-7.334 3.864 1.4-8.168L.132 9.21l8.2-1.192z" />
</svg> </svg>
{/* Popover */} {/* Popover */}
<div className="absolute left-1/2 transform -translate-x-1/2 -top-10 hidden group-hover:block bg-white/10 backdrop-blur-md text-primary text-sm rounded-md shadow-lg px-4 py-2"> <div className="absolute left-1/2 transform -translate-x-1/2 -top-10 hidden group-hover:block bg-white/10 text-primary text-sm rounded-md shadow-lg px-4 py-2 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
Thank you for supporting Pangolin as a {tier}! Thank you for supporting Pangolin as a {tier}!
</div> </div>
</div> </div>

View file

@ -4,38 +4,39 @@ import { cn } from "@app/lib/cn";
import { RadioGroup, RadioGroupItem } from "./ui/radio-group"; import { RadioGroup, RadioGroupItem } from "./ui/radio-group";
import { useState } from "react"; import { useState } from "react";
interface StrategyOption { interface StrategyOption<TValue extends string> {
id: string; id: TValue;
title: string; title: string;
description: string; description: string;
disabled?: boolean; // New optional property disabled?: boolean;
} }
interface StrategySelectProps { interface StrategySelectProps<TValue extends string> {
options: StrategyOption[]; options: ReadonlyArray<StrategyOption<TValue>>;
defaultValue?: string; defaultValue?: TValue;
onChange?: (value: string) => void; onChange?: (value: TValue) => void;
cols?: number; cols?: number;
} }
export function StrategySelect({ export function StrategySelect<TValue extends string>({
options, options,
defaultValue, defaultValue,
onChange, onChange,
cols cols
}: StrategySelectProps) { }: StrategySelectProps<TValue>) {
const [selected, setSelected] = useState(defaultValue); const [selected, setSelected] = useState<TValue | undefined>(defaultValue);
return ( return (
<RadioGroup <RadioGroup
defaultValue={defaultValue} defaultValue={defaultValue}
onValueChange={(value) => { onValueChange={(value: string) => {
setSelected(value); const typedValue = value as TValue;
onChange?.(value); setSelected(typedValue);
onChange?.(typedValue);
}} }}
className={`grid md:grid-cols-${cols ? cols : 1} gap-4`} className={`grid md:grid-cols-${cols ? cols : 1} gap-4`}
> >
{options.map((option) => ( {options.map((option: StrategyOption<TValue>) => (
<label <label
key={option.id} key={option.id}
htmlFor={option.id} htmlFor={option.id}