removed all unused api routes and components
This commit is contained in:
parent
5a941d3883
commit
0badf0bf76
11 changed files with 1 additions and 381 deletions
|
|
@ -1,65 +0,0 @@
|
||||||
// app/api/auth/me/route.ts
|
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
|
||||||
|
|
||||||
const DIRECTUS_URL = process.env.DIRECTUS_URL!;
|
|
||||||
const ACCESS_COOKIE = "ma_at";
|
|
||||||
|
|
||||||
export const runtime = "nodejs";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GET /api/auth/me
|
|
||||||
* Returns the current Directus user using the access token in "ma_at".
|
|
||||||
* Mirrors the shape you’re already expecting on the client:
|
|
||||||
* { id, username, display_name, first_name, last_name, email, ... }
|
|
||||||
*/
|
|
||||||
export async function GET(_req: NextRequest) {
|
|
||||||
try {
|
|
||||||
if (!DIRECTUS_URL) {
|
|
||||||
return NextResponse.json({ error: "Missing DIRECTUS_URL" }, { status: 500 });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer cookie; allow Authorization header for flexibility
|
|
||||||
const cookie = _req.cookies.get(ACCESS_COOKIE)?.value;
|
|
||||||
const authHeader = _req.headers.get("authorization") || "";
|
|
||||||
const bearer =
|
|
||||||
authHeader?.toLowerCase().startsWith("bearer ")
|
|
||||||
? authHeader.slice(7).trim()
|
|
||||||
: cookie;
|
|
||||||
|
|
||||||
if (!bearer) {
|
|
||||||
// No token: treat as not signed in (same semantics as your client)
|
|
||||||
return NextResponse.json({ error: "not-signed-in" }, { status: 401 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = `${DIRECTUS_URL}/users/me?fields=id,username,display_name,first_name,last_name,email`;
|
|
||||||
|
|
||||||
const res = await fetch(url, {
|
|
||||||
headers: {
|
|
||||||
Accept: "application/json",
|
|
||||||
Authorization: `Bearer ${bearer}`,
|
|
||||||
},
|
|
||||||
cache: "no-store",
|
|
||||||
});
|
|
||||||
|
|
||||||
const text = await res.text();
|
|
||||||
let json: any = null;
|
|
||||||
try {
|
|
||||||
json = text ? JSON.parse(text) : null;
|
|
||||||
} catch {
|
|
||||||
// non-JSON from Directus; keep raw text for error messages
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res.ok) {
|
|
||||||
const msg = json?.errors?.[0]?.message || json?.error || text || "Directus error";
|
|
||||||
const status = res.status === 401 || res.status === 403 ? res.status : 500;
|
|
||||||
return NextResponse.json({ error: msg }, { status });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Directus often wraps in { data: {...} }
|
|
||||||
const data = json?.data ?? json ?? null;
|
|
||||||
return NextResponse.json(data ?? {}, { status: 200 });
|
|
||||||
} catch (err: any) {
|
|
||||||
const msg = err?.message || "Failed to fetch current user";
|
|
||||||
return NextResponse.json({ error: msg }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
export const runtime = "nodejs";
|
|
||||||
export const dynamic = "force-dynamic";
|
|
||||||
|
|
||||||
const BGBYE_URL =
|
|
||||||
process.env.BGBYE_URL ||
|
|
||||||
process.env.BG_BYE_URL ||
|
|
||||||
process.env.BGREMOVER_BASE_URL ||
|
|
||||||
"http://bgbye:7001";
|
|
||||||
|
|
||||||
export async function GET() {
|
|
||||||
try {
|
|
||||||
const r = await fetch(`${BGBYE_URL}/methods`, { cache: "no-store" });
|
|
||||||
const body = await r.text();
|
|
||||||
return new Response(body, {
|
|
||||||
status: r.status,
|
|
||||||
headers: { "content-type": r.headers.get("content-type") || "application/json" },
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
return new Response(JSON.stringify({ methods: [] }), {
|
|
||||||
status: 200,
|
|
||||||
headers: { "content-type": "application/json" },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import { NextResponse } from 'next/server';
|
|
||||||
import path from 'node:path';
|
|
||||||
import fs from 'node:fs/promises';
|
|
||||||
|
|
||||||
const BASE_DIR = '/app/files';
|
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
|
||||||
try {
|
|
||||||
const url = new URL(req.url);
|
|
||||||
const raw = url.searchParams.get('path');
|
|
||||||
if (!raw) {
|
|
||||||
return NextResponse.json({ error: 'Missing path' }, { status: 400 });
|
|
||||||
}
|
|
||||||
const safe = path.normalize('/' + raw).replace(/^\/+/, '/');
|
|
||||||
const target = path.resolve(BASE_DIR, '.' + safe);
|
|
||||||
|
|
||||||
if (!target.startsWith(BASE_DIR)) {
|
|
||||||
return NextResponse.json({ error: 'Invalid path' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const st = await fs.stat(target).catch(() => null);
|
|
||||||
if (!st || !st.isFile()) {
|
|
||||||
return NextResponse.json({ error: 'Not a file' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await fs.readFile(target);
|
|
||||||
// naive content-type guess
|
|
||||||
const ext = path.extname(target).toLowerCase();
|
|
||||||
const ctype =
|
|
||||||
ext === '.pdf' ? 'application/pdf' :
|
|
||||||
ext === '.png' ? 'image/png' :
|
|
||||||
ext === '.jpg' || ext === '.jpeg' ? 'image/jpeg' :
|
|
||||||
ext === '.webp' ? 'image/webp' :
|
|
||||||
ext === '.txt' ? 'text/plain; charset=utf-8' :
|
|
||||||
'application/octet-stream';
|
|
||||||
|
|
||||||
return new Response(data, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': ctype,
|
|
||||||
'Content-Length': String(data.byteLength),
|
|
||||||
'Content-Disposition': `inline; filename="${path.basename(target)}"`,
|
|
||||||
'Cache-Control': 'no-store',
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e: any) {
|
|
||||||
return NextResponse.json({ error: e?.message ?? 'Unknown error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
import fs from "node:fs/promises";
|
|
||||||
import path from "node:path";
|
|
||||||
|
|
||||||
export const runtime = "nodejs";
|
|
||||||
export const dynamic = "force-dynamic";
|
|
||||||
|
|
||||||
const BASE = "/app/files";
|
|
||||||
|
|
||||||
function safeJoin(base: string, reqPath: string) {
|
|
||||||
const rel = reqPath.startsWith("/") ? reqPath : `/${reqPath}`;
|
|
||||||
const full = path.resolve(base, "." + rel);
|
|
||||||
if (!full.startsWith(base)) throw new Error("Outside base");
|
|
||||||
return full;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CONTENT_MAP: Record<string, string> = {
|
|
||||||
".png": "image/png",
|
|
||||||
".jpg": "image/jpeg",
|
|
||||||
".jpeg": "image/jpeg",
|
|
||||||
".gif": "image/gif",
|
|
||||||
".webp": "image/webp",
|
|
||||||
".svg": "image/svg+xml",
|
|
||||||
".txt": "text/plain; charset=utf-8",
|
|
||||||
".json": "application/json; charset=utf-8",
|
|
||||||
".pdf": "application/pdf",
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
|
||||||
try {
|
|
||||||
const url = new URL(req.url);
|
|
||||||
const reqPath = url.searchParams.get("path");
|
|
||||||
if (!reqPath) return NextResponse.json({ error: "Missing path" }, { status: 400 });
|
|
||||||
|
|
||||||
const full = safeJoin(BASE, reqPath);
|
|
||||||
const stat = await fs.stat(full);
|
|
||||||
if (!stat.isFile()) return NextResponse.json({ error: "Not a file" }, { status: 400 });
|
|
||||||
|
|
||||||
const data = await fs.readFile(full);
|
|
||||||
const ext = path.extname(full).toLowerCase();
|
|
||||||
const type = CONTENT_MAP[ext] ?? "application/octet-stream";
|
|
||||||
|
|
||||||
return new NextResponse(data, {
|
|
||||||
status: 200,
|
|
||||||
headers: { "Content-Type": type, "Cache-Control": "public, max-age=300" },
|
|
||||||
});
|
|
||||||
} catch (e: any) {
|
|
||||||
return NextResponse.json({ error: e?.message ?? "Unknown" }, { status: 400 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
import { NextResponse } from 'next/server';
|
|
||||||
import path from 'node:path';
|
|
||||||
import fs from 'node:fs/promises';
|
|
||||||
|
|
||||||
const BASE_DIR = '/app/files';
|
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
|
||||||
try {
|
|
||||||
const url = new URL(req.url);
|
|
||||||
const raw = url.searchParams.get('path') ?? '/';
|
|
||||||
const safe = path.normalize('/' + raw).replace(/^\/+/, '/'); // normalize & ensure leading slash
|
|
||||||
const target = path.resolve(BASE_DIR, '.' + safe);
|
|
||||||
|
|
||||||
if (!target.startsWith(BASE_DIR)) {
|
|
||||||
return NextResponse.json({ error: 'Invalid path' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const st = await fs.stat(target).catch(() => null);
|
|
||||||
if (!st || !st.isDirectory()) {
|
|
||||||
return NextResponse.json({ error: 'Not a directory' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const entries = await fs.readdir(target, { withFileTypes: true });
|
|
||||||
const items = await Promise.all(entries.map(async (d) => {
|
|
||||||
const full = path.join(target, d.name);
|
|
||||||
const rel = path.posix.join(safe, d.name).replaceAll('\\', '/');
|
|
||||||
const s = await fs.stat(full);
|
|
||||||
return {
|
|
||||||
name: d.name,
|
|
||||||
path: rel,
|
|
||||||
type: d.isDirectory() ? 'dir' : 'file',
|
|
||||||
size: s.size,
|
|
||||||
mtime: s.mtimeMs,
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
return NextResponse.json({ path: safe, items });
|
|
||||||
} catch (e: any) {
|
|
||||||
return NextResponse.json({ error: e?.message ?? 'Unknown error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
import fs from "node:fs/promises";
|
|
||||||
import fssync from "node:fs";
|
|
||||||
import path from "node:path";
|
|
||||||
|
|
||||||
const BASE = "/app/files"; // this is /var/www/makearmy.io/app/files on the host
|
|
||||||
|
|
||||||
function safeJoin(base: string, reqPath: string) {
|
|
||||||
const decoded = decodeURIComponent(reqPath || "/");
|
|
||||||
// normalize, strip traversal, and join under BASE
|
|
||||||
const normalized = path.posix.normalize("/" + decoded).replace(/^(\.\.(\/|\\|$))+/g, "");
|
|
||||||
const full = path.join(base, normalized);
|
|
||||||
if (!full.startsWith(base)) throw new Error("Invalid path");
|
|
||||||
return full;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
|
||||||
try {
|
|
||||||
const { searchParams } = new URL(req.url);
|
|
||||||
const p = searchParams.get("path") || "/";
|
|
||||||
const abs = safeJoin(BASE, p);
|
|
||||||
|
|
||||||
const entries = await fs.readdir(abs, { withFileTypes: true });
|
|
||||||
const rows = await Promise.all(entries.map(async (ent) => {
|
|
||||||
const full = path.join(abs, ent.name);
|
|
||||||
const stat = await fs.stat(full);
|
|
||||||
const isDir = ent.isDirectory();
|
|
||||||
return {
|
|
||||||
name: ent.name,
|
|
||||||
type: isDir ? "dir" : "file",
|
|
||||||
size: isDir ? null : stat.size,
|
|
||||||
mtime: stat.mtime.toISOString(),
|
|
||||||
path: path.posix.join(p.endsWith("/") ? p : p + "/", ent.name),
|
|
||||||
// raw download/view URL (served by /api/files/raw)
|
|
||||||
url: isDir ? null : `/api/files/raw?path=${encodeURIComponent(path.posix.join(p, ent.name))}`,
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Sort: directories first, then files alphabetically
|
|
||||||
rows.sort((a, b) => {
|
|
||||||
if (a.type !== b.type) return a.type === "dir" ? -1 : 1;
|
|
||||||
return a.name.localeCompare(b.name, undefined, { sensitivity: "base" });
|
|
||||||
});
|
|
||||||
|
|
||||||
return NextResponse.json({ ok: true, path: p, items: rows });
|
|
||||||
} catch (err: any) {
|
|
||||||
return NextResponse.json({ ok: false, error: err?.message || "Error" }, { status: 400 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
// app/api/health/directus/route.ts
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
import { directusFetch } from "@/lib/directus";
|
|
||||||
|
|
||||||
export const runtime = "nodejs";
|
|
||||||
|
|
||||||
export async function GET() {
|
|
||||||
const out: any = { ok: true, checks: {} };
|
|
||||||
try {
|
|
||||||
// who am I?
|
|
||||||
try {
|
|
||||||
const who = await directusFetch<{ data: any }>(`/users/me?fields=id,email,role.name`);
|
|
||||||
out.checks.user = { ok: true, role: who?.data?.role?.name ?? null };
|
|
||||||
} catch (e: any) {
|
|
||||||
out.checks.user = { ok: false, error: e?.message || String(e) };
|
|
||||||
}
|
|
||||||
|
|
||||||
// can read folders?
|
|
||||||
try {
|
|
||||||
const folders = await directusFetch<{ data: any[] }>(`/folders?limit=1&fields=id,name`);
|
|
||||||
out.checks.folders = { ok: true, sample: folders?.data?.[0] ?? null };
|
|
||||||
} catch (e: any) {
|
|
||||||
out.checks.folders = { ok: false, error: e?.message || String(e) };
|
|
||||||
}
|
|
||||||
|
|
||||||
// can read files (not create; safe)
|
|
||||||
try {
|
|
||||||
const files = await directusFetch<{ data: any[] }>(`/files?limit=0`);
|
|
||||||
out.checks.files_read = { ok: true, totalKnown: files?.data?.length ?? 0 };
|
|
||||||
} catch (e: any) {
|
|
||||||
out.checks.files_read = { ok: false, error: e?.message || String(e) };
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json(out);
|
|
||||||
} catch (e: any) {
|
|
||||||
return NextResponse.json({ ok: false, error: e?.message || "health error", ...out }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// app/api/health/options/route.ts
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
import { directusFetch } from "@/lib/directus";
|
|
||||||
|
|
||||||
const TESTS = [
|
|
||||||
{ name: "material", path: "/items/material?limit=1" },
|
|
||||||
{ name: "material_coating", path: "/items/material_coating?limit=1" },
|
|
||||||
{ name: "material_color", path: "/items/material_color?limit=1" },
|
|
||||||
{ name: "material_opacity", path: "/items/material_opacity?limit=1" },
|
|
||||||
{ name: "laser_software", path: "/items/laser_software?limit=1" },
|
|
||||||
{ name: "laser_source", path: "/items/laser_source?limit=1" },
|
|
||||||
{ name: "laser_scan_lens", path: "/items/laser_scan_lens?limit=1" },
|
|
||||||
{ name: "laser_focusing_lens",path: "/items/laser_focusing_lens?limit=1" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export async function GET() {
|
|
||||||
const results: any[] = [];
|
|
||||||
for (const t of TESTS) {
|
|
||||||
try {
|
|
||||||
const { data } = await directusFetch<{ data: any[] }>(t.path);
|
|
||||||
const first = data?.[0] ?? null;
|
|
||||||
results.push({ name: t.name, ok: true, sample_id: first?.submission_id ?? first?.id ?? null });
|
|
||||||
} catch (e: any) {
|
|
||||||
results.push({ name: t.name, ok: false, error: e?.message || String(e) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NextResponse.json({ ok: true, results });
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// /var/www/makearmy.io/app/components/toolkit/ToolShell.tsx
|
|
||||||
"use client";
|
|
||||||
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
export default function ToolShell({
|
|
||||||
title,
|
|
||||||
subtitle,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
title: string;
|
|
||||||
subtitle?: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div className="mx-auto max-w-4xl px-4 py-8 space-y-6">
|
|
||||||
<header className="flex items-start justify-between gap-4">
|
|
||||||
<div>
|
|
||||||
<h1 className="text-2xl font-semibold">{title}</h1>
|
|
||||||
{subtitle && (
|
|
||||||
<p className="text-sm text-muted-foreground mt-1">{subtitle}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<Link
|
|
||||||
href="https://makearmy.io"
|
|
||||||
className="rounded-lg px-3 py-2 border hover:bg-muted transition-colors text-sm"
|
|
||||||
>
|
|
||||||
Back to Main Menu
|
|
||||||
</Link>
|
|
||||||
</header>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import SettingsSubmit from "@/app/components/forms/SettingsSubmit";
|
import SettingsSubmit from "@/components/forms/SettingsSubmit";
|
||||||
|
|
||||||
export const dynamic = "force-dynamic"; // keeps this page from being statically prerendered
|
export const dynamic = "force-dynamic"; // keeps this page from being statically prerendered
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue