feat(listings): add user-facing scam/abuse report flow (GOO-19)

- Add ListingFlag model with FlagReason enum (SCAM, DUPLICATE, WRONG_INFO, ALREADY_SOLD, INAPPROPRIATE)
- Add POST /listings/:id/report endpoint with rate limiting and duplicate prevention
- Auto-flag listings with ≥3 reports to PENDING_REVIEW for moderator review
- Add GET /admin/flagged-listings endpoint for admin moderation queue
- Add "Báo cáo" button + modal on listing detail page (Vietnamese UI)
- Add Prisma migration for listing_flags table with unique constraint per user/listing

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-23 00:19:12 +07:00
parent 94d462ef4f
commit 0329455e9a
26 changed files with 615 additions and 57 deletions

View File

@@ -0,0 +1,39 @@
-- CreateEnum
CREATE TYPE "FlagReason" AS ENUM ('SCAM', 'DUPLICATE', 'WRONG_INFO', 'ALREADY_SOLD', 'INAPPROPRIATE');
-- CreateEnum
CREATE TYPE "FlagStatus" AS ENUM ('PENDING', 'REVIEWED', 'DISMISSED');
-- CreateTable
CREATE TABLE "listing_flags" (
"id" TEXT NOT NULL,
"listingId" TEXT NOT NULL,
"reporterId" TEXT NOT NULL,
"reason" "FlagReason" NOT NULL,
"description" TEXT,
"status" "FlagStatus" NOT NULL DEFAULT 'PENDING',
"reviewedBy" TEXT,
"reviewedAt" TIMESTAMP(3),
"reviewNotes" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "listing_flags_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "listing_flags_listingId_idx" ON "listing_flags"("listingId");
-- CreateIndex
CREATE INDEX "listing_flags_status_createdAt_idx" ON "listing_flags"("status", "createdAt" DESC);
-- CreateIndex
CREATE INDEX "listing_flags_reporterId_idx" ON "listing_flags"("reporterId");
-- CreateIndex (unique: one report per user per listing)
CREATE UNIQUE INDEX "listing_flags_listingId_reporterId_key" ON "listing_flags"("listingId", "reporterId");
-- AddForeignKey
ALTER TABLE "listing_flags" ADD CONSTRAINT "listing_flags_listingId_fkey" FOREIGN KEY ("listingId") REFERENCES "Listing"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "listing_flags" ADD CONSTRAINT "listing_flags_reporterId_fkey" FOREIGN KEY ("reporterId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;