diff --git a/app/[slug]/page.tsx b/app/[slug]/page.tsx index 104cf50..89ce625 100644 --- a/app/[slug]/page.tsx +++ b/app/[slug]/page.tsx @@ -202,7 +202,7 @@ function PublicWishlistContent() { const maxForMe = item.remainingQuantity + (myClaim?.quantity ?? 0); const showQuantitySummary = item.quantity > 1 && siteSettings.showQuantity; const sold = item.remainingQuantity === 0 && !myClaim; - const canClaim = siteSettings.claimingEnabled; + const canClaim = siteSettings.claimingEnabled && Boolean(currentGuestId); return (
} ) { try { + const { slug } = await params; const isAdmin = verifyAdminToken(request); const guest = await getGuestFromRequest(request); - if (!isAdmin && !guest) { - return NextResponse.json({ error: 'Convite necessário' }, { status: 401 }); - } - - const { slug } = await params; const wishlist = await db .select() @@ -29,11 +25,11 @@ export async function GET( ); } - // Only return public wishlists (admin can see all) - if (!wishlist[0].isPublic && !isAdmin) { + // Public wishlists can be viewed anonymously; private wishlists require admin or guest access. + if (!wishlist[0].isPublic && !isAdmin && !guest) { return NextResponse.json( - { error: 'Wishlist not found' }, - { status: 404 } + { error: 'Convite necessário' }, + { status: 401 } ); } diff --git a/app/api/items/[id]/route.ts b/app/api/items/[id]/route.ts index 34a424a..e79a6b4 100644 --- a/app/api/items/[id]/route.ts +++ b/app/api/items/[id]/route.ts @@ -11,12 +11,6 @@ export async function GET( try { const { id } = await params; - const isAdmin = verifyAdminToken(request); - const guest = await getGuestFromRequest(request); - if (!isAdmin && !guest) { - return NextResponse.json({ error: 'Convite necessário' }, { status: 401 }); - } - // Get item const item = await db .select() @@ -45,10 +39,13 @@ export async function GET( ); } - if (!wishlist[0].isPublic && !isAdmin) { + const isAdmin = verifyAdminToken(request); + const guest = await getGuestFromRequest(request); + + if (!wishlist[0].isPublic && !isAdmin && !guest) { return NextResponse.json( - { error: 'This item is private' }, - { status: 403 } + { error: 'Convite necessário' }, + { status: 401 } ); } diff --git a/app/api/public/wishlists/route.ts b/app/api/public/wishlists/route.ts index 802cd30..4c3177f 100644 --- a/app/api/public/wishlists/route.ts +++ b/app/api/public/wishlists/route.ts @@ -1,16 +1,9 @@ -import { NextRequest, NextResponse } from 'next/server'; +import { NextResponse } from 'next/server'; import { eq, asc } from 'drizzle-orm'; import { db, wishlists } from '@/lib/db'; -import { getGuestFromRequest, verifyAdminToken } from '@/lib/auth/tokens'; -export async function GET(request: NextRequest) { +export async function GET() { try { - const isAdmin = verifyAdminToken(request); - const guest = await getGuestFromRequest(request); - if (!isAdmin && !guest) { - return NextResponse.json({ error: 'Convite necessário' }, { status: 401 }); - } - // Fetch only public wishlists const publicWishlists = await db .select() diff --git a/app/api/wishlists/[id]/items/route.ts b/app/api/wishlists/[id]/items/route.ts index ca1fcda..77829b2 100644 --- a/app/api/wishlists/[id]/items/route.ts +++ b/app/api/wishlists/[id]/items/route.ts @@ -11,12 +11,6 @@ export async function GET( try { const { id } = await params; - const isAdmin = verifyAdminToken(request); - const guest = await getGuestFromRequest(request); - if (!isAdmin && !guest) { - return NextResponse.json({ error: 'Convite necessário' }, { status: 401 }); - } - // Check if wishlist exists const wishlist = await db .select() @@ -31,11 +25,14 @@ export async function GET( ); } - // Permissions: guest can only see public wishlists; admin sees all - if (!wishlist[0].isPublic && !isAdmin) { + const isAdmin = verifyAdminToken(request); + const guest = await getGuestFromRequest(request); + + // Public wishlists can be viewed anonymously; private wishlists require admin or guest access. + if (!wishlist[0].isPublic && !isAdmin && !guest) { return NextResponse.json( - { error: 'This wishlist is private' }, - { status: 403 } + { error: 'Convite necessário' }, + { status: 401 } ); } diff --git a/components/guest-guard.tsx b/components/guest-guard.tsx index 0acd5f5..e0ffef9 100644 --- a/components/guest-guard.tsx +++ b/components/guest-guard.tsx @@ -1,7 +1,7 @@ 'use client'; import { useEffect, useState } from 'react'; -import { authApi } from '@/lib/api'; +import { authApi, wishlistsApi } from '@/lib/api'; type Status = 'checking' | { kind: 'ok'; guestName: string } | 'denied'; @@ -21,6 +21,15 @@ export default function GuestGuard({ children }: { children: React.ReactNode }) if (who.role === 'admin' || who.role === 'guest') { setStatus({ kind: 'ok', guestName: who.guest?.name ?? 'admin' }); } else { + const slug = window.location.pathname.split('/').filter(Boolean)[0]; + if (slug) { + const wishlist = await wishlistsApi.getBySlug(slug); + if (cancelled) return; + if (wishlist.isPublic) { + setStatus({ kind: 'ok', guestName: 'visitante' }); + return; + } + } setStatus('denied'); } } catch {