mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-15 09:26:40 +00:00
Update libraries to resolve critical security findings
This commit is contained in:
@@ -62,13 +62,11 @@ const createSiteFormSchema = z
|
||||
.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(2, {
|
||||
message: "Name must be at least 2 characters."
|
||||
})
|
||||
.min(2, { message: "Name must be at least 2 characters." })
|
||||
.max(30, {
|
||||
message: "Name must not be longer than 30 characters."
|
||||
}),
|
||||
method: z.string(),
|
||||
method: z.enum(["newt", "wireguard", "local"]),
|
||||
copied: z.boolean()
|
||||
})
|
||||
.refine(
|
||||
@@ -86,6 +84,15 @@ const createSiteFormSchema = z
|
||||
|
||||
type CreateSiteFormValues = z.infer<typeof createSiteFormSchema>;
|
||||
|
||||
type SiteType = "newt" | "wireguard" | "local";
|
||||
|
||||
interface TunnelTypeOption {
|
||||
id: SiteType;
|
||||
title: string;
|
||||
description: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
type Commands = {
|
||||
mac: Record<string, string[]>;
|
||||
linux: Record<string, string[]>;
|
||||
@@ -99,7 +106,9 @@ export default function Page() {
|
||||
const { orgId } = useParams();
|
||||
const router = useRouter();
|
||||
|
||||
const [tunnelTypes, setTunnelTypes] = useState<any>([
|
||||
const [tunnelTypes, setTunnelTypes] = useState<
|
||||
ReadonlyArray<TunnelTypeOption>
|
||||
>([
|
||||
{
|
||||
id: "newt",
|
||||
title: "Newt Tunnel (Recommended)",
|
||||
@@ -310,22 +319,15 @@ PersistentKeepalive = 5`;
|
||||
}
|
||||
};
|
||||
|
||||
const form = useForm({
|
||||
const form = useForm<CreateSiteFormValues>({
|
||||
resolver: zodResolver(createSiteFormSchema),
|
||||
defaultValues: {
|
||||
name: "",
|
||||
copied: false,
|
||||
method: "newt"
|
||||
}
|
||||
defaultValues: { name: "", copied: false, method: "newt" }
|
||||
});
|
||||
|
||||
async function onSubmit(data: CreateSiteFormValues) {
|
||||
setCreateLoading(true);
|
||||
|
||||
let payload: CreateSiteBody = {
|
||||
name: data.name,
|
||||
type: data.method
|
||||
};
|
||||
let payload: CreateSiteBody = { name: data.name, type: data.method };
|
||||
|
||||
if (data.method == "wireguard") {
|
||||
if (!siteDefaults || !wgConfig) {
|
||||
@@ -454,10 +456,7 @@ PersistentKeepalive = 5`;
|
||||
|
||||
setTunnelTypes((prev: any) => {
|
||||
return prev.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
disabled: false
|
||||
};
|
||||
return { ...item, disabled: false };
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -532,9 +531,8 @@ PersistentKeepalive = 5`;
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
<FormDescription>
|
||||
This is the
|
||||
display name for the
|
||||
site.
|
||||
This is the display
|
||||
name for the site.
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -558,12 +556,10 @@ PersistentKeepalive = 5`;
|
||||
<SettingsSectionBody>
|
||||
<StrategySelect
|
||||
options={tunnelTypes}
|
||||
defaultValue={
|
||||
form.getValues("method") as string
|
||||
}
|
||||
onChange={(value) =>
|
||||
form.setValue("method", value)
|
||||
}
|
||||
defaultValue={form.getValues("method")}
|
||||
onChange={(value) => {
|
||||
form.setValue("method", value);
|
||||
}}
|
||||
cols={3}
|
||||
/>
|
||||
</SettingsSectionBody>
|
||||
|
||||
@@ -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" />
|
||||
</svg>
|
||||
{/* 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}!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,38 +4,39 @@ import { cn } from "@app/lib/cn";
|
||||
import { RadioGroup, RadioGroupItem } from "./ui/radio-group";
|
||||
import { useState } from "react";
|
||||
|
||||
interface StrategyOption {
|
||||
id: string;
|
||||
interface StrategyOption<TValue extends string> {
|
||||
id: TValue;
|
||||
title: string;
|
||||
description: string;
|
||||
disabled?: boolean; // New optional property
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
interface StrategySelectProps {
|
||||
options: StrategyOption[];
|
||||
defaultValue?: string;
|
||||
onChange?: (value: string) => void;
|
||||
interface StrategySelectProps<TValue extends string> {
|
||||
options: ReadonlyArray<StrategyOption<TValue>>;
|
||||
defaultValue?: TValue;
|
||||
onChange?: (value: TValue) => void;
|
||||
cols?: number;
|
||||
}
|
||||
|
||||
export function StrategySelect({
|
||||
export function StrategySelect<TValue extends string>({
|
||||
options,
|
||||
defaultValue,
|
||||
onChange,
|
||||
cols
|
||||
}: StrategySelectProps) {
|
||||
const [selected, setSelected] = useState(defaultValue);
|
||||
}: StrategySelectProps<TValue>) {
|
||||
const [selected, setSelected] = useState<TValue | undefined>(defaultValue);
|
||||
|
||||
return (
|
||||
<RadioGroup
|
||||
defaultValue={defaultValue}
|
||||
onValueChange={(value) => {
|
||||
setSelected(value);
|
||||
onChange?.(value);
|
||||
onValueChange={(value: string) => {
|
||||
const typedValue = value as TValue;
|
||||
setSelected(typedValue);
|
||||
onChange?.(typedValue);
|
||||
}}
|
||||
className={`grid md:grid-cols-${cols ? cols : 1} gap-4`}
|
||||
>
|
||||
{options.map((option) => (
|
||||
{options.map((option: StrategyOption<TValue>) => (
|
||||
<label
|
||||
key={option.id}
|
||||
htmlFor={option.id}
|
||||
|
||||
Reference in New Issue
Block a user