first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 22:11:03 +03:00
commit 031582ea2c
98 changed files with 13281 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/db";
import { apiKeys } from "@/db/schema";
import { and, eq } from "drizzle-orm";
import { authenticateWebOrAPIRequest } from "@/app/lib/api-auth";
import { isAdmin } from "@/app/lib/permissions";
import { maskApiKey } from "@/app/lib/jwt";
import {
expiresAtFromDays,
getDaysRemaining,
getExpiryRemainingLabel,
parseExpiresInDaysOptional,
} from "@/app/lib/api-key-utils";
/**
* PATCH /api/v1/admin/users/[id]/api-keys/[keyId]
*
* Body: { "expiresInDays": number | null }
* — null veya 0: süresiz; 13650: bugünden itibaren o kadar gün sonra sona erer
*/
export async function PATCH(
request: NextRequest,
context: { params: Promise<{ id: string; keyId: string }> }
) {
const auth = await authenticateWebOrAPIRequest(request);
if (!auth.authenticated) {
return NextResponse.json({ error: auth.error ?? "Yetkisiz" }, { status: 401 });
}
if (!isAdmin(auth.role!)) {
return NextResponse.json(
{ error: "Bu işlem için admin yetkisi gerekir." },
{ status: 403 }
);
}
const { id: userId, keyId } = await context.params;
let body: { expiresInDays?: unknown };
try {
body = await request.json();
} catch {
return NextResponse.json({ error: "Geçersiz JSON" }, { status: 400 });
}
const parsed = parseExpiresInDaysOptional(body.expiresInDays);
if (!parsed.ok) {
return NextResponse.json({ error: parsed.error }, { status: 400 });
}
const expiresAt =
parsed.value === null ? null : expiresAtFromDays(parsed.value);
const updated = await db
.update(apiKeys)
.set({ expiresAt, updatedAt: new Date() })
.where(and(eq(apiKeys.id, keyId), eq(apiKeys.userId, userId)))
.returning({
id: apiKeys.id,
name: apiKeys.name,
key: apiKeys.key,
expiresAt: apiKeys.expiresAt,
isActive: apiKeys.isActive,
});
if (updated.length === 0) {
return NextResponse.json(
{ error: "Anahtar bulunamadı veya bu kullanıcıya ait değil." },
{ status: 404 }
);
}
const r = updated[0];
const exp = r.expiresAt ?? null;
return NextResponse.json({
success: true,
message: "API anahtarı süresi güncellendi.",
data: {
id: r.id,
name: r.name,
keyPreview: maskApiKey(r.key),
expiresAt: exp?.toISOString() ?? null,
daysRemaining: getDaysRemaining(exp),
remainingLabel: getExpiryRemainingLabel(exp),
isActive: r.isActive,
},
});
}