All files / src/app/api/invitations/accept route.ts

95.45% Statements 21/22
100% Branches 8/8
100% Functions 2/2
95.45% Lines 21/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60              4x 4x 4x 1x           3x 3x   3x 1x           2x             12x   12x 12x 1x             11x 11x 12x 1x     10x 10x 4x       6x      
import { NextRequest, NextResponse } from "next/server";
import { getSession } from "@/lib/auth";
import { getDb } from "@/lib/db";
import { InvitationAcceptService } from "@/server/services/InvitationAcceptService";
import { errorResponse } from "@/server/api/http-errors";
 
export async function GET(request: NextRequest) {
  try {
    const token = request.nextUrl.searchParams.get("token");
    if (!token) {
      return NextResponse.json(
        { error: "Token is required" },
        { status: 400 }
      );
    }
 
    const db = getDb();
    const preview = await InvitationAcceptService.fromDb(db).getPreview(token);
 
    if (!preview) {
      return NextResponse.json(
        { error: "Invitation not found or expired" },
        { status: 404 }
      );
    }
 
    return NextResponse.json(preview);
  } catch (error) {
    return errorResponse(error);
  }
}
 
export async function POST(request: NextRequest) {
  try {
    // Token check first — cheap early return for malformed URLs (no auth cost).
    const token = request.nextUrl.searchParams.get("token");
    if (!token) {
      return NextResponse.json(
        { error: "Token is required" },
        { status: 400 }
      );
    }
 
    // Require session — POST accept must know who is accepting.
    const session = await getSession();
    const userId = session?.user?.id;
    if (!userId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
 
    const db = getDb();
    const { collectionId } = await InvitationAcceptService.fromDb(db).accept(token, userId);
    return NextResponse.json({ message: "Invitation accepted successfully", collectionId });
  } catch (error) {
    // errorResponse passes InvitationAcceptError's curated copy + status through,
    // and logs+hides anything internal.
    return errorResponse(error);
  }
}