Update 3 files
This commit is contained in:
1 parent
2db87a1227
commit
63b81b4764
3 files changed
+55
-3
No files matched your search
@@ -207,3 +207,13 @@ Status: implemented
|
||||
vice principals cannot remove conversation records.
|
||||
- Administrative room closure verifies the administrator belongs to the room's
|
||||
school.
|
||||
|
||||
## Phase 8: Leave Record Integrity
|
||||
|
||||
Status: implemented
|
||||
|
||||
- Teacher absence detail endpoints now require authentication, school scope,
|
||||
and either the absence owner or an administrator.
|
||||
- Teachers cannot alter status, or edit/delete a leave once it is approved.
|
||||
- Vice principals cannot delete student leave records; reporters may only
|
||||
withdraw requests before either approval stage is processed.
|
||||
@@ -189,11 +189,18 @@ export async function DELETE(
|
||||
const role = session.user?.role;
|
||||
const userId = session.userId;
|
||||
|
||||
// Only the reporter or admin can delete
|
||||
if (role !== 'SUPER_ADMIN' && role !== 'SCHOOL_ADMIN' && role !== 'VICE_PRINCIPAL') {
|
||||
// Only the reporter can withdraw a still-pending request. Final approval
|
||||
// records cannot be removed by vice principals.
|
||||
if (role !== 'SUPER_ADMIN' && role !== 'SCHOOL_ADMIN') {
|
||||
if (report.reportedBy !== userId) {
|
||||
return NextResponse.json({ error: 'Only the reporter or admin can delete' }, { status: 403 });
|
||||
}
|
||||
if (report.parentApprovalStatus !== 'pending' || report.adminApprovalStatus !== 'pending') {
|
||||
return NextResponse.json({ error: 'Approved or reviewed reports cannot be deleted by the reporter' }, { status: 400 });
|
||||
}
|
||||
}
|
||||
if (role !== 'SUPER_ADMIN' && role !== 'STUDENT' && role !== 'PARENT' && report.schoolId !== session.user?.schoolId) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
|
||||
await db.illnessReport.delete({ where: { id } });
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { getSession } from '@/lib/auth';
|
||||
|
||||
function canManageAbsence(role: string | undefined, teacherId: string, userId: string): boolean {
|
||||
return role === 'SUPER_ADMIN' || role === 'SCHOOL_ADMIN' || (role === 'TEACHER' && teacherId === userId);
|
||||
}
|
||||
|
||||
// GET /api/substitutes/absences/[id] - Get a single absence
|
||||
export async function GET(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const session = await getSession();
|
||||
if (!session) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 });
|
||||
const { id } = await params;
|
||||
const absence = await db.teacherAbsence.findUnique({
|
||||
where: { id },
|
||||
@@ -22,6 +29,12 @@ export async function GET(_req: NextRequest, { params }: { params: Promise<{ id:
|
||||
if (!absence) {
|
||||
return NextResponse.json({ error: 'Absence not found' }, { status: 404 });
|
||||
}
|
||||
if (!canManageAbsence(session.user?.role, absence.teacherId, session.userId)) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
if (session.user?.role !== 'SUPER_ADMIN' && absence.schoolId !== session.user?.schoolId) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
|
||||
return NextResponse.json(absence);
|
||||
} catch (error) {
|
||||
@@ -33,6 +46,8 @@ export async function GET(_req: NextRequest, { params }: { params: Promise<{ id:
|
||||
// PUT /api/substitutes/absences/[id] - Update an absence
|
||||
export async function PUT(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const session = await getSession();
|
||||
if (!session) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 });
|
||||
const { id } = await params;
|
||||
const body = await req.json();
|
||||
|
||||
@@ -40,9 +55,18 @@ export async function PUT(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
if (!existing) {
|
||||
return NextResponse.json({ error: 'Absence not found' }, { status: 404 });
|
||||
}
|
||||
if (!canManageAbsence(session.user?.role, existing.teacherId, session.userId)) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
if (session.user?.role !== 'SUPER_ADMIN' && existing.schoolId !== session.user?.schoolId) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
if (existing.approvalStatus !== 'pending' && session.user?.role === 'TEACHER') {
|
||||
return NextResponse.json({ error: 'Approved leave cannot be edited by the teacher' }, { status: 400 });
|
||||
}
|
||||
|
||||
const data: Record<string, unknown> = {};
|
||||
const simpleFields = ['type', 'reason', 'status', 'notes'];
|
||||
const simpleFields = session.user?.role === 'TEACHER' ? ['type', 'reason', 'notes'] : ['type', 'reason', 'status', 'notes'];
|
||||
|
||||
for (const field of simpleFields) {
|
||||
if (body[field] !== undefined) data[field] = body[field];
|
||||
@@ -70,12 +94,23 @@ export async function PUT(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
// DELETE /api/substitutes/absences/[id] - Delete an absence
|
||||
export async function DELETE(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const session = await getSession();
|
||||
if (!session) return NextResponse.json({ error: 'Not authenticated' }, { status: 401 });
|
||||
const { id } = await params;
|
||||
|
||||
const existing = await db.teacherAbsence.findUnique({ where: { id } });
|
||||
if (!existing) {
|
||||
return NextResponse.json({ error: 'Absence not found' }, { status: 404 });
|
||||
}
|
||||
if (!canManageAbsence(session.user?.role, existing.teacherId, session.userId)) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
if (session.user?.role !== 'SUPER_ADMIN' && existing.schoolId !== session.user?.schoolId) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
if (existing.approvalStatus === 'approved' && session.user?.role === 'TEACHER') {
|
||||
return NextResponse.json({ error: 'Approved leave cannot be deleted by the teacher' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Delete associated assignments first
|
||||
await db.substitutionAssignment.deleteMany({ where: { absenceId: id } });
|
||||
|
||||
Reference in new issue
Block a user