fix(security): Enforce isAuthenticated across new settings and skills routes

This commit is contained in:
diegosouzapw
2026-04-03 14:03:50 -03:00
parent 02bc2e3ddb
commit 7f723a6bd5
8 changed files with 52 additions and 12 deletions

View File

@@ -1,7 +1,11 @@
import { NextResponse } from "next/server";
import { clearAllLKGP } from "@/lib/db/settings";
import { isAuthenticated } from "@/shared/utils/apiAuth";
export async function DELETE() {
export async function DELETE(request: Request) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
clearAllLKGP();
return NextResponse.json({ cleared: true });

View File

@@ -1,8 +1,12 @@
import { NextResponse } from "next/server";
import { getDbInstance } from "@/lib/db/core";
import { getCallLogRetentionDays } from "@/lib/logEnv";
import { isAuthenticated } from "@/shared/utils/apiAuth";
export async function POST() {
export async function POST(request: Request) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const db = getDbInstance();
const retentionMs = getCallLogRetentionDays() * 24 * 60 * 60 * 1000;

View File

@@ -1,7 +1,10 @@
import { NextResponse } from "next/server";
import { skillExecutor } from "@/lib/skills/executor";
export async function GET() {
export async function GET(request: Request) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const executions = skillExecutor.listExecutions();
return NextResponse.json({ executions });
@@ -11,14 +14,28 @@ export async function GET() {
}
}
export async function POST(request: Request) {
try {
const body = await request.json();
const { skillName, input, apiKeyId, sessionId } = body;
import { z } from "zod";
import { validateBody, isValidationFailure } from "@/shared/validation/helpers";
import { isAuthenticated } from "@/shared/utils/apiAuth";
if (!skillName || !apiKeyId) {
return NextResponse.json({ error: "skillName and apiKeyId are required" }, { status: 400 });
const executionSchema = z.object({
skillName: z.string().min(1),
apiKeyId: z.string().min(1),
input: z.record(z.unknown()).optional(),
sessionId: z.string().optional(),
});
export async function POST(request: Request) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const rawBody = await request.json();
const validation = validateBody(executionSchema, rawBody);
if (isValidationFailure(validation)) {
return validation.response;
}
const { skillName, input, apiKeyId, sessionId } = validation.data;
const execution = await skillExecutor.execute(skillName, input || {}, {
apiKeyId,

View File

@@ -3,6 +3,8 @@ import { z } from "zod";
import { validateBody, isValidationFailure } from "@/shared/validation/helpers";
import { skillRegistry } from "@/lib/skills/registry";
import { isAuthenticated } from "@/shared/utils/apiAuth";
const marketplaceInstallSchema = z.object({
name: z.string().min(1).max(64),
description: z.string().min(1).max(1024),
@@ -12,6 +14,9 @@ const marketplaceInstallSchema = z.object({
});
export async function POST(request: Request) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const rawBody = await request.json();
const validation = validateBody(marketplaceInstallSchema, rawBody);

View File

@@ -1,7 +1,11 @@
import { NextResponse } from "next/server";
import { getSettings } from "@/lib/db/settings";
import { isAuthenticated } from "@/shared/utils/apiAuth";
export async function GET(request: Request) {
if (!(await isAuthenticated(request))) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const { searchParams } = new URL(request.url);
const q = searchParams.get("q") || "";

View File

@@ -2250,7 +2250,9 @@
"adaptiveVolumeRoutingDesc": "Scale connections dynamically based on payload volume and throughput pressure.",
"days": "Days",
"lkgp": "LKGP Mode",
"lkgpDesc": "Last Known Good Provider (Predictable resilience)"
"lkgpDesc": "Last Known Good Provider (Predictable resilience)",
"purgeExpiredLogs": "Purge Expired Logs",
"purgeLogsFailed": "Failed to purge logs"
},
"translator": {
"title": "Translator",

View File

@@ -2248,7 +2248,9 @@
"skillsEnabledDesc": "Permite aos agentes executar consultas e gerar arquivos.",
"skillsComingSoon": "Marketplace em breve.",
"memorySkillsTitle": "Memória e Skills",
"memorySkillsDesc": "Contexto persistente e capacidades A2A"
"memorySkillsDesc": "Contexto persistente e capacidades A2A",
"purgeExpiredLogs": "Purgar Logs Expirados",
"purgeLogsFailed": "Falha ao purgar logs"
},
"translator": {
"title": "Tradutor",

View File

@@ -2248,7 +2248,9 @@
"skillsEnabledDesc": "Permite aos agentes executar consultas e gerar arquivos.",
"skillsComingSoon": "Marketplace em breve.",
"memorySkillsTitle": "Memória e Skills",
"memorySkillsDesc": "Contexto persistente e capacidades A2A"
"memorySkillsDesc": "Contexto persistente e capacidades A2A",
"purgeExpiredLogs": "Purgar Logs Expirados",
"purgeLogsFailed": "Falha ao purgar logs"
},
"translator": {
"title": "Tradutor",