feat(homework,classes,course-plans): add scans, student data, take confirm, error boundaries, dialogs, hooks, calendar
homework: - Add data-access-scans, data-access-student, data-access-utils, data-access-exam-cross - Add excellent-submissions, homework-take-confirm-dialog, homework-take-sidebar components classes: - Add class-delete-dialog, class-error-boundary, class-form-dialog, class-form-utils - Add class-list-table, class-list-toolbar, class-skeleton - Add schedule-create-dialog, schedule-delete-dialog, schedule-edit-dialog, schedule-utils - Add data-access-teacher and hooks directory course-plans: - Add course-plan-calendar, sortable-week-row, template-picker-dialog components - Add lib directory
This commit is contained in:
@@ -294,3 +294,62 @@ export const getClassStudents = cache(
|
||||
}))
|
||||
}
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DataScope resolver helpers (P1-5/P1-6 audit fix)
|
||||
// These lightweight functions return only the IDs needed by the RBAC
|
||||
// data-scope resolver, so shared/lib/auth-guard no longer queries classes/
|
||||
// classEnrollments/classSubjectTeachers tables directly.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get a student's class IDs and grade IDs for DataScope resolution.
|
||||
* Joins classEnrollments with classes to resolve gradeId per enrollment.
|
||||
*/
|
||||
export async function getStudentScopeData(
|
||||
studentId: string,
|
||||
): Promise<{ classIds: string[]; gradeIds: string[] }> {
|
||||
const rows = await db
|
||||
.select({ classId: classEnrollments.classId, gradeId: classes.gradeId })
|
||||
.from(classEnrollments)
|
||||
.innerJoin(classes, eq(classEnrollments.classId, classes.id))
|
||||
.where(eq(classEnrollments.studentId, studentId))
|
||||
|
||||
const classIds = rows.map((r) => r.classId)
|
||||
const gradeIdSet = new Set<string>()
|
||||
for (const row of rows) {
|
||||
if (row.gradeId !== null && row.gradeId.trim().length > 0) {
|
||||
gradeIdSet.add(row.gradeId)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
classIds,
|
||||
gradeIds: Array.from(gradeIdSet),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get grade IDs for a list of student IDs (used by parent DataScope).
|
||||
* Queries classEnrollments JOIN classes for all students in a single query.
|
||||
*/
|
||||
export async function getGradeIdsForStudentIds(
|
||||
studentIds: string[],
|
||||
): Promise<string[]> {
|
||||
if (studentIds.length === 0) return []
|
||||
|
||||
const rows = await db
|
||||
.select({ gradeId: classes.gradeId })
|
||||
.from(classEnrollments)
|
||||
.innerJoin(classes, eq(classEnrollments.classId, classes.id))
|
||||
.where(inArray(classEnrollments.studentId, studentIds))
|
||||
|
||||
const gradeIdSet = new Set<string>()
|
||||
for (const row of rows) {
|
||||
if (row.gradeId !== null && row.gradeId.trim().length > 0) {
|
||||
gradeIdSet.add(row.gradeId)
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(gradeIdSet)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user