143 lines
3.5 KiB
JavaScript
143 lines
3.5 KiB
JavaScript
// Force this API route to use Node.js runtime for database access
|
|
export const runtime = "nodejs";
|
|
|
|
import db from "@/lib/db";
|
|
import { NextResponse } from "next/server";
|
|
import { withUserAuth, withReadAuth } from "@/lib/middleware/auth";
|
|
import {
|
|
logApiActionSafe,
|
|
AUDIT_ACTIONS,
|
|
RESOURCE_TYPES,
|
|
} from "@/lib/auditLogSafe.js";
|
|
|
|
async function getNotesHandler(req) {
|
|
const { searchParams } = new URL(req.url);
|
|
const projectId = searchParams.get("project_id");
|
|
const taskId = searchParams.get("task_id");
|
|
|
|
let query;
|
|
let params;
|
|
|
|
if (projectId) {
|
|
query = `
|
|
SELECT n.*,
|
|
u.name as created_by_name,
|
|
u.username as created_by_username
|
|
FROM notes n
|
|
LEFT JOIN users u ON n.created_by = u.id
|
|
WHERE n.project_id = ?
|
|
ORDER BY n.note_date DESC
|
|
`;
|
|
params = [projectId];
|
|
} else if (taskId) {
|
|
query = `
|
|
SELECT n.*,
|
|
u.name as created_by_name,
|
|
u.username as created_by_username
|
|
FROM notes n
|
|
LEFT JOIN users u ON n.created_by = u.id
|
|
WHERE n.task_id = ?
|
|
ORDER BY n.note_date DESC
|
|
`;
|
|
params = [taskId];
|
|
} else {
|
|
return NextResponse.json({ error: "project_id or task_id is required" }, { status: 400 });
|
|
}
|
|
|
|
try {
|
|
const notes = db.prepare(query).all(...params);
|
|
return NextResponse.json(notes);
|
|
} catch (error) {
|
|
console.error("Error fetching notes:", error);
|
|
return NextResponse.json(
|
|
{ error: "Failed to fetch notes" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
async function createNoteHandler(req) {
|
|
const { project_id, task_id, note } = await req.json();
|
|
|
|
if (!note || (!project_id && !task_id)) {
|
|
return NextResponse.json({ error: "Missing fields" }, { status: 400 });
|
|
}
|
|
|
|
try {
|
|
const result = db
|
|
.prepare(
|
|
`
|
|
INSERT INTO notes (project_id, task_id, note, created_by, note_date)
|
|
VALUES (?, ?, ?, ?, datetime('now', 'localtime'))
|
|
`
|
|
)
|
|
.run(project_id || null, task_id || null, note, req.user?.id || null);
|
|
|
|
// Get the created note with user info
|
|
const createdNote = db
|
|
.prepare(
|
|
`
|
|
SELECT n.*,
|
|
u.name as created_by_name,
|
|
u.username as created_by_username
|
|
FROM notes n
|
|
LEFT JOIN users u ON n.created_by = u.id
|
|
WHERE n.note_id = ?
|
|
`
|
|
)
|
|
.get(result.lastInsertRowid);
|
|
|
|
// Log note creation
|
|
await logApiActionSafe(
|
|
req,
|
|
AUDIT_ACTIONS.NOTE_CREATE,
|
|
RESOURCE_TYPES.NOTE,
|
|
result.lastInsertRowid.toString(),
|
|
req.auth, // Use req.auth instead of req.session
|
|
{
|
|
noteData: { project_id, task_id, note_length: note.length },
|
|
}
|
|
);
|
|
|
|
return NextResponse.json(createdNote);
|
|
} catch (error) {
|
|
console.error("Error creating note:", error);
|
|
return NextResponse.json(
|
|
{ error: "Failed to create note", details: error.message },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
async function deleteNoteHandler(req, { params }) {
|
|
const { id } = await params;
|
|
|
|
// Get note data before deletion for audit log
|
|
const note = db.prepare("SELECT * FROM notes WHERE note_id = ?").get(id);
|
|
|
|
db.prepare("DELETE FROM notes WHERE note_id = ?").run(id);
|
|
|
|
// Log note deletion
|
|
await logApiActionSafe(
|
|
req,
|
|
AUDIT_ACTIONS.NOTE_DELETE,
|
|
RESOURCE_TYPES.NOTE,
|
|
id,
|
|
req.auth, // Use req.auth instead of req.session
|
|
{
|
|
deletedNote: {
|
|
project_id: note?.project_id,
|
|
task_id: note?.task_id,
|
|
note_length: note?.note?.length || 0,
|
|
},
|
|
}
|
|
);
|
|
|
|
return NextResponse.json({ success: true });
|
|
}
|
|
|
|
// Protected routes - require authentication
|
|
export const GET = withReadAuth(getNotesHandler);
|
|
export const POST = withUserAuth(createNoteHandler);
|
|
export const DELETE = withUserAuth(deleteNoteHandler);
|