security: enforce family ownership on all baby-data API routes
All collection routes (events, growth, doctor-notes, journal, milestones, vaccinations, milk, reminders, teeth, search, export) now verify the requested babyId belongs to the authenticated user's family before querying or writing. All [id] mutation routes verify record ownership via nested baby→familyId before any PATCH/DELETE. Additional fixes: admin config masks sensitive secrets in GET response, invite send-email enforces PARENT role, photo serving requires authentication, baby PATCH restricted to own-family PARENT. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,11 @@ export async function GET(req: Request) {
|
||||
|
||||
if (!babyId) return NextResponse.json({ error: "babyId requis" }, { status: 400 });
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const ownedBaby = await prisma.baby.findFirst({ where: { id: babyId, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ error: "Bébé introuvable" }, { status: 404 });
|
||||
|
||||
const teeth = await prisma.tooth.findMany({
|
||||
where: { babyId },
|
||||
orderBy: { appearedAt: "asc" },
|
||||
@@ -30,6 +35,11 @@ export async function POST(req: Request) {
|
||||
return NextResponse.json({ error: "Champs requis manquants" }, { status: 400 });
|
||||
}
|
||||
|
||||
const postFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!postFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const postBaby = await prisma.baby.findFirst({ where: { id: babyId, familyId: postFamilyId } });
|
||||
if (!postBaby) return NextResponse.json({ error: "Bébé introuvable" }, { status: 404 });
|
||||
|
||||
const tooth = await prisma.tooth.upsert({
|
||||
where: { babyId_code: { babyId, code } },
|
||||
update: {
|
||||
|
||||
Reference in New Issue
Block a user