diff --git a/.pwd.example b/.pwd.example index 5454631..4e8ec24 100644 --- a/.pwd.example +++ b/.pwd.example @@ -1,3 +1 @@ -# Default password: 123456 -# Remember to change this password after setting up the app -PASSWORD=14e1b600b1fd579f47433b88e8d85291 +PASSWORD=14e1b600b1fd579f47433b88e8d85291 \ No newline at end of file diff --git a/README.md b/README.md index f929a22..ddb3bad 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,13 @@ First, you need to make sure that your server (or computer) has installed Nodejs git clone https://github.com/nocpiun/ferrum.git cd ferrum npm i +npm run patch npm run build ``` 2. Prepare the `.pwd` file -Rename the `.pwd.example` to `.pwd` in the project root folder. And delete the comments in it. This file stores your access key to Ferrum. The default password is `123456`, and you can change your password in the settings. +Rename the `.pwd.example` to `.pwd` in the project root folder. This file stores your access key to Ferrum. The default password is `123456`, and you can change your password in the settings. ```txt PASSWORD=.... @@ -102,6 +103,7 @@ An explanation of the `package.json` scripts. - **`start`** Launch the app in production mode - **`dev`** Launch the app in development mode +- **`patch`** Install `next-ws` plugin - **`build`** Create a production build - **`build:ci`** Create a production build for CI environment - **`lint`** Run ESLint diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index da7b0a6..d4f6a78 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -16,7 +16,7 @@ import { useRouter } from "next/navigation"; import ThemeSwitch from "@/components/theme-switch"; import PasswordInput from "@/components/password-input"; import { BaseResponseData } from "@/types"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; const schema = z.object({ password: z.string().min(6, { message: "请输入访问密码" }), @@ -85,7 +85,7 @@ export default function Page() { src="/icon.png" className="w-[70px] mb-4" style={{ imageRendering: "pixelated" }}/> -
Explore throughout your server.
diff --git a/app/api/fs/disks/route.ts b/app/api/fs/disks/route.ts index 5455ac0..6e026dc 100644 --- a/app/api/fs/disks/route.ts +++ b/app/api/fs/disks/route.ts @@ -3,11 +3,25 @@ import os from "node:os"; import { NextRequest } from "next/server"; import si from "systeminformation"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; import { packet, error } from "@/lib/packet"; +// Demo +import demoOS from "@/lib/demo/os.json"; export async function GET(req: NextRequest) { + if(isDemo) { + return packet({ + system: demoOS.os.platform, + disks: demoOS.disk.map((item) => ({ + used: item.used, + size: item.size, + capacity: (item.used / item.size) * 100, + mount: item.mount + })) + }); + } + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -17,7 +31,6 @@ export async function GET(req: NextRequest) { const disk = await si.fsSize(); return packet({ - status: 200, system: os.platform(), disks: disk.map((item) => ({ used: item.used, diff --git a/app/api/fs/download/route.ts b/app/api/fs/download/route.ts index 2ea0e21..7630b86 100644 --- a/app/api/fs/download/route.ts +++ b/app/api/fs/download/route.ts @@ -4,12 +4,25 @@ import path from "node:path"; import { NextRequest, NextResponse } from "next/server"; import mime from "mime"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; import { error } from "@/lib/packet"; import { streamFile } from "@/lib/stream"; +// Demo +import demoFile from "@/lib/demo/file.json"; export async function GET(req: NextRequest) { + if(isDemo) { + return new NextResponse(demoFile.content, { + status: 200, + headers: { + "Content-Disposition": `attachment; filename=hello.txt`, + "Content-Type": "text/plain", + "Content-Length": demoFile.size.toString() + } + }); + } + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); diff --git a/app/api/fs/file/route.ts b/app/api/fs/file/route.ts index 75f8b16..7050ef1 100644 --- a/app/api/fs/file/route.ts +++ b/app/api/fs/file/route.ts @@ -4,13 +4,19 @@ import path from "node:path"; import { NextRequest, NextResponse } from "next/server"; import mime from "mime"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; import { packet, error } from "@/lib/packet"; import { streamFile } from "@/lib/stream"; import { getFileType } from "@/lib/utils"; +// Demo +import demoFile from "@/lib/demo/file.json"; export async function GET(req: NextRequest) { + if(isDemo) { + return packet(demoFile); + } + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -59,6 +65,8 @@ interface FilePostRequestData { } export async function POST(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -95,6 +103,8 @@ interface FilePatchRequestData { } export async function PATCH(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -125,6 +135,8 @@ export async function PATCH(req: NextRequest) { } export async function DELETE(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); diff --git a/app/api/fs/folder/route.ts b/app/api/fs/folder/route.ts index 7d0cb6e..ffc4d03 100644 --- a/app/api/fs/folder/route.ts +++ b/app/api/fs/folder/route.ts @@ -5,11 +5,19 @@ import path from "node:path"; import { NextRequest } from "next/server"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; import { packet, error } from "@/lib/packet"; +// Demo +import demoFiles from "@/lib/demo/files.json"; export async function GET(req: NextRequest) { + if(isDemo) { + return packet({ + items: demoFiles + }); + } + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -62,6 +70,8 @@ interface FolderPostRequestData { } export async function POST(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -95,6 +105,8 @@ export async function POST(req: NextRequest) { } export async function DELETE(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); @@ -128,6 +140,8 @@ interface FolderPutRequestData { } export async function PUT(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); diff --git a/app/api/fs/thumbnail/route.ts b/app/api/fs/thumbnail/route.ts index bf9e673..fd8d82c 100644 --- a/app/api/fs/thumbnail/route.ts +++ b/app/api/fs/thumbnail/route.ts @@ -3,13 +3,15 @@ import fs from "node:fs"; import { NextRequest, NextResponse } from "next/server"; import mime from "mime"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; -import { error } from "@/lib/packet"; +import { error, packet } from "@/lib/packet"; import { getExtname, getFileType } from "@/lib/utils"; import { streamFile } from "@/lib/stream"; export async function GET(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); diff --git a/app/api/fs/upload/route.ts b/app/api/fs/upload/route.ts index d66a643..e009149 100644 --- a/app/api/fs/upload/route.ts +++ b/app/api/fs/upload/route.ts @@ -3,11 +3,13 @@ import path from "node:path"; import { NextRequest } from "next/server"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; import { packet, error } from "@/lib/packet"; export async function POST(req: NextRequest) { + if(isDemo) return packet({}); + const token = req.cookies.get(tokenStorageKey)?.value; if(!token) return error(401); diff --git a/app/api/os/route.ts b/app/api/os/route.ts index 97075e7..46e82c8 100644 --- a/app/api/os/route.ts +++ b/app/api/os/route.ts @@ -10,8 +10,10 @@ import { cpuModel, usagePercent as cpuPercent } from "node-system-stats"; import cookie from "cookie"; import { error } from "@/lib/packet"; -import { tokenStorageKey } from "@/lib/global"; +import { isDemo, tokenStorageKey } from "@/lib/global"; import { validateToken } from "@/lib/token"; +// Demo +import demoOS from "@/lib/demo/os.json"; export function GET() { return error(400); @@ -38,6 +40,12 @@ export function SOCKET( console.log("[Server: /api/os] Socket client connected."); const handleRequest = async () => { + if(isDemo) { + client.send(JSON.stringify(demoOS)); + + return; + } + const cpu = await si.cpu(); const cpuTemp = await si.cpuTemperature(); const mem = await si.mem(); diff --git a/components/dashboard/disk-widget.tsx b/components/dashboard/disk-widget.tsx index 38f46a5..d73e64e 100644 --- a/components/dashboard/disk-widget.tsx +++ b/components/dashboard/disk-widget.tsx @@ -56,7 +56,7 @@ const DiskWidget: React.FC