forked from administration/panel
feat: add backup list/viewer
parent
a03c539890
commit
d1ff57b239
|
@ -0,0 +1,18 @@
|
|||
import { JsonCard } from "@/components/cards/JsonCard";
|
||||
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { fetchBackup } from "@/lib/actions"
|
||||
|
||||
export default async function Report({ params }: { params: { name: string } }) {
|
||||
const name = decodeURIComponent(params.name);
|
||||
const backup = await fetchBackup(name);
|
||||
|
||||
return <>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{name}</CardTitle>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<br />
|
||||
<JsonCard obj={backup} />
|
||||
</>
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||
import { fetchBackups } from "@/lib/actions";
|
||||
import Link from "next/link";
|
||||
|
||||
export default async function Backups() {
|
||||
const backups = await fetchBackups();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Type</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{backups.map((backup) => (
|
||||
<TableRow key={backup.name}>
|
||||
<TableCell>{backup.name}</TableCell>
|
||||
<TableCell>{backup.type}</TableCell>
|
||||
<TableCell>
|
||||
<Link href={`/panel/backups/${encodeURIComponent(backup.name)}`}>
|
||||
<Button>
|
||||
Open
|
||||
</Button>
|
||||
</Link>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import Link from "next/link";
|
||||
import { buttonVariants } from "../ui/button";
|
||||
import {
|
||||
Bomb,
|
||||
Eye,
|
||||
Globe2,
|
||||
Home,
|
||||
|
@ -38,6 +39,12 @@ export function NavigationLinks() {
|
|||
>
|
||||
<Search className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
className={buttonVariants({ variant: "outline", size: "icon" })}
|
||||
href="/panel/backups"
|
||||
>
|
||||
<Bomb className="h-4 w-4" />
|
||||
</Link>
|
||||
{/*<Link
|
||||
className={buttonVariants({ variant: "outline", size: "icon" })}
|
||||
href="/panel/discover"
|
||||
|
|
|
@ -53,7 +53,8 @@ type Permission =
|
|||
| `safety_notes${
|
||||
| ""
|
||||
| `/fetch${"" | `/${SafetyNotes["_id"]["type"]}`}`
|
||||
| `/update${"" | `/${SafetyNotes["_id"]["type"]}`}`}`;
|
||||
| `/update${"" | `/${SafetyNotes["_id"]["type"]}`}`}`
|
||||
| `backup${"" | `/fetch${"" | "/by-name"}`}`;
|
||||
|
||||
const PermissionSets = {
|
||||
// Admin
|
||||
|
@ -149,6 +150,7 @@ const PermissionSets = {
|
|||
"channels/create/dm",
|
||||
|
||||
"servers/update/quarantine",
|
||||
"backup/fetch",
|
||||
|
||||
"reports/fetch/related/by-user",
|
||||
"reports/fetch/related/by-content",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use server";
|
||||
|
||||
import { writeFile } from "fs/promises";
|
||||
import { readFile, readdir, writeFile } from "fs/promises";
|
||||
import { PLATFORM_MOD_ID, RESTRICT_ACCESS_LIST } from "./constants";
|
||||
import mongo, {
|
||||
Account,
|
||||
|
@ -862,3 +862,26 @@ export async function cancelAccountDeletion(accountId: string) {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchBackups() {
|
||||
await checkPermission("backup/fetch", null);
|
||||
|
||||
return await Promise.all(
|
||||
(await readdir("./exports", { withFileTypes: true }))
|
||||
.filter((file) => file.isFile() && file.name.endsWith(".json"))
|
||||
.map(async (file) => {
|
||||
let type: string | null = null;
|
||||
try {
|
||||
type = JSON.parse((await readFile(`./exports/${file.name}`)).toString("utf-8"))._event;
|
||||
} catch(e) {}
|
||||
|
||||
return { name: file.name, type: type }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchBackup(name: string) {
|
||||
await checkPermission("backup/fetch/by-name", null);
|
||||
|
||||
return JSON.parse((await readFile(`./exports/${name}`)).toString("utf-8"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue