← back to Norma
app/api/gmail/messages/[id]/mark-read/route.ts
53 lines
// POST /api/gmail/messages/[id]/mark-read — record that the CURRENT user has
// read this message. Idempotent — re-calling does nothing (existing row stays).
// Also flips the legacy global is_read flag so existing list-view logic works.
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
export const runtime = 'nodejs';
export async function POST(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const auth = requireRole(request, 'admin', 'staff', 'intern');
if (auth instanceof NextResponse) return auth;
const { id } = await params;
if (!id) return NextResponse.json({ error: 'missing id' }, { status: 400 });
// Resolve current user id
const userRow = await query<{ id: string }>(
`SELECT id FROM tier_credentials WHERE username = $1 LIMIT 1`,
[auth.username],
);
if (userRow.rows.length === 0) {
return NextResponse.json({ error: 'session user not found in credentials' }, { status: 403 });
}
const userId = userRow.rows[0].id;
// Verify message exists
const msgRow = await query<{ id: string }>(
`SELECT id FROM gmail_messages WHERE id = $1 LIMIT 1`,
[id],
);
if (msgRow.rows.length === 0) {
return NextResponse.json({ error: 'message not found' }, { status: 404 });
}
// Insert read receipt (idempotent via PK conflict)
await query(
`INSERT INTO gmail_message_reads (message_id, user_id)
VALUES ($1, $2)
ON CONFLICT (message_id, user_id) DO NOTHING`,
[id, userId],
);
// Also flip the legacy is_read flag so existing UI markers still work.
await query(
`UPDATE gmail_messages SET is_read = TRUE WHERE id = $1 AND is_read = FALSE`,
[id],
);
return NextResponse.json({ ok: true, message_id: id, user_id: userId });
}