@studious-lms/server 1.17.1 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/models/agenda.d.ts +2 -0
- package/dist/models/agenda.d.ts.map +1 -1
- package/dist/models/announcement.d.ts +1 -0
- package/dist/models/announcement.d.ts.map +1 -1
- package/dist/models/assignment.d.ts +7 -0
- package/dist/models/assignment.d.ts.map +1 -1
- package/dist/models/auth.d.ts +2 -0
- package/dist/models/auth.d.ts.map +1 -1
- package/dist/models/class.d.ts +6 -0
- package/dist/models/class.d.ts.map +1 -1
- package/dist/models/class.js +3 -2
- package/dist/models/class.js.map +1 -1
- package/dist/models/event.d.ts +4 -0
- package/dist/models/event.d.ts.map +1 -1
- package/dist/models/file.d.ts +8 -0
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/folder.d.ts +2 -0
- package/dist/models/folder.d.ts.map +1 -1
- package/dist/models/labChat.d.ts +2 -0
- package/dist/models/labChat.d.ts.map +1 -1
- package/dist/models/newtonChat.d.ts +1 -0
- package/dist/models/newtonChat.d.ts.map +1 -1
- package/dist/models/school.d.ts +1 -0
- package/dist/models/school.d.ts.map +1 -1
- package/dist/models/section.d.ts +1 -0
- package/dist/models/section.d.ts.map +1 -1
- package/dist/models/worksheet.d.ts +4 -0
- package/dist/models/worksheet.d.ts.map +1 -1
- package/dist/models/worksheet.js +3 -3
- package/dist/models/worksheet.js.map +1 -1
- package/dist/routers/_app.d.ts +50 -0
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/agenda.d.ts +2 -0
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/assignment.d.ts +6 -0
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/class.d.ts +11 -0
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +4 -2
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/event.d.ts +1 -0
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/school.d.ts +3 -0
- package/dist/routers/school.d.ts.map +1 -1
- package/dist/routers/school.js +3 -2
- package/dist/routers/school.js.map +1 -1
- package/dist/routers/worksheet.d.ts +2 -0
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/services/agenda.d.ts +2 -0
- package/dist/services/agenda.d.ts.map +1 -1
- package/dist/services/assignment.d.ts +6 -0
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/class.d.ts +11 -0
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +7 -3
- package/dist/services/class.js.map +1 -1
- package/dist/services/event.d.ts +1 -0
- package/dist/services/event.d.ts.map +1 -1
- package/dist/services/school.d.ts +3 -0
- package/dist/services/school.d.ts.map +1 -1
- package/dist/services/school.js +3 -2
- package/dist/services/school.js.map +1 -1
- package/dist/services/worksheet.d.ts +2 -0
- package/dist/services/worksheet.d.ts.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260616071500_add_class_symbol/migration.sql +2 -0
- package/prisma/schema.prisma +1 -0
- package/src/models/class.ts +1 -0
- package/src/models/worksheet.ts +1 -1
- package/src/routers/class.ts +2 -0
- package/src/routers/school.ts +1 -0
- package/src/services/class.ts +7 -0
- package/src/services/school.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"school.js","sources":["services/school.ts"],"sourceRoot":"/","sourcesContent":["/**\n * School service - school admin workflow, memberships, and invites.\n */\nimport { SchoolMembershipRole, SessionType } from \"@prisma/client\";\nimport { TRPCError } from \"@trpc/server\";\nimport { hash } from \"bcryptjs\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { env } from \"../lib/config/env.js\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { sendMail } from \"../utils/email.js\";\nimport { generateUniqueUsername } from \"../utils/generateUsername.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n createSession,\n createUser,\n findUserByEmail,\n findUserById,\n findUserByUsername,\n} from \"../models/auth.js\";\nimport { upsertUserProfile } from \"../models/user.js\";\nimport {\n acceptSchoolInvite,\n countActiveAdmins,\n createSchoolInvite,\n createSchoolWithAdmin,\n findActiveSchoolAdminMembership,\n findPendingInviteByToken,\n findSchoolMembership,\n getSchoolById,\n getSchoolOverview,\n listSchoolClasses,\n listSchoolInvites,\n listSchoolMembers,\n listUserSchoolMemberships,\n removeSchoolMembershipPreservingContent,\n revokeSchoolInvite,\n updateSchoolMembershipRole,\n updateSchoolRecord,\n upsertSchoolMembership,\n} from \"../models/school.js\";\n\nasync function requireSchoolAdmin(schoolId: string, userId: string) {\n const membership = await findActiveSchoolAdminMembership(schoolId, userId);\n if (!membership) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can perform this action\",\n });\n }\n return membership;\n}\n\nasync function requireSchoolMember(schoolId: string, userId: string) {\n const membership = await findSchoolMembership(schoolId, userId);\n if (!membership || membership.status !== \"ACTIVE\") {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You are not a member of this school\",\n });\n }\n return membership;\n}\n\nexport async function getCurrentSchool(userId: string, schoolId?: string) {\n const memberships = await listUserSchoolMemberships(userId);\n const activeMembership = schoolId\n ? memberships.find((membership) => membership.schoolId === schoolId)\n : memberships[0];\n\n const activeSchool = activeMembership?.school\n ? {\n id: activeMembership.school.id,\n name: activeMembership.school.name,\n description: activeMembership.school.description ?? null,\n subdomain: activeMembership.school.subdomain ?? null,\n logoId: activeMembership.school.logoId ?? null,\n // The path is the GCS object key — the frontend resolves it to a\n // signed URL through trpc.file.getSignedUrl when needed.\n logoPath: activeMembership.school.logo?.path ?? null,\n logoType: activeMembership.school.logo?.type ?? null,\n }\n : null;\n\n return {\n activeSchool,\n activeRole: activeMembership?.role ?? null,\n memberships,\n };\n}\n\nexport async function createSchoolRecord(\n userId: string,\n input: {\n name: string;\n description?: string;\n subdomain?: string;\n logoId?: string;\n }\n) {\n const school = await createSchoolWithAdmin({\n userId,\n name: input.name,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n\n if (input.description) {\n await updateSchoolRecord(school.id, { description: input.description });\n }\n\n return { school };\n}\n\nexport async function updateSchoolDetails(\n userId: string,\n input: {\n schoolId: string;\n name?: string;\n description?: string | null;\n subdomain?: string | null;\n logoId?: string | null;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const updated = await updateSchoolRecord(input.schoolId, {\n name: input.name,\n description: input.description,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n return { school: updated };\n}\n\nexport async function getAdminOverview(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n const school = await getSchoolOverview(schoolId);\n if (!school) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"School not found\" });\n }\n\n const roleCounts = school.memberships.reduce(\n (counts, membership) => {\n counts[membership.role] += 1;\n return counts;\n },\n { ADMIN: 0, TEACHER: 0, STUDENT: 0 } satisfies Record<SchoolMembershipRole, number>\n );\n\n return {\n school: {\n id: school.id,\n name: school.name,\n subdomain: school.subdomain,\n counts: {\n classes: school._count.classes,\n members: school._count.memberships,\n pendingInvites: school._count.invites,\n ...roleCounts,\n },\n recentClasses: school.classes,\n recentInvites: school.invites,\n },\n };\n}\n\nexport async function listClasses(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { classes: await listSchoolClasses(schoolId) };\n}\n\nexport async function createSchoolClass(\n userId: string,\n input: {\n schoolId: string;\n name: string;\n section: string;\n subject: string;\n color?: string;\n departmentId?: string;\n teachers?: string[];\n students?: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n if (input.departmentId) {\n const dept = await prisma.department.findUnique({\n where: { id: input.departmentId },\n select: { schoolId: true },\n });\n if (!dept || dept.schoolId !== input.schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Department does not belong to this institution\",\n });\n }\n }\n\n const createdClass = await prisma.class.create({\n data: {\n name: input.name,\n section: input.section,\n subject: input.subject,\n color: input.color,\n schoolId: input.schoolId,\n departmentId: input.departmentId,\n teachers: input.teachers?.length\n ? { connect: input.teachers.map((id) => ({ id })) }\n : undefined,\n students: input.students?.length\n ? { connect: input.students.map((id) => ({ id })) }\n : undefined,\n },\n include: { teachers: true, students: true },\n });\n\n return { class: createdClass };\n}\n\nexport async function listMembers(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { members: await listSchoolMembers(schoolId) };\n}\n\nexport async function addMember(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const membership = await upsertSchoolMembership({\n schoolId: input.schoolId,\n userId: input.memberUserId,\n role: input.role,\n });\n return { membership };\n}\n\nexport async function updateMemberRole(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && input.role !== \"ADMIN\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n const membership = await updateSchoolMembershipRole(\n input.schoolId,\n input.memberUserId,\n input.role\n );\n return { membership };\n}\n\nexport async function removeMember(\n userId: string,\n input: { schoolId: string; memberUserId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && current.status === \"ACTIVE\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n await removeSchoolMembershipPreservingContent(input.schoolId, input.memberUserId);\n return { success: true };\n}\n\nexport async function listInvites(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { invites: await listSchoolInvites(schoolId) };\n}\n\n/**\n * Issue a direct-upload URL for a school-level asset (e.g. logo). The file\n * is created unattached and is owned by the requester until they associate\n * it via school.create or school.update.\n */\nexport async function getSchoolAssetUploadUrl(\n userId: string,\n input: { fileName: string; fileType: string; fileSize: number }\n) {\n const { createDirectUploadFiles } = await import(\"../lib/fileUpload.js\");\n const [uploadFile] = await createDirectUploadFiles(\n [\n {\n name: input.fileName,\n type: input.fileType,\n size: input.fileSize,\n },\n ],\n userId\n );\n return uploadFile;\n}\n\nexport async function confirmSchoolAssetUpload(\n userId: string,\n fileId: string,\n uploadSuccess: boolean\n) {\n const { confirmDirectUpload } = await import(\"../lib/fileUpload.js\");\n await confirmDirectUpload(fileId, uploadSuccess);\n return { success: true };\n}\n\n/**\n * Lightweight ID-only listing used to mask external user names in the UI.\n * Any active institution member can fetch this.\n */\nexport async function listMemberIds(userId: string, schoolId: string) {\n await requireSchoolMember(schoolId, userId);\n const rows = await prisma.schoolMembership.findMany({\n where: { schoolId, status: \"ACTIVE\" },\n select: { userId: true },\n });\n return rows.map((r) => r.userId);\n}\n\n/** Search active institution members by username, displayName, or email. */\nexport async function searchMembers(\n userId: string,\n schoolId: string,\n query: string,\n limit = 10,\n role?: \"ADMIN\" | \"TEACHER\" | \"STUDENT\"\n) {\n await requireSchoolMember(schoolId, userId);\n const trimmed = query.trim();\n if (!trimmed) return [];\n return prisma.user.findMany({\n where: {\n id: { not: userId },\n schoolMemberships: {\n some: {\n schoolId,\n status: \"ACTIVE\",\n ...(role ? { role } : {}),\n },\n },\n OR: [\n { username: { contains: trimmed, mode: \"insensitive\" } },\n { email: { contains: trimmed, mode: \"insensitive\" } },\n {\n profile: {\n displayName: { contains: trimmed, mode: \"insensitive\" },\n },\n },\n ],\n },\n take: limit,\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n schoolMemberships: {\n where: { schoolId, status: \"ACTIVE\" },\n select: { role: true },\n },\n },\n orderBy: { username: \"asc\" },\n });\n}\n\n/**\n * Combined student timeline: calendar events + assignments + attendance.\n * Visible to school admins (any student) and to teachers who share at least\n * one class with the student.\n */\nexport async function getStudentTimeline(\n userId: string,\n input: {\n schoolId: string;\n studentId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const isAdmin = await findActiveSchoolAdminMembership(\n input.schoolId,\n userId\n );\n\n // Permission: admin OR shares a class.\n if (!isAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.studentId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n // Make sure student is in the institution.\n const studentMembership = await prisma.schoolMembership.findFirst({\n where: { schoolId: input.schoolId, userId: input.studentId, status: \"ACTIVE\" },\n select: { role: true, user: { select: { id: true, username: true, profile: { select: { displayName: true, profilePicture: true } } } } },\n });\n if (!studentMembership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student is not in this institution\",\n });\n }\n\n const range = {\n ...(input.from ? { gte: input.from } : {}),\n ...(input.to ? { lte: input.to } : {}),\n };\n const hasRange = Object.keys(range).length > 0;\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.studentId,\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: {\n students: { some: { id: input.studentId } },\n },\n template: false,\n ...(hasRange ? { dueDate: range } : {}),\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.studentId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendance.findMany({\n where: {\n OR: [\n { present: { some: { id: input.studentId } } },\n { late: { some: { id: input.studentId } } },\n { absent: { some: { id: input.studentId } } },\n ],\n ...(hasRange ? { date: range } : {}),\n },\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n present: { where: { id: input.studentId }, select: { id: true } },\n late: { where: { id: input.studentId }, select: { id: true } },\n absent: { where: { id: input.studentId }, select: { id: true } },\n },\n orderBy: { date: \"asc\" },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.id,\n date: record.date,\n class: record.class,\n status: record.present.length\n ? (\"PRESENT\" as const)\n : record.late.length\n ? (\"LATE\" as const)\n : (\"ABSENT\" as const),\n }));\n\n return {\n student: studentMembership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n}\n\n/**\n * Role-aware overview used by `/view/[userId]`.\n *\n * - For STUDENT members it returns the same timeline as `getStudentTimeline`\n * (events, assignments, attendance) so teachers/admins can audit progress.\n * - For TEACHER/ADMIN members it returns their teaching agenda: every event in\n * a class they teach plus their personal events, alongside the classes they\n * run with enrolment counts.\n *\n * Permissions:\n * - School admins can view anyone in the institution.\n * - A teacher can view a STUDENT they share a class with.\n * - A teacher/admin can always view their own overview.\n */\nexport async function getMemberTimeline(\n userId: string,\n input: {\n schoolId: string;\n memberId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const callerIsAdmin = Boolean(\n await findActiveSchoolAdminMembership(input.schoolId, userId)\n );\n\n const membership = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: input.schoolId,\n userId: input.memberId,\n status: \"ACTIVE\",\n },\n select: {\n role: true,\n user: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true, profilePicture: true } },\n },\n },\n },\n });\n if (!membership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"This person is not in this institution\",\n });\n }\n\n const range = {\n ...(input.from ? { gte: input.from } : {}),\n ...(input.to ? { lte: input.to } : {}),\n };\n const hasRange = Object.keys(range).length > 0;\n\n if (membership.role === \"STUDENT\") {\n if (!callerIsAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.memberId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.memberId,\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: { students: { some: { id: input.memberId } } },\n template: false,\n ...(hasRange ? { dueDate: range } : {}),\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.memberId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendance.findMany({\n where: {\n OR: [\n { present: { some: { id: input.memberId } } },\n { late: { some: { id: input.memberId } } },\n { absent: { some: { id: input.memberId } } },\n ],\n ...(hasRange ? { date: range } : {}),\n },\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n present: { where: { id: input.memberId }, select: { id: true } },\n late: { where: { id: input.memberId }, select: { id: true } },\n absent: { where: { id: input.memberId }, select: { id: true } },\n },\n orderBy: { date: \"asc\" },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.id,\n date: record.date,\n class: record.class,\n status: record.present.length\n ? (\"PRESENT\" as const)\n : record.late.length\n ? (\"LATE\" as const)\n : (\"ABSENT\" as const),\n }));\n\n return {\n role: \"STUDENT\" as const,\n member: membership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n }\n\n // TEACHER or ADMIN: only admins (or the member themselves) may view.\n if (!callerIsAdmin && userId !== input.memberId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can view this member\",\n });\n }\n\n const [events, classes] = await Promise.all([\n prisma.event.findMany({\n where: {\n OR: [\n { userId: input.memberId },\n { class: { teachers: { some: { id: input.memberId } } } },\n ],\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.class.findMany({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: input.memberId } },\n },\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n _count: { select: { students: true } },\n },\n orderBy: { name: \"asc\" },\n }),\n ]);\n\n return {\n role: membership.role as \"TEACHER\" | \"ADMIN\",\n member: membership.user,\n events,\n classes: classes.map((c) => ({\n id: c.id,\n name: c.name,\n section: c.section,\n subject: c.subject,\n color: c.color,\n studentCount: c._count.students,\n })),\n };\n}\n\nexport async function createInvite(\n userId: string,\n input: {\n schoolId: string;\n email: string;\n role: SchoolMembershipRole;\n /** Optional display name set by the inviting admin. If omitted the user\n * picks their own when they complete the password reset flow. */\n displayName?: string;\n /** Optional username; if omitted we generate a friendly random one. */\n username?: string;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n // The institution invite flow is \"new account only\": if the email is\n // already in use we reject. This keeps the join experience simple — every\n // new institution member always lands on a password reset link.\n const existingUser = await findUserByEmail(input.email);\n if (existingUser) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message:\n \"An account with this email already exists. Ask them to log in and you can add them via search.\",\n });\n }\n\n let username: string;\n if (input.username) {\n const taken = await findUserByUsername(input.username);\n if (taken) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message: \"Username already taken\",\n });\n }\n username = input.username;\n } else {\n username = await generateUniqueUsername(async (candidate) => {\n const existing = await findUserByUsername(candidate);\n return Boolean(existing);\n });\n }\n\n const placeholderPassword = await hash(uuidv4(), 10);\n const user = await createUser({\n username,\n email: input.email,\n password: placeholderPassword,\n verified: true,\n });\n const createdUser = { id: user.id, username: user.username };\n\n if (input.displayName) {\n await upsertUserProfile(user.id, { displayName: input.displayName });\n }\n\n const resetSession = await createSession({\n id: uuidv4(),\n type: SessionType.PASSWORD_RESET,\n userId: user.id,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n const passwordResetToken = resetSession.id;\n\n const token = uuidv4();\n const invite = await createSchoolInvite({\n schoolId: input.schoolId,\n invitedById: userId,\n email: input.email,\n role: input.role,\n token,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n\n await acceptSchoolInvite(invite.id, createdUser.id);\n\n const passwordResetUrl = `${env.NEXT_PUBLIC_APP_URL}/reset-password/${passwordResetToken}`;\n const emailLines = [\n `You've been added to ${invite.school.name} on Studious.`,\n \"\",\n `We created an account for you with the username \"${createdUser.username}\".`,\n input.displayName\n ? `Your name is set to \"${input.displayName}\" — you can change it after signing in.`\n : `You can set your name once you sign in for the first time.`,\n \"\",\n `Set your password to get started: ${passwordResetUrl}`,\n ];\n\n try {\n await sendMail({\n from: \"hello@studious.sh\",\n to: input.email,\n subject: `Join ${invite.school.name} on Studious`,\n text: emailLines.join(\"\\n\"),\n });\n } catch (err) {\n logger.error(\"Failed to send school invite email\", {\n schoolId: input.schoolId,\n email: input.email,\n err,\n });\n }\n\n return {\n invite,\n createdUser,\n passwordResetUrl,\n };\n}\n\nexport async function revokeInvite(\n userId: string,\n input: { schoolId: string; inviteId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n return { invite: await revokeSchoolInvite(input.inviteId, input.schoolId) };\n}\n\nexport async function getInvite(token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n return {\n invite: {\n id: invite.id,\n email: invite.email,\n role: invite.role,\n school: invite.school,\n expiresAt: invite.expiresAt,\n },\n };\n}\n\nexport async function acceptInvite(userId: string, token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n\n const user = await findUserById(userId);\n if (!user) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"User not found\" });\n }\n if (user.email.toLowerCase() !== invite.email.toLowerCase()) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"This invite was sent to a different account\",\n });\n }\n\n const membership = await acceptSchoolInvite(invite.id, userId);\n return { membership };\n}\n"],"names":[],"mappings":"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","debug_id":"db6efcf6-9a7f-5dfa-a71c-f6706018a154"}
|
|
1
|
+
{"version":3,"file":"school.js","sources":["services/school.ts"],"sourceRoot":"/","sourcesContent":["/**\n * School service - school admin workflow, memberships, and invites.\n */\nimport { SchoolMembershipRole, SessionType } from \"@prisma/client\";\nimport { TRPCError } from \"@trpc/server\";\nimport { hash } from \"bcryptjs\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { env } from \"../lib/config/env.js\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { sendMail } from \"../utils/email.js\";\nimport { generateUniqueUsername } from \"../utils/generateUsername.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n createSession,\n createUser,\n findUserByEmail,\n findUserById,\n findUserByUsername,\n} from \"../models/auth.js\";\nimport { upsertUserProfile } from \"../models/user.js\";\nimport {\n acceptSchoolInvite,\n countActiveAdmins,\n createSchoolInvite,\n createSchoolWithAdmin,\n findActiveSchoolAdminMembership,\n findPendingInviteByToken,\n findSchoolMembership,\n getSchoolById,\n getSchoolOverview,\n listSchoolClasses,\n listSchoolInvites,\n listSchoolMembers,\n listUserSchoolMemberships,\n removeSchoolMembershipPreservingContent,\n revokeSchoolInvite,\n updateSchoolMembershipRole,\n updateSchoolRecord,\n upsertSchoolMembership,\n} from \"../models/school.js\";\n\nasync function requireSchoolAdmin(schoolId: string, userId: string) {\n const membership = await findActiveSchoolAdminMembership(schoolId, userId);\n if (!membership) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can perform this action\",\n });\n }\n return membership;\n}\n\nasync function requireSchoolMember(schoolId: string, userId: string) {\n const membership = await findSchoolMembership(schoolId, userId);\n if (!membership || membership.status !== \"ACTIVE\") {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You are not a member of this school\",\n });\n }\n return membership;\n}\n\nexport async function getCurrentSchool(userId: string, schoolId?: string) {\n const memberships = await listUserSchoolMemberships(userId);\n const activeMembership = schoolId\n ? memberships.find((membership) => membership.schoolId === schoolId)\n : memberships[0];\n\n const activeSchool = activeMembership?.school\n ? {\n id: activeMembership.school.id,\n name: activeMembership.school.name,\n description: activeMembership.school.description ?? null,\n subdomain: activeMembership.school.subdomain ?? null,\n logoId: activeMembership.school.logoId ?? null,\n // The path is the GCS object key — the frontend resolves it to a\n // signed URL through trpc.file.getSignedUrl when needed.\n logoPath: activeMembership.school.logo?.path ?? null,\n logoType: activeMembership.school.logo?.type ?? null,\n }\n : null;\n\n return {\n activeSchool,\n activeRole: activeMembership?.role ?? null,\n memberships,\n };\n}\n\nexport async function createSchoolRecord(\n userId: string,\n input: {\n name: string;\n description?: string;\n subdomain?: string;\n logoId?: string;\n }\n) {\n const school = await createSchoolWithAdmin({\n userId,\n name: input.name,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n\n if (input.description) {\n await updateSchoolRecord(school.id, { description: input.description });\n }\n\n return { school };\n}\n\nexport async function updateSchoolDetails(\n userId: string,\n input: {\n schoolId: string;\n name?: string;\n description?: string | null;\n subdomain?: string | null;\n logoId?: string | null;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const updated = await updateSchoolRecord(input.schoolId, {\n name: input.name,\n description: input.description,\n subdomain: input.subdomain,\n logoId: input.logoId,\n });\n return { school: updated };\n}\n\nexport async function getAdminOverview(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n const school = await getSchoolOverview(schoolId);\n if (!school) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"School not found\" });\n }\n\n const roleCounts = school.memberships.reduce(\n (counts, membership) => {\n counts[membership.role] += 1;\n return counts;\n },\n { ADMIN: 0, TEACHER: 0, STUDENT: 0 } satisfies Record<SchoolMembershipRole, number>\n );\n\n return {\n school: {\n id: school.id,\n name: school.name,\n subdomain: school.subdomain,\n counts: {\n classes: school._count.classes,\n members: school._count.memberships,\n pendingInvites: school._count.invites,\n ...roleCounts,\n },\n recentClasses: school.classes,\n recentInvites: school.invites,\n },\n };\n}\n\nexport async function listClasses(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { classes: await listSchoolClasses(schoolId) };\n}\n\nexport async function createSchoolClass(\n userId: string,\n input: {\n schoolId: string;\n name: string;\n section: string;\n subject: string;\n color?: string;\n symbol?: string | null;\n departmentId?: string;\n teachers?: string[];\n students?: string[];\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n if (input.departmentId) {\n const dept = await prisma.department.findUnique({\n where: { id: input.departmentId },\n select: { schoolId: true },\n });\n if (!dept || dept.schoolId !== input.schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Department does not belong to this institution\",\n });\n }\n }\n\n const createdClass = await prisma.class.create({\n data: {\n name: input.name,\n section: input.section,\n subject: input.subject,\n color: input.color,\n symbol: input.symbol,\n schoolId: input.schoolId,\n departmentId: input.departmentId,\n teachers: input.teachers?.length\n ? { connect: input.teachers.map((id) => ({ id })) }\n : undefined,\n students: input.students?.length\n ? { connect: input.students.map((id) => ({ id })) }\n : undefined,\n },\n include: { teachers: true, students: true },\n });\n\n return { class: createdClass };\n}\n\nexport async function listMembers(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { members: await listSchoolMembers(schoolId) };\n}\n\nexport async function addMember(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const membership = await upsertSchoolMembership({\n schoolId: input.schoolId,\n userId: input.memberUserId,\n role: input.role,\n });\n return { membership };\n}\n\nexport async function updateMemberRole(\n userId: string,\n input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && input.role !== \"ADMIN\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n const membership = await updateSchoolMembershipRole(\n input.schoolId,\n input.memberUserId,\n input.role\n );\n return { membership };\n}\n\nexport async function removeMember(\n userId: string,\n input: { schoolId: string; memberUserId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n const current = await findSchoolMembership(input.schoolId, input.memberUserId);\n if (!current) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Member not found\" });\n }\n\n if (current.role === \"ADMIN\" && current.status === \"ACTIVE\") {\n const adminCount = await countActiveAdmins(input.schoolId);\n if (adminCount <= 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"A school must have at least one active admin\",\n });\n }\n }\n\n await removeSchoolMembershipPreservingContent(input.schoolId, input.memberUserId);\n return { success: true };\n}\n\nexport async function listInvites(userId: string, schoolId: string) {\n await requireSchoolAdmin(schoolId, userId);\n return { invites: await listSchoolInvites(schoolId) };\n}\n\n/**\n * Issue a direct-upload URL for a school-level asset (e.g. logo). The file\n * is created unattached and is owned by the requester until they associate\n * it via school.create or school.update.\n */\nexport async function getSchoolAssetUploadUrl(\n userId: string,\n input: { fileName: string; fileType: string; fileSize: number }\n) {\n const { createDirectUploadFiles } = await import(\"../lib/fileUpload.js\");\n const [uploadFile] = await createDirectUploadFiles(\n [\n {\n name: input.fileName,\n type: input.fileType,\n size: input.fileSize,\n },\n ],\n userId\n );\n return uploadFile;\n}\n\nexport async function confirmSchoolAssetUpload(\n userId: string,\n fileId: string,\n uploadSuccess: boolean\n) {\n const { confirmDirectUpload } = await import(\"../lib/fileUpload.js\");\n await confirmDirectUpload(fileId, uploadSuccess);\n return { success: true };\n}\n\n/**\n * Lightweight ID-only listing used to mask external user names in the UI.\n * Any active institution member can fetch this.\n */\nexport async function listMemberIds(userId: string, schoolId: string) {\n await requireSchoolMember(schoolId, userId);\n const rows = await prisma.schoolMembership.findMany({\n where: { schoolId, status: \"ACTIVE\" },\n select: { userId: true },\n });\n return rows.map((r) => r.userId);\n}\n\n/** Search active institution members by username, displayName, or email. */\nexport async function searchMembers(\n userId: string,\n schoolId: string,\n query: string,\n limit = 10,\n role?: \"ADMIN\" | \"TEACHER\" | \"STUDENT\"\n) {\n await requireSchoolMember(schoolId, userId);\n const trimmed = query.trim();\n if (!trimmed) return [];\n return prisma.user.findMany({\n where: {\n id: { not: userId },\n schoolMemberships: {\n some: {\n schoolId,\n status: \"ACTIVE\",\n ...(role ? { role } : {}),\n },\n },\n OR: [\n { username: { contains: trimmed, mode: \"insensitive\" } },\n { email: { contains: trimmed, mode: \"insensitive\" } },\n {\n profile: {\n displayName: { contains: trimmed, mode: \"insensitive\" },\n },\n },\n ],\n },\n take: limit,\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n schoolMemberships: {\n where: { schoolId, status: \"ACTIVE\" },\n select: { role: true },\n },\n },\n orderBy: { username: \"asc\" },\n });\n}\n\n/**\n * Combined student timeline: calendar events + assignments + attendance.\n * Visible to school admins (any student) and to teachers who share at least\n * one class with the student.\n */\nexport async function getStudentTimeline(\n userId: string,\n input: {\n schoolId: string;\n studentId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const isAdmin = await findActiveSchoolAdminMembership(\n input.schoolId,\n userId\n );\n\n // Permission: admin OR shares a class.\n if (!isAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.studentId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n // Make sure student is in the institution.\n const studentMembership = await prisma.schoolMembership.findFirst({\n where: { schoolId: input.schoolId, userId: input.studentId, status: \"ACTIVE\" },\n select: { role: true, user: { select: { id: true, username: true, profile: { select: { displayName: true, profilePicture: true } } } } },\n });\n if (!studentMembership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student is not in this institution\",\n });\n }\n\n const range = {\n ...(input.from ? { gte: input.from } : {}),\n ...(input.to ? { lte: input.to } : {}),\n };\n const hasRange = Object.keys(range).length > 0;\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.studentId,\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: {\n students: { some: { id: input.studentId } },\n },\n template: false,\n ...(hasRange ? { dueDate: range } : {}),\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.studentId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendance.findMany({\n where: {\n OR: [\n { present: { some: { id: input.studentId } } },\n { late: { some: { id: input.studentId } } },\n { absent: { some: { id: input.studentId } } },\n ],\n ...(hasRange ? { date: range } : {}),\n },\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n present: { where: { id: input.studentId }, select: { id: true } },\n late: { where: { id: input.studentId }, select: { id: true } },\n absent: { where: { id: input.studentId }, select: { id: true } },\n },\n orderBy: { date: \"asc\" },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.id,\n date: record.date,\n class: record.class,\n status: record.present.length\n ? (\"PRESENT\" as const)\n : record.late.length\n ? (\"LATE\" as const)\n : (\"ABSENT\" as const),\n }));\n\n return {\n student: studentMembership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n}\n\n/**\n * Role-aware overview used by `/view/[userId]`.\n *\n * - For STUDENT members it returns the same timeline as `getStudentTimeline`\n * (events, assignments, attendance) so teachers/admins can audit progress.\n * - For TEACHER/ADMIN members it returns their teaching agenda: every event in\n * a class they teach plus their personal events, alongside the classes they\n * run with enrolment counts.\n *\n * Permissions:\n * - School admins can view anyone in the institution.\n * - A teacher can view a STUDENT they share a class with.\n * - A teacher/admin can always view their own overview.\n */\nexport async function getMemberTimeline(\n userId: string,\n input: {\n schoolId: string;\n memberId: string;\n from?: Date;\n to?: Date;\n }\n) {\n const callerIsAdmin = Boolean(\n await findActiveSchoolAdminMembership(input.schoolId, userId)\n );\n\n const membership = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: input.schoolId,\n userId: input.memberId,\n status: \"ACTIVE\",\n },\n select: {\n role: true,\n user: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true, profilePicture: true } },\n },\n },\n },\n });\n if (!membership) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"This person is not in this institution\",\n });\n }\n\n const range = {\n ...(input.from ? { gte: input.from } : {}),\n ...(input.to ? { lte: input.to } : {}),\n };\n const hasRange = Object.keys(range).length > 0;\n\n if (membership.role === \"STUDENT\") {\n if (!callerIsAdmin) {\n const sharedClass = await prisma.class.findFirst({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: userId } },\n students: { some: { id: input.memberId } },\n },\n select: { id: true },\n });\n if (!sharedClass) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't share a class with this student\",\n });\n }\n }\n\n const [events, assignments, attendance] = await Promise.all([\n prisma.event.findMany({\n where: {\n userId: input.memberId,\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.assignment.findMany({\n where: {\n class: { students: { some: { id: input.memberId } } },\n template: false,\n ...(hasRange ? { dueDate: range } : {}),\n },\n select: {\n id: true,\n title: true,\n dueDate: true,\n type: true,\n graded: true,\n maxGrade: true,\n weight: true,\n class: {\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n },\n },\n submissions: {\n where: { studentId: input.memberId },\n select: {\n id: true,\n submitted: true,\n submittedAt: true,\n returned: true,\n gradeReceived: true,\n },\n },\n },\n orderBy: { dueDate: \"asc\" },\n }),\n prisma.attendance.findMany({\n where: {\n OR: [\n { present: { some: { id: input.memberId } } },\n { late: { some: { id: input.memberId } } },\n { absent: { some: { id: input.memberId } } },\n ],\n ...(hasRange ? { date: range } : {}),\n },\n select: {\n id: true,\n date: true,\n class: { select: { id: true, name: true, color: true } },\n present: { where: { id: input.memberId }, select: { id: true } },\n late: { where: { id: input.memberId }, select: { id: true } },\n absent: { where: { id: input.memberId }, select: { id: true } },\n },\n orderBy: { date: \"asc\" },\n }),\n ]);\n\n const attendanceShaped = attendance.map((record) => ({\n id: record.id,\n date: record.date,\n class: record.class,\n status: record.present.length\n ? (\"PRESENT\" as const)\n : record.late.length\n ? (\"LATE\" as const)\n : (\"ABSENT\" as const),\n }));\n\n return {\n role: \"STUDENT\" as const,\n member: membership.user,\n events,\n assignments,\n attendance: attendanceShaped,\n };\n }\n\n // TEACHER or ADMIN: only admins (or the member themselves) may view.\n if (!callerIsAdmin && userId !== input.memberId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can view this member\",\n });\n }\n\n const [events, classes] = await Promise.all([\n prisma.event.findMany({\n where: {\n OR: [\n { userId: input.memberId },\n { class: { teachers: { some: { id: input.memberId } } } },\n ],\n ...(hasRange ? { startTime: range } : {}),\n },\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n remarks: true,\n color: true,\n class: { select: { id: true, name: true, color: true } },\n },\n orderBy: { startTime: \"asc\" },\n }),\n prisma.class.findMany({\n where: {\n schoolId: input.schoolId,\n teachers: { some: { id: input.memberId } },\n },\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n color: true,\n _count: { select: { students: true } },\n },\n orderBy: { name: \"asc\" },\n }),\n ]);\n\n return {\n role: membership.role as \"TEACHER\" | \"ADMIN\",\n member: membership.user,\n events,\n classes: classes.map((c) => ({\n id: c.id,\n name: c.name,\n section: c.section,\n subject: c.subject,\n color: c.color,\n studentCount: c._count.students,\n })),\n };\n}\n\nexport async function createInvite(\n userId: string,\n input: {\n schoolId: string;\n email: string;\n role: SchoolMembershipRole;\n /** Optional display name set by the inviting admin. If omitted the user\n * picks their own when they complete the password reset flow. */\n displayName?: string;\n /** Optional username; if omitted we generate a friendly random one. */\n username?: string;\n }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n\n // The institution invite flow is \"new account only\": if the email is\n // already in use we reject. This keeps the join experience simple — every\n // new institution member always lands on a password reset link.\n const existingUser = await findUserByEmail(input.email);\n if (existingUser) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message:\n \"An account with this email already exists. Ask them to log in and you can add them via search.\",\n });\n }\n\n let username: string;\n if (input.username) {\n const taken = await findUserByUsername(input.username);\n if (taken) {\n throw new TRPCError({\n code: \"CONFLICT\",\n message: \"Username already taken\",\n });\n }\n username = input.username;\n } else {\n username = await generateUniqueUsername(async (candidate) => {\n const existing = await findUserByUsername(candidate);\n return Boolean(existing);\n });\n }\n\n const placeholderPassword = await hash(uuidv4(), 10);\n const user = await createUser({\n username,\n email: input.email,\n password: placeholderPassword,\n verified: true,\n });\n const createdUser = { id: user.id, username: user.username };\n\n if (input.displayName) {\n await upsertUserProfile(user.id, { displayName: input.displayName });\n }\n\n const resetSession = await createSession({\n id: uuidv4(),\n type: SessionType.PASSWORD_RESET,\n userId: user.id,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n const passwordResetToken = resetSession.id;\n\n const token = uuidv4();\n const invite = await createSchoolInvite({\n schoolId: input.schoolId,\n invitedById: userId,\n email: input.email,\n role: input.role,\n token,\n expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),\n });\n\n await acceptSchoolInvite(invite.id, createdUser.id);\n\n const passwordResetUrl = `${env.NEXT_PUBLIC_APP_URL}/reset-password/${passwordResetToken}`;\n const emailLines = [\n `You've been added to ${invite.school.name} on Studious.`,\n \"\",\n `We created an account for you with the username \"${createdUser.username}\".`,\n input.displayName\n ? `Your name is set to \"${input.displayName}\" — you can change it after signing in.`\n : `You can set your name once you sign in for the first time.`,\n \"\",\n `Set your password to get started: ${passwordResetUrl}`,\n ];\n\n try {\n await sendMail({\n from: \"hello@studious.sh\",\n to: input.email,\n subject: `Join ${invite.school.name} on Studious`,\n text: emailLines.join(\"\\n\"),\n });\n } catch (err) {\n logger.error(\"Failed to send school invite email\", {\n schoolId: input.schoolId,\n email: input.email,\n err,\n });\n }\n\n return {\n invite,\n createdUser,\n passwordResetUrl,\n };\n}\n\nexport async function revokeInvite(\n userId: string,\n input: { schoolId: string; inviteId: string }\n) {\n await requireSchoolAdmin(input.schoolId, userId);\n return { invite: await revokeSchoolInvite(input.inviteId, input.schoolId) };\n}\n\nexport async function getInvite(token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n return {\n invite: {\n id: invite.id,\n email: invite.email,\n role: invite.role,\n school: invite.school,\n expiresAt: invite.expiresAt,\n },\n };\n}\n\nexport async function acceptInvite(userId: string, token: string) {\n const invite = await findPendingInviteByToken(token);\n if (!invite || invite.status !== \"PENDING\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Invite not found\" });\n }\n if (invite.expiresAt < new Date()) {\n throw new TRPCError({ code: \"UNAUTHORIZED\", message: \"Invite expired\" });\n }\n\n const user = await findUserById(userId);\n if (!user) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"User not found\" });\n }\n if (user.email.toLowerCase() !== invite.email.toLowerCase()) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"This invite was sent to a different account\",\n });\n }\n\n const membership = await acceptSchoolInvite(invite.id, userId);\n return { membership };\n}\n"],"names":[],"mappings":"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","debug_id":"e6792872-7695-5c7d-85ab-253749211d95"}
|
|
@@ -2,6 +2,7 @@ import { Prisma, type WorksheetQuestionType } from "@prisma/client";
|
|
|
2
2
|
/** Get worksheet with questions and mark schemes. */
|
|
3
3
|
export declare function getWorksheet(worksheetId: string, userId: string): Promise<{
|
|
4
4
|
class: {
|
|
5
|
+
symbol: string | null;
|
|
5
6
|
section: string;
|
|
6
7
|
id: string;
|
|
7
8
|
name: string;
|
|
@@ -55,6 +56,7 @@ export declare function listWorksheets(classId: string): Promise<{
|
|
|
55
56
|
}[];
|
|
56
57
|
questions: {
|
|
57
58
|
id: string;
|
|
59
|
+
question: string;
|
|
58
60
|
}[];
|
|
59
61
|
status: import(".prisma/client").$Enums.JobStatus | null;
|
|
60
62
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["services/worksheet.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,MAAM,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AA8D/E,qDAAqD;AACrD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["services/worksheet.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
package/src/models/class.ts
CHANGED
|
@@ -619,6 +619,7 @@ export async function createClassByImport(classId: string, userId: string, year:
|
|
|
619
619
|
name: classData.name,
|
|
620
620
|
subject: classData.subject,
|
|
621
621
|
color: classData.color,
|
|
622
|
+
symbol: classData.symbol,
|
|
622
623
|
section: classData.section,
|
|
623
624
|
syllabus: classData.syllabus,
|
|
624
625
|
teachers: { connect: { id: userId } },
|
package/src/models/worksheet.ts
CHANGED
|
@@ -70,7 +70,7 @@ export function findWorksheetsByClassId(classId: string) {
|
|
|
70
70
|
return prisma.worksheet.findMany({
|
|
71
71
|
where: { classId },
|
|
72
72
|
include: {
|
|
73
|
-
questions: { select: { id: true } },
|
|
73
|
+
questions: { select: { id: true, question: true }, orderBy: { order: "asc" } },
|
|
74
74
|
tags: true,
|
|
75
75
|
},
|
|
76
76
|
orderBy: { createdAt: "desc" },
|
package/src/routers/class.ts
CHANGED
|
@@ -59,6 +59,7 @@ export const classRouter = createTRPCRouter({
|
|
|
59
59
|
section: z.string().optional(),
|
|
60
60
|
subject: z.string().optional(),
|
|
61
61
|
color: z.string().optional(),
|
|
62
|
+
symbol: z.string().nullable().optional(),
|
|
62
63
|
departmentId: z.string().nullable().optional(),
|
|
63
64
|
discussionsEnabled: z.boolean().optional(),
|
|
64
65
|
studentsCanCreateDiscussions: z.boolean().optional(),
|
|
@@ -79,6 +80,7 @@ export const classRouter = createTRPCRouter({
|
|
|
79
80
|
section: z.string(),
|
|
80
81
|
subject: z.string(),
|
|
81
82
|
color: z.string().optional(),
|
|
83
|
+
symbol: z.string().nullable().optional(),
|
|
82
84
|
schoolId: z.string().optional(),
|
|
83
85
|
departmentId: z.string().optional(),
|
|
84
86
|
})
|
package/src/routers/school.ts
CHANGED
|
@@ -154,6 +154,7 @@ export const schoolRouter = createTRPCRouter({
|
|
|
154
154
|
section: z.string(),
|
|
155
155
|
subject: z.string(),
|
|
156
156
|
color: z.string().optional(),
|
|
157
|
+
symbol: z.string().nullable().optional(),
|
|
157
158
|
departmentId: z.string().optional(),
|
|
158
159
|
teachers: z.array(z.string()).optional(),
|
|
159
160
|
students: z.array(z.string()).optional(),
|
package/src/services/class.ts
CHANGED
|
@@ -75,6 +75,7 @@ export async function getAllClasses(userId: string) {
|
|
|
75
75
|
assignments: cls.assignments,
|
|
76
76
|
members: [...cls.students, ...cls.teachers],
|
|
77
77
|
color: cls.color,
|
|
78
|
+
symbol: cls.symbol,
|
|
78
79
|
schoolId: cls.schoolId ?? null,
|
|
79
80
|
school: cls.school ?? null,
|
|
80
81
|
department: cls.department ?? null,
|
|
@@ -100,6 +101,7 @@ export async function getAllClasses(userId: string) {
|
|
|
100
101
|
})),
|
|
101
102
|
members: [...cls.students, ...cls.teachers],
|
|
102
103
|
color: cls.color,
|
|
104
|
+
symbol: cls.symbol,
|
|
103
105
|
schoolId: cls.schoolId ?? null,
|
|
104
106
|
school: cls.school ?? null,
|
|
105
107
|
department: cls.department ?? null,
|
|
@@ -189,6 +191,7 @@ export async function updateClass(
|
|
|
189
191
|
section?: string;
|
|
190
192
|
subject?: string;
|
|
191
193
|
color?: string;
|
|
194
|
+
symbol?: string | null;
|
|
192
195
|
departmentId?: string | null;
|
|
193
196
|
discussionsEnabled?: boolean;
|
|
194
197
|
studentsCanCreateDiscussions?: boolean;
|
|
@@ -230,6 +233,7 @@ export async function updateClass(
|
|
|
230
233
|
section: true,
|
|
231
234
|
subject: true,
|
|
232
235
|
color: true,
|
|
236
|
+
symbol: true,
|
|
233
237
|
departmentId: true,
|
|
234
238
|
discussionsEnabled: true,
|
|
235
239
|
studentsCanCreateDiscussions: true,
|
|
@@ -248,6 +252,7 @@ export async function createClass(
|
|
|
248
252
|
section: string;
|
|
249
253
|
subject: string;
|
|
250
254
|
color?: string;
|
|
255
|
+
symbol?: string | null;
|
|
251
256
|
schoolId?: string;
|
|
252
257
|
departmentId?: string;
|
|
253
258
|
}
|
|
@@ -259,6 +264,7 @@ export async function createClass(
|
|
|
259
264
|
section,
|
|
260
265
|
subject,
|
|
261
266
|
color,
|
|
267
|
+
symbol,
|
|
262
268
|
schoolId,
|
|
263
269
|
departmentId,
|
|
264
270
|
} = input;
|
|
@@ -316,6 +322,7 @@ export async function createClass(
|
|
|
316
322
|
section,
|
|
317
323
|
subject,
|
|
318
324
|
color,
|
|
325
|
+
symbol,
|
|
319
326
|
schoolId,
|
|
320
327
|
departmentId,
|
|
321
328
|
teachers: { connect: teacherIds.map((id) => ({ id })) },
|
package/src/services/school.ts
CHANGED
|
@@ -176,6 +176,7 @@ export async function createSchoolClass(
|
|
|
176
176
|
section: string;
|
|
177
177
|
subject: string;
|
|
178
178
|
color?: string;
|
|
179
|
+
symbol?: string | null;
|
|
179
180
|
departmentId?: string;
|
|
180
181
|
teachers?: string[];
|
|
181
182
|
students?: string[];
|
|
@@ -202,6 +203,7 @@ export async function createSchoolClass(
|
|
|
202
203
|
section: input.section,
|
|
203
204
|
subject: input.subject,
|
|
204
205
|
color: input.color,
|
|
206
|
+
symbol: input.symbol,
|
|
205
207
|
schoolId: input.schoolId,
|
|
206
208
|
departmentId: input.departmentId,
|
|
207
209
|
teachers: input.teachers?.length
|