made the mods vulnerabilities

This commit is contained in:
Cypro Freelance 2024-08-01 00:13:04 +05:30
parent a162f66b30
commit deb62f9730
13 changed files with 628 additions and 109 deletions

View file

@ -16,6 +16,7 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
const { toast } = useToast(); const { toast } = useToast();
const [title, setTitle] = useState(""); const [title, setTitle] = useState("");
const [content, setContent] = useState(""); const [content, setContent] = useState("");
const [vulnerabilities, setVulnerabilities] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
useEffect(() => { useEffect(() => {
@ -25,6 +26,7 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
.then((data) => { .then((data) => {
setTitle(data.title); setTitle(data.title);
setContent(data.content); setContent(data.content);
setVulnerabilities(data.vulnerabilities || "");
}) })
.catch((error) => console.error("Failed to load page", error)); .catch((error) => console.error("Failed to load page", error));
} }
@ -35,7 +37,7 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
const response = await fetch(`/api/mdx/pages/${slug}`, { const response = await fetch(`/api/mdx/pages/${slug}`, {
method: "PUT", method: "PUT",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title, content }), body: JSON.stringify({ title, content, vulnerabilities }),
}); });
if (response.ok) { if (response.ok) {
@ -44,9 +46,7 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
router.push(`/admin/multi-logs/`); router.push(`/admin/multi-logs/`);
} else { } else {
setLoading(false); setLoading(false);
// TEMPERARORY ERROR toast({ description: "Page Updated" });
router.push(`/admin/multi-logs/`);
toast({ description: "Updated but cant return data" });
} }
}; };
@ -57,7 +57,7 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
}; };
return ( return (
<section id="edit-page" className="wrapper container"> <section id="edit-page" className="wrapper container gap-4">
<h1 className="text-3xl font-bold py-6">Edit Page: {slug}</h1> <h1 className="text-3xl font-bold py-6">Edit Page: {slug}</h1>
<Input <Input
value={title} value={title}
@ -69,6 +69,12 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
onChange={handleEditorChange} onChange={handleEditorChange}
height={560} height={560}
/> />
<h1 className="text-3xl font-bold py-6">Vulnerabilities</h1>
<MarkdownEditor
value={vulnerabilities}
onChange={(value) => setVulnerabilities(value || "")}
height={200}
/>
<Button onClick={savePage} disabled={loading} className="mt-4"> <Button onClick={savePage} disabled={loading} className="mt-4">
Save Save
</Button> </Button>

View file

@ -0,0 +1,276 @@
"use client";
import React, { useEffect, useState } from "react";
import { useForm, SubmitHandler, useFieldArray } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Input } from "@/components/ui/input";
import {
Select,
SelectTrigger,
SelectContent,
SelectItem,
SelectValue,
} from "@/components/ui/select";
import { z } from "zod";
import { useToast } from "@/components/ui/use-toast";
import {
ModsVulnerability,
vulnerabilitiesSchema,
} from "@/lib/validations/validation";
interface VulnerabilityEntry {
_id: string;
title: string;
category: string;
bullets: { point: string }[];
}
type VulnerabilitiesForm = z.infer<typeof vulnerabilitiesSchema>;
const AdminLogPage = () => {
const [logs, setLogs] = useState<VulnerabilityEntry[]>([]);
const [categories, setCategories] = useState<
{ title: string; _id: string }[]
>([]);
const [selectedCategory, setSelectedCategory] = useState<string>("");
const [error, setError] = useState("");
const { toast } = useToast();
const [loading, setLoading] = useState(false);
const form = useForm<ModsVulnerability>({
resolver: zodResolver(vulnerabilitiesSchema),
defaultValues: {
title: "",
category: "",
bullets: [{ point: "" }],
},
});
const { fields, append, remove } = useFieldArray({
control: form.control,
name: "bullets",
});
const fetchLogs = async () => {
try {
const response = await fetch("/api/vulnerabilities", { method: "GET" });
if (response.ok) {
const data: VulnerabilityEntry[] = await response.json();
setLogs(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to fetch logs");
}
};
const fetchCategories = async () => {
try {
const response = await fetch("/api/mdx/pages", { method: "GET" });
if (response.ok) {
const data = await response.json();
setCategories(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to fetch categories");
}
};
const onSubmit: SubmitHandler<ModsVulnerability> = async (data) => {
setLoading(true);
const response = await fetch("/api/vulnerability/mods", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
...data,
category: selectedCategory,
}),
});
if (response.ok) {
form.reset();
fetchLogs();
setLoading(false);
toast({ description: "Logs successfully added" });
} else {
setLoading(false);
toast({ description: "Upload Failed", variant: "destructive" });
}
};
const deleteLog = async (id: string) => {
try {
const response = await fetch(`/api/delete/vulnerability/${id}`, {
method: "DELETE",
});
if (response.ok) {
fetchLogs();
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to delete log");
}
};
useEffect(() => {
fetchLogs();
fetchCategories();
const interval = setInterval(() => {
fetchLogs();
}, 10000);
return () => clearInterval(interval);
}, []);
return (
<section id="logs-page" className="wrapper container">
<h1 className="text-3xl font-bold py-6">Server Vulnerabilities Form</h1>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="category"
render={({ field }) => (
<FormItem>
<FormLabel>Category</FormLabel>
<Select
value={selectedCategory}
onValueChange={(value) => setSelectedCategory(field.value)}
>
<SelectTrigger>
<SelectValue placeholder={"Category"} />
</SelectTrigger>
<SelectContent>
{categories.map((cat) => (
<SelectItem key={cat._id} value={cat._id}>
{cat.title}
</SelectItem>
))}
</SelectContent>
</Select>
</FormItem>
)}
/>
{fields.map((field, index) => (
<FormField
key={field.id}
control={form.control}
name={`bullets.${index}.point`}
render={({ field }) => (
<FormItem>
<FormLabel>Bullet Point {index + 1}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
<Button
type="button"
className="mt-2"
variant={"secondary"}
onClick={() => remove(index)}
>
Remove
</Button>
</FormItem>
)}
/>
))}
<Button
type="button"
className="mb-4"
size={"icon"}
variant={"outline"}
onClick={() => append({ point: "" })}
>
+
</Button>
<Button
type="submit"
className="w-full text-lg rounded-full"
disabled={loading}
size={"lg"}
>
Submit
</Button>
</form>
</Form>
{/* Section to list and delete logs */}
<section id="logs-list" className="py-16 md:py-24">
<h2 className="text-3xl md:text-4xl font-bold">
Existing Vulnerabilities
</h2>
{error && <p className="text-red-500">{error}</p>}
<Table className="w-full mt-4 border-muted">
<TableHeader>
<TableRow>
<TableHead className="border-b px-4 py-2">Title</TableHead>
<TableHead className="border-b px-4 py-2">Category</TableHead>
<TableHead className="border-b px-4 py-2">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{logs
.slice()
.reverse()
.map((log) => (
<TableRow key={log._id}>
<TableCell className="border-b px-4 py-2">
{log.title}
</TableCell>
<TableCell className="border-b px-4 py-2">
{log.category}
</TableCell>
<TableCell className="border-b px-4 py-2">
<Button
variant={"destructive"}
onClick={() => deleteLog(log._id)}
>
Delete
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</section>
</section>
);
};
export default AdminLogPage;

View file

@ -22,30 +22,34 @@ import {
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { logsSchema } from "@/lib/validations/validation";
import { z } from "zod"; import { z } from "zod";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { vulnerabilitiesSchema } from "@/lib/validations/validation";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
} from "@/components/ui/select";
interface LogEntry { interface VulnerabiltyEntry {
_id: string; _id: string;
version: string; version: string;
date: string;
bullets: { point: string }[]; bullets: { point: string }[];
} }
type LogsFormValues = z.infer<typeof logsSchema>; type VulnerabiltiesForm = z.infer<typeof vulnerabilitiesSchema>;
const AdminLogPage = () => { const AdminLogPage = () => {
const [logs, setLogs] = useState<LogEntry[]>([]); const [logs, setLogs] = useState<VulnerabiltyEntry[]>([]);
const [error, setError] = useState(""); const [error, setError] = useState("");
const { toast } = useToast(); const { toast } = useToast();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const form = useForm<LogsFormValues>({ const form = useForm<VulnerabiltiesForm>({
resolver: zodResolver(logsSchema), resolver: zodResolver(vulnerabilitiesSchema),
defaultValues: { defaultValues: {
version: "", version: "",
date: "",
bullets: [{ point: "" }], bullets: [{ point: "" }],
}, },
}); });
@ -59,7 +63,7 @@ const AdminLogPage = () => {
try { try {
const response = await fetch("/api/vulnerabilities", { method: "GET" }); const response = await fetch("/api/vulnerabilities", { method: "GET" });
if (response.ok) { if (response.ok) {
const data: LogEntry[] = await response.json(); const data: VulnerabiltyEntry[] = await response.json();
setLogs(data); setLogs(data);
} else { } else {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
@ -69,7 +73,7 @@ const AdminLogPage = () => {
} }
}; };
const onSubmit: SubmitHandler<LogsFormValues> = async (data) => { const onSubmit: SubmitHandler<VulnerabiltiesForm> = async (data) => {
setLoading(true); setLoading(true);
const response = await fetch("/api/uploadvulnerabilities", { const response = await fetch("/api/uploadvulnerabilities", {
method: "POST", method: "POST",
@ -90,7 +94,7 @@ const AdminLogPage = () => {
const deleteLog = async (id: string) => { const deleteLog = async (id: string) => {
try { try {
const response = await fetch(`/api/delete/logs/${id}`, { const response = await fetch(`/api/delete/vulnerability/${id}`, {
method: "DELETE", method: "DELETE",
}); });
if (response.ok) { if (response.ok) {

View file

@ -74,7 +74,7 @@ const Page = ({ params }: { params: { slug: string } }) => {
<> <>
<section className="wrapper container py-24 md:py-28 gap-2 flex flex-col"> <section className="wrapper container py-24 md:py-28 gap-2 flex flex-col">
<h1 className="text-3xl md:text-5xl pb-1 md:pb-2 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400"> <h1 className="text-3xl md:text-5xl pb-1 md:pb-2 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
{page.title} {page.title} Change Log
</h1> </h1>
<ReactMarkdown className="prose max-w-full md:prose-lg dark:prose-invert"> <ReactMarkdown className="prose max-w-full md:prose-lg dark:prose-invert">
{page.content} {page.content}

View file

@ -1,7 +1,7 @@
"use client"; "use client";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { vulnerabilities } from "@/constants/guidelines"; import { VULNERABILITY } from "@/constants/guidelines";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
@ -11,14 +11,22 @@ interface Bullet {
interface Vulnerabilities { interface Vulnerabilities {
_id: string; _id: string;
date: string;
version: string; version: string;
bullets?: Bullet[]; // Make bullets optional bullets?: Bullet[]; // Make bullets optional
} }
interface ModsVulnerability {
_id: string;
title: string;
slug: string;
content: string;
vulnerabilities: string;
}
const Vulnerabilities = () => { const Vulnerabilities = () => {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [downloads, setDownloads] = useState<Vulnerabilities[]>([]); const [downloads, setDownloads] = useState<Vulnerabilities[]>([]);
const [mods, setMods] = useState<ModsVulnerability[]>([]);
const [error, setError] = useState(""); const [error, setError] = useState("");
const fetchData = async () => { const fetchData = async () => {
@ -29,7 +37,7 @@ const Vulnerabilities = () => {
if (response.ok) { if (response.ok) {
const data: Vulnerabilities[] = await response.json(); const data: Vulnerabilities[] = await response.json();
setDownloads(data); setDownloads(data);
return (document.title = "Vulnerabilities | SVRJS"); document.title = "Vulnerabilities | SVRJS";
} else { } else {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
} }
@ -40,18 +48,43 @@ const Vulnerabilities = () => {
} }
}; };
const fetchMods = async () => {
try {
const response = await fetch(`/api/mdx/pages`, {
method: "GET",
});
if (response.ok) {
const data: ModsVulnerability[] = await response.json();
// Filter out entries where vulnerabilities is undefined or an empty string
const filteredMods = data.filter(
(mod) => mod.vulnerabilities && mod.vulnerabilities.trim() !== ""
);
setMods(filteredMods);
document.title = "Vulnerabilities | SVRJS";
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to fetch vulnerabilities");
} finally {
setLoading(false);
}
};
useEffect(() => { useEffect(() => {
fetchData(); fetchData();
fetchMods();
const interval = setInterval(() => { const interval = setInterval(() => {
fetchData(); fetchData();
fetchMods();
}, 10000); }, 10000);
return () => clearInterval(interval); return () => clearInterval(interval);
}, []); }, []);
const reversedDownloads = [...downloads].reverse();
// initially loading = true const reversedDownloads = [...downloads].reverse();
const reversedMods = [...mods].reverse();
if (loading) { if (loading) {
return ( return (
<section className="wrapper container py-24 md:py-28 gap-4 flex flex-col"> <section className="wrapper container py-24 md:py-28 gap-4 flex flex-col">
@ -98,9 +131,27 @@ const Vulnerabilities = () => {
</ul> </ul>
</div> </div>
))} ))}
<div className="prose max-w-full md:prose-lg dark:prose-invert"> <div className="prose max-w-full md:prose-lg dark:prose-invert">
<ReactMarkdown>{vulnerabilities}</ReactMarkdown> <ReactMarkdown>{VULNERABILITY}</ReactMarkdown>
</div> </div>
{/* Section with MODS content */}
{reversedMods.map((mod) => (
<div
key={mod._id}
className="flex-start flex-col prose dark:prose-invert mb-4 gap-4"
>
<h2 className="text-3xl md:text-5xl py-1 md:py-2 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400 -mb-1">
{mod.title}
</h2>
{mod.vulnerabilities && (
<div className="prose max-w-full md:prose-lg dark:prose-invert">
<ReactMarkdown>{mod.vulnerabilities}</ReactMarkdown>
</div>
)}
</div>
))}
</section> </section>
); );
}; };

View file

@ -0,0 +1,30 @@
// app/api/delete/[id]/route.ts
import clientPromise from "@/lib/db";
import { ObjectId } from "mongodb";
import { NextResponse } from "next/server";
export async function DELETE(
request: Request,
{ params }: { params: { id: string } }
) {
const { id } = params;
try {
const client = await clientPromise;
const db = client.db("downloadsDatabase");
const collection = db.collection("vulnerabilities");
const result = await collection.deleteOne({ _id: new ObjectId(id) });
if (result.deletedCount === 1) {
return NextResponse.json({ message: "Log deleted successfully" });
} else {
return NextResponse.json({ message: "Log not found" }, { status: 404 });
}
} catch (error) {
return NextResponse.json(
{ message: "Failed to delete log", error: error },
{ status: 500 }
);
}
}

View file

@ -0,0 +1,32 @@
import clientPromise from "@/lib/db";
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === "POST") {
try {
const client = await clientPromise;
const db = client.db("modsVuln");
const { title, category, bullets } = req.body;
if (!title || !category || !bullets || !Array.isArray(bullets)) {
return res.status(400).json({ error: "Invalid data" });
}
await db.collection("vulnerabilities").insertOne({
title,
category,
bullets,
});
res.status(200).json({ message: "Vulnerability added successfully" });
} catch (error) {
res.status(500).json({ error: error || "Failed to add vulnerability" });
}
} else {
res.setHeader("Allow", ["POST"]);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}

View file

@ -34,57 +34,35 @@ export const PUT = async (
return NextResponse.json({ message: "Slug is required" }, { status: 400 }); return NextResponse.json({ message: "Slug is required" }, { status: 400 });
} }
const { title, content } = await req.json(); const { title, content, vulnerabilities } = await req.json();
if (typeof title !== "string" || typeof content !== "string") { if (
typeof title !== "string" ||
typeof content !== "string" ||
typeof vulnerabilities !== "string"
) {
return NextResponse.json( return NextResponse.json(
{ message: "Invalid title or content" }, { message: "Invalid title, content, or vulnerabilities" },
{ status: 400 } { status: 400 }
); );
} }
try { try {
// it works here ig const result = await db.collection("pages").findOneAndUpdate(
const result = await db { slug },
.collection("pages") { $set: { title, content, vulnerabilities } },
.findOneAndUpdate( { returnDocument: "after" } // Updated option
{ slug }, );
{ $set: { title, content } },
{ returnDocument: "after" }
);
// i hate my life fr fr if (result?.value) {
console.log("Update Result:", result); const serializedResult = {
// result returns like ...result.value,
_id: result.value._id.toString(), // Convert ObjectId to string
// Update Result: { };
// _id: new ObjectId('66a2946b2b91eef505eef943'), return NextResponse.json(serializedResult, { status: 200 });
// title: 'TEST PAGE', } else {
// slug: 'test-page', return NextResponse.json({ message: "Page not found" }, { status: 404 });
// content: 'asd]---\n' + }
// '---\n' +
// '\n' +
// 'this is basic heading ?\n' +
// '\n' +
// '**HELLO**\n' +
// '\n' +
// 'erw\n' +
// '\n' +
// 'trying another time for test'
// }
// ERRROR : TypeError: Cannot read properties of undefined (reading '_id')
// aposdjaoi sdio JUST WORK NIAWWWWWWWWW
// if (result && result.value) {
const serializedResult = {
...result?.value,
_id: result?.value._id.toString(), // Convert ObjectId to string
};
return NextResponse.json(result?.value.content, { status: 200 });
// } else {
// return NextResponse.json({ message: "Page not found" }, { status: 404 });
// }
} catch (error) { } catch (error) {
console.error("Error updating page:", error); console.error("Error updating page:", error);
return NextResponse.json( return NextResponse.json(

BIN
bun.lockb

Binary file not shown.

160
components/ui/select.tsx Normal file
View file

@ -0,0 +1,160 @@
"use client"
import * as React from "react"
import * as SelectPrimitive from "@radix-ui/react-select"
import { Check, ChevronDown, ChevronUp } from "lucide-react"
import { cn } from "@/lib/utils"
const Select = SelectPrimitive.Root
const SelectGroup = SelectPrimitive.Group
const SelectValue = SelectPrimitive.Value
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
)}
{...props}
>
<ChevronUp className="h-4 w-4" />
</SelectPrimitive.ScrollUpButton>
))
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
)}
{...props}
>
<ChevronDown className="h-4 w-4" />
</SelectPrimitive.ScrollDownButton>
))
SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
{...props}
/>
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
}

View file

@ -357,7 +357,7 @@ By contributing to our project, you agree that your contributions will be licens
Thank you for considering contributing to our project! Thank you for considering contributing to our project!
`; `;
export const vulnerabilities = ` export const VULNERABILITY = `
### Fixed in SVR.JS 3.15.0 and in SVR.JS 3.14.16 LTS ### Fixed in SVR.JS 3.15.0 and in SVR.JS 3.14.16 LTS
- An attacker could send a HTTP forward proxy request with malformed URL not using CONNECT method to possibly crash the server. - An attacker could send a HTTP forward proxy request with malformed URL not using CONNECT method to possibly crash the server.
@ -419,46 +419,6 @@ export const vulnerabilities = `
### Fixed in SVR.JS 2.1.1 ### Fixed in SVR.JS 2.1.1
- An attacker could use directory listing to access secret files (through path traversal). - An attacker could use directory listing to access secret files (through path traversal).
## easy-waf integration
### Fixed in easy-waf integration 1.2.4
- An attacker could send a very small chunk of the POST request body (which will not trigger WAF) before the payload to bypass the WAF.
### Fixed in easy-waf integration 1.2.1
- An attacker could access the resource on the server with poorly written SVR.JS mod or server-side JavaScript (that normally would invoke 500 Internal Server Error) to crash the server.
## RedBrick
### Fixed in RedBrick 2.5.4
- An attacker could add HTTP authentication header to the HTTP request when not required to enable web application functionality normally disabled on unauthenticated requests. View the security advisory
### Fixed in RedBrick 2.3.3
- An attacker could use CGI-BIN instead of cgi-bin to leak source code, while SVR.JS with RedBrick is running on Windows. View the security advisory
- An attacker could leak RedBrick interpreter settings, while SVR.JS with RedBrick is running on Windows. View the security advisory
## reverse-proxy-mod
### Fixed in reverse-proxy-mod 1.1.2
- An attacker could hack the upstream server, replace the web server or application with one that sends an invalid HTTP response code, and make a request to the hacked server through the reverse proxy to crash the reverse proxy server.
### Fixed in reverse-proxy-mod 1.0.4
- An attacker could leak reverse proxy configuration file. View the security advisory
## OrangeCircle
### Fixed in OrangeCircle 1.1.2
- An attacker could add HTTP authentication header to the HTTP request when not required to enable web application functionality normally disabled on unauthenticated requests. View the security advisory
### Fixed in OrangeCircle 1.0.2
- An attacker could leak OrangeCircle configuration, while SVR.JS with YellowSquare is running on Windows. View the security advisory
## YellowSquare
### Fixed in YellowSquare 1.1.2
- An attacker could add HTTP authentication header to the HTTP request when not required to enable web application functionality normally disabled on unauthenticated requests. View the security advisory
### Fixed in YellowSquare 1.0.1
- An attacker could use JSGI-BIN instead of jsgi-bin to leak source code, while SVR.JS with YellowSquare is running on Windows. View the security advisory
`; `;
export const CHANGE_LOGS = ` export const CHANGE_LOGS = `

View file

@ -24,7 +24,28 @@ export const logsSchema = z.object({
), ),
}); });
export const vulnerabilitiesSchema = z.object({
version: z.string(),
bullets: z.array(
z.object({
point: z.string(),
})
),
});
export const ModsVulnerabilities = z.object({
title: z.string(),
category: z.string(),
bullets: z.array(
z.object({
point: z.string(),
})
),
});
export type LogsFormValues = z.infer<typeof logsSchema>; export type LogsFormValues = z.infer<typeof logsSchema>;
export type VulnerabiltiesForm = z.infer<typeof vulnerabilitiesSchema>;
export type ModsVulnerability = z.infer<typeof ModsVulnerabilities>;
// Contact Page // Contact Page

View file

@ -13,9 +13,10 @@
"@hookform/resolvers": "^3.6.0", "@hookform/resolvers": "^3.6.0",
"@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-label": "^2.1.0", "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-navigation-menu": "^1.1.4", "@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1", "@radix-ui/react-toast": "^1.2.1",