feat: add edited_at column to notes and implement note update functionality with audit logging

This commit is contained in:
2025-11-18 09:43:39 +01:00
parent acb7117c7d
commit fae7615818
4 changed files with 222 additions and 83 deletions

View File

@@ -68,5 +68,70 @@ async function deleteNoteHandler(req, { params }) {
}
}
async function updateNoteHandler(req, { params }) {
const { id } = await params;
const noteId = id;
const { note: noteText } = await req.json();
if (!noteText || !noteId) {
return NextResponse.json({ error: "Missing note or ID" }, { status: 400 });
}
try {
// Get original note for audit log and permission check
const originalNote = db
.prepare("SELECT * FROM notes WHERE note_id = ?")
.get(noteId);
if (!originalNote) {
return NextResponse.json({ error: "Note not found" }, { status: 404 });
}
// Check if user has permission to update this note
// Users can update their own notes, or admins can update any note
const userRole = req.user?.role;
const userId = req.user?.id;
if (userRole !== 'admin' && originalNote.created_by !== userId) {
return NextResponse.json({ error: "Unauthorized to update this note" }, { status: 403 });
}
// Update the note
db.prepare(
`
UPDATE notes SET note = ?, edited_at = datetime('now', 'localtime') WHERE note_id = ?
`
).run(noteText, noteId);
// Log note update
await logApiActionSafe(
req,
AUDIT_ACTIONS.NOTE_UPDATE,
RESOURCE_TYPES.NOTE,
noteId,
req.auth,
{
originalNote: {
note_length: originalNote?.note?.length || 0,
project_id: originalNote?.project_id,
task_id: originalNote?.task_id,
},
updatedNote: {
note_length: noteText.length,
},
}
);
return NextResponse.json({ success: true });
} catch (error) {
console.error("Error updating note:", error);
return NextResponse.json(
{ error: "Failed to update note", details: error.message },
{ status: 500 }
);
}
}
// Protected route - require user authentication
export const DELETE = withUserAuth(deleteNoteHandler);
export const PUT = withUserAuth(updateNoteHandler);

View File

@@ -136,50 +136,7 @@ async function deleteNoteHandler(req, { params }) {
return NextResponse.json({ success: true });
}
async function updateNoteHandler(req, { params }) {
const { id } = await params;
const noteId = id;
const { note } = await req.json();
if (!note || !noteId) {
return NextResponse.json({ error: "Missing note or ID" }, { status: 400 });
}
// Get original note for audit log
const originalNote = db
.prepare("SELECT * FROM notes WHERE note_id = ?")
.get(noteId);
db.prepare(
`
UPDATE notes SET note = ? WHERE note_id = ?
`
).run(note, noteId);
// Log note update
await logApiActionSafe(
req,
AUDIT_ACTIONS.NOTE_UPDATE,
RESOURCE_TYPES.NOTE,
noteId,
req.auth, // Use req.auth instead of req.session
{
originalNote: {
note_length: originalNote?.note?.length || 0,
project_id: originalNote?.project_id,
task_id: originalNote?.task_id,
},
updatedNote: {
note_length: note.length,
},
}
);
return NextResponse.json({ success: true });
}
// Protected routes - require authentication
export const GET = withReadAuth(getNotesHandler);
export const POST = withUserAuth(createNoteHandler);
export const DELETE = withUserAuth(deleteNoteHandler);
export const PUT = withUserAuth(updateNoteHandler);