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:
@@ -30,13 +30,17 @@ async function requireSuperAdmin() {
|
||||
return session;
|
||||
}
|
||||
|
||||
const SENSITIVE_KEYS = new Set(["mailgun_api_key", "smtp_pass", "cron_secret", "pushover_app_token"]);
|
||||
|
||||
export async function GET() {
|
||||
const session = await requireSuperAdmin();
|
||||
if (!session) return NextResponse.json({ error: "Non autorisé" }, { status: 403 });
|
||||
|
||||
const configs = await prisma.systemConfig.findMany();
|
||||
const result: Record<string, string> = {};
|
||||
for (const c of configs) result[c.key] = c.value;
|
||||
for (const c of configs) {
|
||||
result[c.key] = SENSITIVE_KEYS.has(c.key) && c.value ? "••••••" : c.value;
|
||||
}
|
||||
return NextResponse.json(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@ export async function PATCH(
|
||||
const { id } = await params;
|
||||
const { name, birthDate, gender } = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const role = (session.user as { role?: string }).role;
|
||||
if (role !== "PARENT") return NextResponse.json({ error: "Réservé aux parents" }, { status: 403 });
|
||||
const ownedBaby = await prisma.baby.findFirst({ where: { id, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ error: "Bébé introuvable" }, { status: 404 });
|
||||
|
||||
const baby = await prisma.baby.update({
|
||||
where: { id },
|
||||
data: {
|
||||
|
||||
@@ -22,6 +22,11 @@ export async function DELETE(
|
||||
return NextResponse.json({ error: "Observation introuvable" }, { status: 404 });
|
||||
}
|
||||
|
||||
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: note.babyId, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
|
||||
if (note.userId !== session.user.id) {
|
||||
return NextResponse.json({ error: "Vous ne pouvez supprimer que vos propres observations" }, { status: 403 });
|
||||
}
|
||||
@@ -50,6 +55,11 @@ export async function PATCH(
|
||||
return NextResponse.json({ error: "Observation introuvable" }, { status: 404 });
|
||||
}
|
||||
|
||||
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: note.babyId, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
|
||||
if (note.userId !== session.user.id) {
|
||||
return NextResponse.json({ error: "Vous ne pouvez modifier que vos propres observations" }, { status: 403 });
|
||||
}
|
||||
|
||||
@@ -12,6 +12,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 notes = await prisma.doctorNote.findMany({
|
||||
where: { babyId },
|
||||
orderBy: { date: "desc" },
|
||||
@@ -37,6 +42,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 noteDate = new Date(date);
|
||||
noteDate.setHours(12, 0, 0, 0);
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ export async function PATCH(
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const owned = await prisma.event.findFirst({ where: { id, baby: { familyId } } });
|
||||
if (!owned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
const event = await prisma.event.update({
|
||||
where: { id },
|
||||
data: {
|
||||
@@ -38,6 +43,12 @@ export async function DELETE(
|
||||
if (!session?.user?.id) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
const delFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!delFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const delOwned = await prisma.event.findFirst({ where: { id, baby: { familyId: delFamilyId } } });
|
||||
if (!delOwned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
await prisma.event.delete({ where: { id } });
|
||||
await logAudit(session, { action: "event.delete", targetId: id });
|
||||
return new NextResponse(null, { status: 204 });
|
||||
|
||||
@@ -18,6 +18,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 where: Record<string, unknown> = { babyId };
|
||||
if (type) where.type = type;
|
||||
if (dateFrom || dateTo) {
|
||||
@@ -52,6 +57,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 event = await prisma.event.create({
|
||||
data: {
|
||||
babyId,
|
||||
|
||||
@@ -17,6 +17,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 where: Record<string, unknown> = { babyId };
|
||||
if (dateFrom || dateTo) {
|
||||
where.startedAt = {
|
||||
|
||||
@@ -12,6 +12,11 @@ export async function PATCH(req: Request, { params }: { params: Promise<{ id: st
|
||||
const { id } = await params;
|
||||
const { date, weight, height, headCirc, notes } = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const owned = await prisma.growthLog.findFirst({ where: { id, baby: { familyId } } });
|
||||
if (!owned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
const log = await prisma.growthLog.update({
|
||||
where: { id },
|
||||
data: {
|
||||
@@ -34,6 +39,12 @@ export async function DELETE(_req: Request, { params }: { params: Promise<{ id:
|
||||
if (role === "READONLY") return NextResponse.json({ error: "Accès en lecture seule" }, { status: 403 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
const delFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!delFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const delOwned = await prisma.growthLog.findFirst({ where: { id, baby: { familyId: delFamilyId } } });
|
||||
if (!delOwned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
await prisma.growthLog.delete({ where: { id } });
|
||||
|
||||
return new NextResponse(null, { status: 204 });
|
||||
|
||||
@@ -11,6 +11,11 @@ export async function GET(req: Request) {
|
||||
const babyId = searchParams.get("babyId");
|
||||
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 logs = await prisma.growthLog.findMany({
|
||||
where: { babyId },
|
||||
orderBy: { date: "asc" },
|
||||
@@ -29,6 +34,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 log = await prisma.growthLog.create({
|
||||
data: {
|
||||
babyId,
|
||||
|
||||
@@ -30,6 +30,10 @@ export async function POST(req: Request) {
|
||||
return NextResponse.json({ error: "Famille introuvable" }, { status: 404 });
|
||||
}
|
||||
|
||||
if (user.role !== "PARENT") {
|
||||
return NextResponse.json({ error: "Réservé aux parents" }, { status: 403 });
|
||||
}
|
||||
|
||||
const origin = req.headers.get("origin") ?? process.env.NEXTAUTH_URL ?? "";
|
||||
const assignedRole = role as Role;
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@ export async function PATCH(
|
||||
const existing = await prisma.journalNote.findUnique({ where: { id } });
|
||||
if (!existing) return NextResponse.json({ error: "Note introuvable" }, { status: 404 });
|
||||
|
||||
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: existing.babyId, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
|
||||
const userRole = (session.user as { role?: string }).role;
|
||||
const isOwner = existing.userId === session.user.id;
|
||||
const isParent = userRole === "PARENT";
|
||||
@@ -48,6 +53,11 @@ export async function DELETE(
|
||||
const existing = await prisma.journalNote.findUnique({ where: { id } });
|
||||
if (!existing) return NextResponse.json({ error: "Note introuvable" }, { status: 404 });
|
||||
|
||||
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: existing.babyId, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
|
||||
const userRole = (session.user as { role?: string }).role;
|
||||
const isOwner = existing.userId === session.user.id;
|
||||
const isParent = userRole === "PARENT";
|
||||
|
||||
@@ -12,6 +12,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 where: Record<string, unknown> = { babyId };
|
||||
|
||||
if (date) {
|
||||
@@ -47,6 +52,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 noteDate = new Date(date);
|
||||
noteDate.setHours(12, 0, 0, 0);
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ export async function PATCH(
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const owned = await prisma.milestone.findFirst({ where: { id, baby: { familyId } } });
|
||||
if (!owned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
const milestone = await prisma.milestone.update({
|
||||
where: { id },
|
||||
data: {
|
||||
@@ -43,6 +48,12 @@ export async function DELETE(
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
const delFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!delFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const delOwned = await prisma.milestone.findFirst({ where: { id, baby: { familyId: delFamilyId } } });
|
||||
if (!delOwned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
await prisma.milestone.delete({ where: { id } });
|
||||
return new NextResponse(null, { status: 204 });
|
||||
}
|
||||
|
||||
@@ -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 milestones = await prisma.milestone.findMany({
|
||||
where: { babyId },
|
||||
orderBy: { date: "desc" },
|
||||
@@ -35,6 +40,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 milestone = await prisma.milestone.create({
|
||||
data: {
|
||||
babyId,
|
||||
|
||||
@@ -12,6 +12,11 @@ export async function PATCH(
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const owned = await prisma.milkStock.findFirst({ where: { id, baby: { familyId } } });
|
||||
if (!owned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
const data: Record<string, unknown> = {};
|
||||
if (body.volume !== undefined) data.volume = parseFloat(body.volume);
|
||||
if (body.notes !== undefined) data.notes = body.notes;
|
||||
@@ -34,6 +39,12 @@ export async function DELETE(
|
||||
if (!session?.user?.id) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
const delFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!delFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const delOwned = await prisma.milkStock.findFirst({ where: { id, baby: { familyId: delFamilyId } } });
|
||||
if (!delOwned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
await prisma.milkStock.delete({ where: { id } });
|
||||
return new NextResponse(null, { status: 204 });
|
||||
}
|
||||
|
||||
@@ -17,6 +17,11 @@ export async function GET(req: Request) {
|
||||
const babyId = searchParams.get("babyId");
|
||||
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 stocks = await prisma.milkStock.findMany({
|
||||
where: { babyId },
|
||||
orderBy: { storedAt: "desc" },
|
||||
@@ -36,6 +41,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 loc = location ?? "fridge";
|
||||
const storedDate = storedAt ? new Date(storedAt) : new Date();
|
||||
const hours = expiryHours ?? EXPIRY_HOURS[loc] ?? EXPIRY_HOURS.fridge;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { readFile } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import { auth } from "@/lib/auth";
|
||||
|
||||
const UPLOAD_DIR = process.env.UPLOAD_DIR ?? join(process.cwd(), "public", "uploads");
|
||||
|
||||
@@ -12,6 +13,9 @@ const MIME: Record<string, string> = {
|
||||
};
|
||||
|
||||
export async function GET(_req: Request, { params }: { params: Promise<{ filename: string }> }) {
|
||||
const session = await auth();
|
||||
if (!session?.user?.id) return new Response("Not found", { status: 404 });
|
||||
|
||||
const { filename } = await params;
|
||||
|
||||
// Prevent path traversal
|
||||
|
||||
@@ -12,6 +12,11 @@ export async function PATCH(
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const owned = await prisma.medicationReminder.findFirst({ where: { id, baby: { familyId } } });
|
||||
if (!owned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
const reminder = await prisma.medicationReminder.update({
|
||||
where: { id },
|
||||
data: {
|
||||
@@ -35,6 +40,12 @@ export async function DELETE(
|
||||
if (!session?.user?.id) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
const delFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!delFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const delOwned = await prisma.medicationReminder.findFirst({ where: { id, baby: { familyId: delFamilyId } } });
|
||||
if (!delOwned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
await prisma.medicationReminder.delete({ where: { id } });
|
||||
return new NextResponse(null, { status: 204 });
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ export async function GET(req: Request) {
|
||||
const babyId = searchParams.get("babyId");
|
||||
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 reminders = await prisma.medicationReminder.findMany({
|
||||
where: { babyId },
|
||||
orderBy: { createdAt: "desc" },
|
||||
@@ -29,6 +34,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 reminder = await prisma.medicationReminder.create({
|
||||
data: {
|
||||
babyId,
|
||||
|
||||
@@ -12,6 +12,11 @@ export async function GET(req: Request) {
|
||||
|
||||
if (!babyId || q.length < 2) return NextResponse.json({ events: [], notes: [] });
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ events: [], notes: [] });
|
||||
const ownedBaby = await prisma.baby.findFirst({ where: { id: babyId, familyId } });
|
||||
if (!ownedBaby) return NextResponse.json({ events: [], notes: [] });
|
||||
|
||||
const [events, notes] = await Promise.all([
|
||||
prisma.event.findMany({
|
||||
where: {
|
||||
|
||||
@@ -12,6 +12,11 @@ export async function DELETE(req: Request, { params }: { params: Promise<{ code:
|
||||
|
||||
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 });
|
||||
|
||||
await prisma.tooth.delete({
|
||||
where: { babyId_code: { babyId, code } },
|
||||
});
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -18,6 +18,11 @@ export async function PATCH(
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
const familyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!familyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const owned = await prisma.vaccination.findFirst({ where: { id, baby: { familyId } } });
|
||||
if (!owned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
const vaccination = await prisma.vaccination.update({
|
||||
where: { id },
|
||||
data: {
|
||||
@@ -50,6 +55,12 @@ export async function DELETE(
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
const delFamilyId = (session.user as { familyId?: string }).familyId;
|
||||
if (!delFamilyId) return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
||||
const delOwned = await prisma.vaccination.findFirst({ where: { id, baby: { familyId: delFamilyId } } });
|
||||
if (!delOwned) return NextResponse.json({ error: "Introuvable" }, { status: 404 });
|
||||
|
||||
await prisma.vaccination.delete({ where: { id } });
|
||||
return new NextResponse(null, { status: 204 });
|
||||
}
|
||||
|
||||
@@ -13,6 +13,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 vaccinations = await prisma.vaccination.findMany({
|
||||
where: { babyId },
|
||||
orderBy: [{ dueDate: "asc" }, { date: "asc" }],
|
||||
@@ -42,6 +47,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 vaccination = await prisma.vaccination.create({
|
||||
data: {
|
||||
babyId,
|
||||
|
||||
Reference in New Issue
Block a user