77 lines
2.6 KiB
TypeScript
77 lines
2.6 KiB
TypeScript
import { db } from "@/db";
|
||
import { apps, remoteConfig } from "@/db/schema";
|
||
import { eq } from "drizzle-orm";
|
||
import { NextResponse } from "next/server";
|
||
|
||
/**
|
||
* GET /api/config/:slug
|
||
*
|
||
* :slug → bundle ID (önerilen) örn: com.sirket.uygulama
|
||
* → numeric app ID (geriye dönük uyumluluk) örn: 4
|
||
*
|
||
* Kimlik doğrulama — iki yöntemden biri:
|
||
* Authorization: Bearer <CONFIG_API_TOKEN>
|
||
* ?token=<CONFIG_API_TOKEN>
|
||
*/
|
||
export async function GET(
|
||
request: Request,
|
||
{ params }: { params: Promise<{ slug: string }> }
|
||
) {
|
||
// ── Auth ──────────────────────────────────────────────────────────────
|
||
const apiToken = process.env.CONFIG_API_TOKEN;
|
||
if (apiToken) {
|
||
const authHeader = request.headers.get("Authorization") ?? "";
|
||
const url = new URL(request.url);
|
||
const queryToken = url.searchParams.get("token") ?? "";
|
||
const bearerToken = authHeader.startsWith("Bearer ")
|
||
? authHeader.slice(7)
|
||
: "";
|
||
|
||
if ((bearerToken || queryToken) !== apiToken) {
|
||
return NextResponse.json(
|
||
{ error: "Unauthorized" },
|
||
{
|
||
status: 401,
|
||
headers: { "WWW-Authenticate": 'Bearer realm="config"' },
|
||
}
|
||
);
|
||
}
|
||
}
|
||
|
||
// ── Lookup ────────────────────────────────────────────────────────────
|
||
const { slug } = await params;
|
||
const numericId = parseInt(slug);
|
||
const isNumeric = !isNaN(numericId) && String(numericId) === slug;
|
||
|
||
const app = await db.query.apps.findFirst({
|
||
where: isNumeric
|
||
? eq(apps.id, numericId)
|
||
: eq(apps.bundleId, slug),
|
||
});
|
||
|
||
if (!app) {
|
||
return NextResponse.json({ error: "App not found" }, { status: 404 });
|
||
}
|
||
|
||
// Numeric ID ile gelindiyse bundle ID'li URL'e kalıcı yönlendir
|
||
if (isNumeric) {
|
||
const url = new URL(request.url);
|
||
url.pathname = `/api/config/${app.bundleId}`;
|
||
return NextResponse.redirect(url.toString(), 301);
|
||
}
|
||
|
||
// ── Config ────────────────────────────────────────────────────────────
|
||
const configs = await db.query.remoteConfig.findMany({
|
||
where: eq(remoteConfig.appId, app.id),
|
||
});
|
||
|
||
const configObject = configs.reduce<Record<string, unknown>>((acc, c) => {
|
||
acc[c.configKey] = c.configValue;
|
||
return acc;
|
||
}, {});
|
||
|
||
return NextResponse.json(configObject, {
|
||
headers: { "Cache-Control": "no-store" },
|
||
});
|
||
}
|