@studious-lms/server 1.7.0 → 1.9.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.
Files changed (212) hide show
  1. package/dist/middleware/security.d.ts.map +1 -1
  2. package/dist/middleware/security.js +3 -3
  3. package/dist/middleware/security.js.map +1 -1
  4. package/dist/models/access.d.ts +21 -66
  5. package/dist/models/access.d.ts.map +1 -1
  6. package/dist/models/access.js +10 -26
  7. package/dist/models/access.js.map +1 -1
  8. package/dist/models/agenda.d.ts +4 -2
  9. package/dist/models/agenda.d.ts.map +1 -1
  10. package/dist/models/announcement.d.ts +4 -3
  11. package/dist/models/announcement.d.ts.map +1 -1
  12. package/dist/models/announcement.js +2 -3
  13. package/dist/models/announcement.js.map +1 -1
  14. package/dist/models/assignment.d.ts +40 -33
  15. package/dist/models/assignment.d.ts.map +1 -1
  16. package/dist/models/auth.d.ts +2 -4
  17. package/dist/models/auth.d.ts.map +1 -1
  18. package/dist/models/auth.js +2 -3
  19. package/dist/models/auth.js.map +1 -1
  20. package/dist/models/class.d.ts +34 -6
  21. package/dist/models/class.d.ts.map +1 -1
  22. package/dist/models/class.js +15 -2
  23. package/dist/models/class.js.map +1 -1
  24. package/dist/models/cloudStorage.d.ts +153 -0
  25. package/dist/models/cloudStorage.d.ts.map +1 -0
  26. package/dist/models/cloudStorage.js +295 -0
  27. package/dist/models/cloudStorage.js.map +1 -0
  28. package/dist/models/comment.d.ts +0 -24
  29. package/dist/models/comment.d.ts.map +1 -1
  30. package/dist/models/comment.js +2 -6
  31. package/dist/models/comment.js.map +1 -1
  32. package/dist/models/conversation.d.ts +22 -22
  33. package/dist/models/department.d.ts +154 -0
  34. package/dist/models/department.d.ts.map +1 -0
  35. package/dist/models/department.js +135 -0
  36. package/dist/models/department.js.map +1 -0
  37. package/dist/models/event.d.ts +10 -4
  38. package/dist/models/event.d.ts.map +1 -1
  39. package/dist/models/event.js +2 -5
  40. package/dist/models/event.js.map +1 -1
  41. package/dist/models/file.d.ts +52 -36
  42. package/dist/models/file.d.ts.map +1 -1
  43. package/dist/models/file.js +4 -42
  44. package/dist/models/file.js.map +1 -1
  45. package/dist/models/folder.d.ts +47 -0
  46. package/dist/models/folder.d.ts.map +1 -1
  47. package/dist/models/labChat.d.ts +11 -9
  48. package/dist/models/labChat.d.ts.map +1 -1
  49. package/dist/models/message.d.ts +46 -12
  50. package/dist/models/message.d.ts.map +1 -1
  51. package/dist/models/message.js +19 -10
  52. package/dist/models/message.js.map +1 -1
  53. package/dist/models/newtonChat.d.ts +2 -1
  54. package/dist/models/newtonChat.d.ts.map +1 -1
  55. package/dist/models/school.d.ts +45 -12
  56. package/dist/models/school.d.ts.map +1 -1
  57. package/dist/models/school.js +19 -2
  58. package/dist/models/school.js.map +1 -1
  59. package/dist/models/section.d.ts +2 -1
  60. package/dist/models/section.d.ts.map +1 -1
  61. package/dist/models/tag.d.ts +117 -0
  62. package/dist/models/tag.d.ts.map +1 -0
  63. package/dist/models/tag.js +113 -0
  64. package/dist/models/tag.js.map +1 -0
  65. package/dist/models/worksheet.d.ts +3 -0
  66. package/dist/models/worksheet.d.ts.map +1 -1
  67. package/dist/pipelines/aiLabChatContract.d.ts +8 -8
  68. package/dist/routers/_app.d.ts +6704 -5222
  69. package/dist/routers/_app.d.ts.map +1 -1
  70. package/dist/routers/_app.js +8 -2
  71. package/dist/routers/_app.js.map +1 -1
  72. package/dist/routers/agenda.d.ts +4 -2
  73. package/dist/routers/agenda.d.ts.map +1 -1
  74. package/dist/routers/announcement.d.ts.map +1 -1
  75. package/dist/routers/announcement.js +3 -5
  76. package/dist/routers/announcement.js.map +1 -1
  77. package/dist/routers/assignment.d.ts +49 -40
  78. package/dist/routers/assignment.d.ts.map +1 -1
  79. package/dist/routers/assignment.js +2 -3
  80. package/dist/routers/assignment.js.map +1 -1
  81. package/dist/routers/class.d.ts +92 -19
  82. package/dist/routers/class.d.ts.map +1 -1
  83. package/dist/routers/class.js +5 -2
  84. package/dist/routers/class.js.map +1 -1
  85. package/dist/routers/conversation.d.ts +5 -5
  86. package/dist/routers/department.d.ts +293 -0
  87. package/dist/routers/department.d.ts.map +1 -0
  88. package/dist/routers/department.js +93 -0
  89. package/dist/routers/department.js.map +1 -0
  90. package/dist/routers/event.d.ts +4 -3
  91. package/dist/routers/event.d.ts.map +1 -1
  92. package/dist/routers/file.d.ts +10 -8
  93. package/dist/routers/file.d.ts.map +1 -1
  94. package/dist/routers/file.js +26 -17
  95. package/dist/routers/file.js.map +1 -1
  96. package/dist/routers/folder.d.ts +163 -186
  97. package/dist/routers/folder.d.ts.map +1 -1
  98. package/dist/routers/folder.js +102 -88
  99. package/dist/routers/folder.js.map +1 -1
  100. package/dist/routers/labChat.d.ts +13 -4
  101. package/dist/routers/labChat.d.ts.map +1 -1
  102. package/dist/routers/message.d.ts +20 -2
  103. package/dist/routers/message.d.ts.map +1 -1
  104. package/dist/routers/newtonChat.d.ts +10 -1
  105. package/dist/routers/newtonChat.d.ts.map +1 -1
  106. package/dist/routers/permissions.d.ts +120 -0
  107. package/dist/routers/permissions.d.ts.map +1 -0
  108. package/dist/routers/permissions.js +50 -0
  109. package/dist/routers/permissions.js.map +1 -0
  110. package/dist/routers/school.d.ts +160 -17
  111. package/dist/routers/school.d.ts.map +1 -1
  112. package/dist/routers/school.js +46 -3
  113. package/dist/routers/school.js.map +1 -1
  114. package/dist/routers/tag.d.ts +119 -0
  115. package/dist/routers/tag.d.ts.map +1 -0
  116. package/dist/routers/tag.js +52 -0
  117. package/dist/routers/tag.js.map +1 -0
  118. package/dist/routers/worksheet.d.ts +1 -0
  119. package/dist/routers/worksheet.d.ts.map +1 -1
  120. package/dist/seedDatabase.d.ts +0 -1
  121. package/dist/seedDatabase.d.ts.map +1 -1
  122. package/dist/services/agenda.d.ts +4 -2
  123. package/dist/services/agenda.d.ts.map +1 -1
  124. package/dist/services/assignment.d.ts +49 -40
  125. package/dist/services/assignment.d.ts.map +1 -1
  126. package/dist/services/class.d.ts +92 -19
  127. package/dist/services/class.d.ts.map +1 -1
  128. package/dist/services/class.js +92 -5
  129. package/dist/services/class.js.map +1 -1
  130. package/dist/services/conversation.d.ts +5 -5
  131. package/dist/services/department.d.ts +200 -0
  132. package/dist/services/department.d.ts.map +1 -0
  133. package/dist/services/department.js +368 -0
  134. package/dist/services/department.js.map +1 -0
  135. package/dist/services/event.d.ts +4 -3
  136. package/dist/services/event.d.ts.map +1 -1
  137. package/dist/services/file.d.ts +105 -3
  138. package/dist/services/file.d.ts.map +1 -1
  139. package/dist/services/file.js +167 -41
  140. package/dist/services/file.js.map +1 -1
  141. package/dist/services/folder.d.ts +220 -149
  142. package/dist/services/folder.d.ts.map +1 -1
  143. package/dist/services/folder.js +326 -196
  144. package/dist/services/folder.js.map +1 -1
  145. package/dist/services/labChat.d.ts +13 -4
  146. package/dist/services/labChat.d.ts.map +1 -1
  147. package/dist/services/labChat.js +4 -3
  148. package/dist/services/labChat.js.map +1 -1
  149. package/dist/services/message.d.ts +20 -2
  150. package/dist/services/message.d.ts.map +1 -1
  151. package/dist/services/message.js +7 -23
  152. package/dist/services/message.js.map +1 -1
  153. package/dist/services/newtonChat.d.ts +9 -0
  154. package/dist/services/newtonChat.d.ts.map +1 -1
  155. package/dist/services/newtonChat.js +4 -3
  156. package/dist/services/newtonChat.js.map +1 -1
  157. package/dist/services/permissions.d.ts +188 -0
  158. package/dist/services/permissions.d.ts.map +1 -0
  159. package/dist/services/permissions.js +661 -0
  160. package/dist/services/permissions.js.map +1 -0
  161. package/dist/services/school.d.ts +142 -15
  162. package/dist/services/school.d.ts.map +1 -1
  163. package/dist/services/school.js +308 -54
  164. package/dist/services/school.js.map +1 -1
  165. package/dist/services/tag.d.ts +71 -0
  166. package/dist/services/tag.d.ts.map +1 -0
  167. package/dist/services/tag.js +178 -0
  168. package/dist/services/tag.js.map +1 -0
  169. package/dist/services/worksheet.d.ts +1 -0
  170. package/dist/services/worksheet.d.ts.map +1 -1
  171. package/dist/utils/aiUser.d.ts.map +1 -1
  172. package/dist/utils/aiUser.js +2 -3
  173. package/dist/utils/aiUser.js.map +1 -1
  174. package/package.json +1 -1
  175. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +184 -0
  176. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +93 -0
  177. package/prisma/schema.prisma +193 -35
  178. package/src/middleware/security.ts +1 -1
  179. package/src/models/access.ts +8 -24
  180. package/src/models/announcement.ts +0 -1
  181. package/src/models/auth.ts +0 -1
  182. package/src/models/class.ts +13 -0
  183. package/src/models/cloudStorage.ts +327 -0
  184. package/src/models/comment.ts +0 -4
  185. package/src/models/department.ts +159 -0
  186. package/src/models/event.ts +0 -3
  187. package/src/models/file.ts +2 -40
  188. package/src/models/message.ts +19 -5
  189. package/src/models/school.ts +26 -0
  190. package/src/models/tag.ts +140 -0
  191. package/src/routers/_app.ts +6 -0
  192. package/src/routers/announcement.ts +1 -3
  193. package/src/routers/assignment.ts +0 -1
  194. package/src/routers/class.ts +3 -0
  195. package/src/routers/department.ts +174 -0
  196. package/src/routers/file.ts +29 -26
  197. package/src/routers/folder.ts +127 -118
  198. package/src/routers/permissions.ts +71 -0
  199. package/src/routers/school.ts +83 -0
  200. package/src/routers/tag.ts +78 -0
  201. package/src/services/class.ts +109 -4
  202. package/src/services/department.ts +478 -0
  203. package/src/services/file.ts +172 -43
  204. package/src/services/folder.ts +399 -237
  205. package/src/services/labChat.ts +2 -1
  206. package/src/services/message.ts +5 -21
  207. package/src/services/newtonChat.ts +2 -1
  208. package/src/services/permissions.ts +778 -0
  209. package/src/services/school.ts +369 -57
  210. package/src/services/tag.ts +229 -0
  211. package/src/utils/aiUser.ts +0 -1
  212. package/tests/unit/services/permissions.test.ts +463 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sources":["services/permissions.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Permissions resolver — single source of truth for \"can user U do X to target T?\"\n *\n * Sits on top of the existing scope-derived defaults (class members, school\n * members, personal owner) computed in `getScopeDefault`. Explicit `Permission`\n * rows are *additive* — they only ever grant more access, never less. There is\n * no concept of a \"deny\" rule by design; revocation = delete the row.\n *\n * Resolution order for `requireFolderAccess(user, folder, level)`:\n * 1. Scope default (class member / school member / personal owner)\n * 2. Direct grant on the folder, OR inherited grant on any ancestor\n * (walk up to scope root)\n * First match wins; otherwise FORBIDDEN.\n *\n * `requireFileAccess` resolves the file's parent folder and delegates. Files\n * inherit from their folder in v1; per-file grants are deliberately deferred\n * (forward-compatible additive migration when needed).\n */\nimport { TRPCError } from \"@trpc/server\";\nimport type {\n PermissionLevel,\n PermissionPrincipalType,\n Prisma,\n} from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\nimport {\n type CloudScope,\n resolveFolderScope,\n} from \"../models/cloudStorage.js\";\n\nexport type AccessLevel = \"READ\" | \"WRITE\";\n\n/**\n * The set of \"audiences\" a user belongs to that an explicit grant can match.\n * Generated once per request via `expandUserPrincipals` and threaded through\n * the resolver.\n */\nexport interface UserPrincipals {\n userId: string;\n tagIds: string[];\n classTeacherIds: string[];\n classStudentIds: string[];\n /** Union of teacher + student class memberships (i.e. all CLASS principals). */\n classIds: string[];\n departmentIds: string[];\n /** Active school memberships only. */\n schoolIds: string[];\n}\n\n/**\n * Build the audience set for a user. Cheap (5 queries, all id-only) but worth\n * caching per request — most permission checks in a single tRPC call hit this.\n */\nexport async function expandUserPrincipals(\n userId: string\n): Promise<UserPrincipals> {\n const [user, asTeacher, asStudent, departments, schoolMemberships] =\n await Promise.all([\n prisma.user.findUnique({\n where: { id: userId },\n select: { tags: { select: { id: true } } },\n }),\n prisma.class.findMany({\n where: { teachers: { some: { id: userId } } },\n select: { id: true },\n }),\n prisma.class.findMany({\n where: { students: { some: { id: userId } } },\n select: { id: true },\n }),\n prisma.department.findMany({\n where: { members: { some: { id: userId } } },\n select: { id: true },\n }),\n prisma.schoolMembership.findMany({\n where: { userId, status: \"ACTIVE\" },\n select: { schoolId: true },\n }),\n ]);\n\n const classTeacherIds = asTeacher.map((c) => c.id);\n const classStudentIds = asStudent.map((c) => c.id);\n return {\n userId,\n tagIds: user?.tags.map((t) => t.id) ?? [],\n classTeacherIds,\n classStudentIds,\n classIds: Array.from(new Set([...classTeacherIds, ...classStudentIds])),\n departmentIds: departments.map((d) => d.id),\n schoolIds: schoolMemberships.map((m) => m.schoolId),\n };\n}\n\n/**\n * The principal-side `where` clause that matches any explicit grant whose\n * principal applies to this user. CLASS / CLASS_TEACHERS / CLASS_STUDENTS all\n * use `classId` but with different `principalType` values, so we have to fan\n * those out into three OR branches.\n */\nfunction principalsWhere(\n principals: UserPrincipals\n): Prisma.PermissionWhereInput {\n const ors: Prisma.PermissionWhereInput[] = [\n { principalType: \"USER\", userId: principals.userId },\n ];\n if (principals.tagIds.length) {\n ors.push({ principalType: \"TAG\", tagId: { in: principals.tagIds } });\n }\n if (principals.classIds.length) {\n ors.push({\n principalType: \"CLASS\",\n classId: { in: principals.classIds },\n });\n }\n if (principals.classTeacherIds.length) {\n ors.push({\n principalType: \"CLASS_TEACHERS\",\n classId: { in: principals.classTeacherIds },\n });\n }\n if (principals.classStudentIds.length) {\n ors.push({\n principalType: \"CLASS_STUDENTS\",\n classId: { in: principals.classStudentIds },\n });\n }\n if (principals.departmentIds.length) {\n ors.push({\n principalType: \"DEPARTMENT\",\n departmentId: { in: principals.departmentIds },\n });\n }\n if (principals.schoolIds.length) {\n ors.push({\n principalType: \"SCHOOL\",\n schoolId: { in: principals.schoolIds },\n });\n }\n return { OR: ors };\n}\n\nfunction levelSatisfies(\n granted: PermissionLevel,\n required: AccessLevel\n): boolean {\n if (required === \"READ\") return granted === \"READ\" || granted === \"WRITE\";\n return granted === \"WRITE\";\n}\n\n/** Walk up to the scope root, collecting folder ids visited along the way (inclusive). */\nasync function findAncestorIds(folderId: string): Promise<string[]> {\n const ids: string[] = [];\n let cursor: string | null = folderId;\n let visits = 0;\n while (cursor && visits < 64) {\n ids.push(cursor);\n const node: { parentFolderId: string | null } | null =\n await prisma.folder.findUnique({\n where: { id: cursor },\n select: { parentFolderId: true },\n });\n if (!node) break;\n cursor = node.parentFolderId;\n visits += 1;\n }\n return ids;\n}\n\nexport { findAncestorIds };\n\n/**\n * Compute the scope default for a user — i.e. the access level the existing\n * scope-derived rules grant, *before* any explicit ACL is consulted.\n *\n * Mirrors the logic that used to live in `requireScopeAccess` in folder.ts.\n * Returns \"WRITE\" / \"READ\" / null.\n */\nexport async function getScopeDefault(\n userId: string,\n scope: CloudScope\n): Promise<AccessLevel | null> {\n switch (scope.kind) {\n case \"CLASS\": {\n const classData = await prisma.class.findFirst({\n where: { id: scope.classId },\n select: {\n id: true,\n schoolId: true,\n teachers: { where: { id: userId }, select: { id: true } },\n students: { where: { id: userId }, select: { id: true } },\n },\n });\n if (!classData) return null;\n if (classData.teachers.length > 0) return \"WRITE\";\n const isSchoolAdmin = classData.schoolId\n ? Boolean(\n await prisma.schoolMembership.findFirst({\n where: {\n schoolId: classData.schoolId,\n userId,\n role: \"ADMIN\",\n status: \"ACTIVE\",\n },\n select: { id: true },\n })\n )\n : false;\n if (isSchoolAdmin) return \"WRITE\";\n if (classData.students.length > 0) return \"READ\";\n return null;\n }\n case \"SCHOOL_STORAGE\": {\n const membership = await prisma.schoolMembership.findFirst({\n where: { schoolId: scope.schoolId, userId, status: \"ACTIVE\" },\n select: { role: true },\n });\n if (!membership) return null;\n if (membership.role === \"ADMIN\" || membership.role === \"TEACHER\")\n return \"WRITE\";\n return \"READ\";\n }\n case \"PERSONAL\": {\n return scope.userId === userId ? \"WRITE\" : null;\n }\n }\n}\n\n/**\n * Does any of the given folder ids carry a grant matching this user at >=\n * `level`? Returns the matching folder id (highest-priority for caller use)\n * or null.\n */\nasync function findGrantOnFolders(\n folderIds: string[],\n principals: UserPrincipals,\n level: AccessLevel\n): Promise<string | null> {\n if (!folderIds.length) return null;\n const grant = await prisma.permission.findFirst({\n where: {\n folderId: { in: folderIds },\n ...principalsWhere(principals),\n ...(level === \"WRITE\" ? { level: \"WRITE\" } : {}),\n },\n select: { folderId: true },\n });\n return grant?.folderId ?? null;\n}\n\nexport interface AccessResult {\n scope: CloudScope | null;\n scopeDefault: AccessLevel | null;\n /** Truthy if the resolver returned because of an explicit grant (folder or file). */\n viaGrant: boolean;\n}\n\n/**\n * Permission gate for folder-scoped operations. Throws TRPCError on denial,\n * returns the scope (and which path granted access) on success.\n *\n * `opts.mutatesSelf` (Drive-style guard): when true, the action targets the\n * folder *itself* — rename, delete, move-this-folder. Explicit grants do NOT\n * authorize these; only scope-default WRITE does. This means a teacher sharing\n * \"Math Resources\" with the parents tag can let parents read/edit children of\n * the folder, but parents cannot rename or delete the share root. Mutations\n * targeting *children* of the folder (uploads, sub-folders, child renames)\n * pass `mutatesSelf: false` and flow through the normal grant + ancestor +\n * scope-default path.\n */\nexport async function requireFolderAccess(\n userId: string,\n folderId: string,\n level: AccessLevel,\n opts: { mutatesSelf?: boolean } = {}\n): Promise<AccessResult> {\n const scope = await resolveFolderScope(folderId);\n if (!scope) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Folder not found\" });\n }\n const scopeDefault = await getScopeDefault(userId, scope);\n if (scopeDefault && levelSatisfies(scopeDefault as PermissionLevel, level)) {\n return { scope, scopeDefault, viaGrant: false };\n }\n\n // Mutations of the share root itself are reserved for scope-default WRITE.\n // Explicit grants don't authorize delete/rename/move-self even at WRITE\n // level. We've already failed the scope-default branch above, so deny.\n if (opts.mutatesSelf && level === \"WRITE\") {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n \"Only the folder's owner can rename, move, or delete it. \" +\n \"You can edit its contents.\",\n });\n }\n\n const principals = await expandUserPrincipals(userId);\n const ancestors = await findAncestorIds(folderId);\n const grantFolderId = await findGrantOnFolders(ancestors, principals, level);\n if (grantFolderId) {\n return { scope, scopeDefault, viaGrant: true };\n }\n\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n level === \"WRITE\"\n ? \"You don't have write access here\"\n : \"You don't have access to this folder\",\n });\n}\n\n/**\n * Per-class role check used by file-context handlers (assignment, submission,\n * annotation, announcement, class-draft attachments). Single query.\n */\nasync function userClassRole(\n userId: string,\n classId: string\n): Promise<\"TEACHER\" | \"STUDENT\" | \"ADMIN\" | null> {\n const cls = await prisma.class.findFirst({\n where: { id: classId },\n select: {\n schoolId: true,\n teachers: { where: { id: userId }, select: { id: true } },\n students: { where: { id: userId }, select: { id: true } },\n },\n });\n if (!cls) return null;\n if (cls.teachers.length) return \"TEACHER\";\n if (cls.schoolId) {\n const admin = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: cls.schoolId,\n userId,\n role: \"ADMIN\",\n status: \"ACTIVE\",\n },\n select: { id: true },\n });\n if (admin) return \"ADMIN\";\n }\n if (cls.students.length) return \"STUDENT\";\n return null;\n}\n\nconst fileGrant = (level: AccessLevel): AccessResult => ({\n scope: null,\n scopeDefault: level,\n viaGrant: false,\n});\n\n/**\n * Permission gate for file-scoped operations. Dispatches on whichever context\n * relation the file carries, so every kind of file (cloud-storage, chat\n * attachment, assignment / submission / annotation / announcement / class-draft\n * attachment, school logo) gets authorized through one entry point.\n *\n * Resolution order — first match wins:\n * 1. **Owner** — `file.userId === user`. Always WRITE.\n * 2. **Folder-bound** — delegate to `requireFolderAccess` (handles scope\n * defaults + explicit grants + ancestor inheritance).\n * 3. **Conversation/message attachment** — any conversation member READs;\n * only the sender (= owner, handled in step 1) WRITEs.\n * 4. **Assignment attachment** — class teacher/admin RW, class student R.\n * 5. **Submission file** — submission's student RW (until grading workflow\n * locks it down), class teacher/admin R.\n * 6. **Annotation file** — class teacher/admin RW, submission's student R.\n * 7. **Announcement attachment** — class teacher/admin RW, class student R.\n * 8. **Class-draft attachment** — class teacher/admin RW (drafts have no\n * students yet in practice).\n * 9. **School logo** — any active school member R, school admin W.\n * 10. **Otherwise** (incl. SDP supporting docs) — owner-only fallback already\n * covered by step 1; deny.\n */\nexport async function requireFileAccess(\n userId: string,\n fileId: string,\n level: AccessLevel\n): Promise<AccessResult> {\n const file = await prisma.file.findUnique({\n where: { id: fileId },\n select: {\n id: true,\n userId: true,\n folderId: true,\n conversationId: true,\n assignmentId: true,\n classDraftId: true,\n announcementId: true,\n schoolDevelopementProgramId: true,\n assignment: { select: { classId: true } },\n submission: {\n select: { studentId: true, assignment: { select: { classId: true } } },\n },\n annotations: {\n select: { studentId: true, assignment: { select: { classId: true } } },\n },\n announcement: { select: { classId: true } },\n schools: { select: { id: true } },\n },\n });\n if (!file) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"File not found\" });\n }\n\n if (file.userId === userId) {\n return { scope: null, scopeDefault: \"WRITE\", viaGrant: false };\n }\n\n if (file.folderId) {\n return requireFolderAccess(userId, file.folderId, level);\n }\n\n if (file.conversationId) {\n const member = await prisma.conversationMember.findFirst({\n where: { conversationId: file.conversationId, userId },\n select: { id: true },\n });\n if (member) {\n // Non-owners can only read; only the sender (owner, already handled\n // above) can mutate the attachment record.\n if (level === \"READ\") return fileGrant(\"READ\");\n }\n }\n\n if (file.assignment?.classId) {\n const role = await userClassRole(userId, file.assignment.classId);\n if (role === \"TEACHER\" || role === \"ADMIN\") return fileGrant(\"WRITE\");\n if (role === \"STUDENT\" && level === \"READ\") return fileGrant(\"READ\");\n }\n\n if (file.submission?.assignment?.classId) {\n if (file.submission.studentId === userId) return fileGrant(\"WRITE\");\n const role = await userClassRole(userId, file.submission.assignment.classId);\n if ((role === \"TEACHER\" || role === \"ADMIN\") && level === \"READ\") {\n return fileGrant(\"READ\");\n }\n }\n\n if (file.annotations?.assignment?.classId) {\n const role = await userClassRole(\n userId,\n file.annotations.assignment.classId\n );\n if (role === \"TEACHER\" || role === \"ADMIN\") return fileGrant(\"WRITE\");\n if (file.annotations.studentId === userId && level === \"READ\") {\n return fileGrant(\"READ\");\n }\n }\n\n if (file.announcement?.classId) {\n const role = await userClassRole(userId, file.announcement.classId);\n if (role === \"TEACHER\" || role === \"ADMIN\") return fileGrant(\"WRITE\");\n if (role === \"STUDENT\" && level === \"READ\") return fileGrant(\"READ\");\n }\n\n if (file.classDraftId) {\n const role = await userClassRole(userId, file.classDraftId);\n if (role === \"TEACHER\" || role === \"ADMIN\") return fileGrant(\"WRITE\");\n }\n\n if (file.schools.length) {\n // Files referenced as `School.logo` — readable by any active member of\n // any school using this file, writable only by an admin of one of them.\n const schoolIds = file.schools.map((s) => s.id);\n if (level === \"WRITE\") {\n const adminMembership = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: { in: schoolIds },\n userId,\n role: \"ADMIN\",\n status: \"ACTIVE\",\n },\n select: { id: true },\n });\n if (adminMembership) return fileGrant(\"WRITE\");\n } else {\n const membership = await prisma.schoolMembership.findFirst({\n where: {\n schoolId: { in: schoolIds },\n userId,\n status: \"ACTIVE\",\n },\n select: { id: true },\n });\n if (membership) return fileGrant(\"READ\");\n }\n }\n\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n level === \"WRITE\"\n ? \"You don't have write access to this file\"\n : \"You don't have access to this file\",\n });\n}\n\n/**\n * Top-most-grant computation: surface every folder the user has an explicit\n * grant on whose nearest permissioned ancestor the user does *not* also hold a\n * grant on, AND whose scope default does not already grant access. That second\n * filter avoids \"Shared with me\" duplicating things you already see in your\n * normal class/school/personal scopes.\n *\n * Files are not surfaced here — file-level grants are deferred to a future\n * feature; in v1 files inherit from their folder.\n */\nexport async function listSharedWithMe(userId: string): Promise<{\n folders: { id: string; name: string; color: string | null }[];\n files: never[];\n}> {\n const principals = await expandUserPrincipals(userId);\n\n const grants = await prisma.permission.findMany({\n where: principalsWhere(principals),\n select: { id: true, folderId: true },\n });\n\n const grantedFolderIds = new Set<string>(\n grants.map((g) => g.folderId).filter((x): x is string => Boolean(x))\n );\n\n const topFolders: { id: string; name: string; color: string | null }[] = [];\n for (const folderId of grantedFolderIds) {\n const ancestors = await findAncestorIds(folderId);\n // Skip self; we want to know if any *strict* ancestor is also granted.\n const strictAncestors = ancestors.slice(1);\n const coveredByAncestor = strictAncestors.some((id) =>\n grantedFolderIds.has(id)\n );\n if (coveredByAncestor) continue;\n\n const scope = await resolveFolderScope(folderId);\n if (scope) {\n const scopeDefault = await getScopeDefault(userId, scope);\n if (scopeDefault) continue;\n }\n\n const folder = await prisma.folder.findUnique({\n where: { id: folderId },\n select: { id: true, name: true, color: true },\n });\n if (folder) topFolders.push(folder);\n }\n\n return { folders: topFolders, files: [] };\n}\n\n/* ------------------------------------------------------------------ *\n * Grant CRUD *\n * ------------------------------------------------------------------ */\n\nexport type PermissionPrincipalInput =\n | { kind: \"USER\"; userId: string }\n | { kind: \"TAG\"; tagId: string }\n | { kind: \"CLASS\"; classId: string }\n | { kind: \"CLASS_TEACHERS\"; classId: string }\n | { kind: \"CLASS_STUDENTS\"; classId: string }\n | { kind: \"DEPARTMENT\"; departmentId: string }\n | { kind: \"SCHOOL\"; schoolId: string };\n\n/** Resolve which school an explicit grant target belongs to (for cross-school checks). */\nasync function resolveTargetSchoolId(folderId: string): Promise<string | null> {\n const scope = await resolveFolderScope(folderId);\n return scopeSchoolId(scope);\n}\n\nasync function scopeSchoolId(scope: CloudScope | null): Promise<string | null> {\n if (!scope) return null;\n switch (scope.kind) {\n case \"CLASS\": {\n const c = await prisma.class.findUnique({\n where: { id: scope.classId },\n select: { schoolId: true },\n });\n return c?.schoolId ?? null;\n }\n case \"SCHOOL_STORAGE\":\n return scope.schoolId;\n case \"PERSONAL\":\n return null;\n }\n}\n\n/** The school a principal lives in (for cross-school leak prevention). */\nasync function principalSchoolId(\n principal: PermissionPrincipalInput\n): Promise<string | null> {\n switch (principal.kind) {\n case \"USER\": {\n const u = await prisma.user.findUnique({\n where: { id: principal.userId },\n select: { schoolId: true },\n });\n return u?.schoolId ?? null;\n }\n case \"TAG\": {\n const t = await prisma.tag.findUnique({\n where: { id: principal.tagId },\n select: { schoolId: true },\n });\n return t?.schoolId ?? null;\n }\n case \"CLASS\":\n case \"CLASS_TEACHERS\":\n case \"CLASS_STUDENTS\": {\n const c = await prisma.class.findUnique({\n where: { id: principal.classId },\n select: { schoolId: true },\n });\n return c?.schoolId ?? null;\n }\n case \"DEPARTMENT\": {\n const d = await prisma.department.findUnique({\n where: { id: principal.departmentId },\n select: { schoolId: true },\n });\n return d?.schoolId ?? null;\n }\n case \"SCHOOL\":\n return principal.schoolId;\n }\n}\n\nfunction principalToColumns(principal: PermissionPrincipalInput): {\n principalType: PermissionPrincipalType;\n userId: string | null;\n tagId: string | null;\n classId: string | null;\n departmentId: string | null;\n schoolId: string | null;\n} {\n const base = {\n userId: null as string | null,\n tagId: null as string | null,\n classId: null as string | null,\n departmentId: null as string | null,\n schoolId: null as string | null,\n };\n switch (principal.kind) {\n case \"USER\":\n return { ...base, principalType: \"USER\", userId: principal.userId };\n case \"TAG\":\n return { ...base, principalType: \"TAG\", tagId: principal.tagId };\n case \"CLASS\":\n return { ...base, principalType: \"CLASS\", classId: principal.classId };\n case \"CLASS_TEACHERS\":\n return {\n ...base,\n principalType: \"CLASS_TEACHERS\",\n classId: principal.classId,\n };\n case \"CLASS_STUDENTS\":\n return {\n ...base,\n principalType: \"CLASS_STUDENTS\",\n classId: principal.classId,\n };\n case \"DEPARTMENT\":\n return {\n ...base,\n principalType: \"DEPARTMENT\",\n departmentId: principal.departmentId,\n };\n case \"SCHOOL\":\n return { ...base, principalType: \"SCHOOL\", schoolId: principal.schoolId };\n }\n}\n\n/**\n * Create a new explicit grant on a folder. Validates:\n * - Granter has WRITE on the folder.\n * - The principal is in the same school as the folder's scope (no\n * cross-school leaks). Personal-scope folders cannot be granted to\n * non-USER principals — there's no \"school\" to check membership against.\n */\nexport async function grantPermission(\n grantedById: string,\n input: {\n folderId: string;\n principal: PermissionPrincipalInput;\n level: AccessLevel;\n }\n) {\n await requireFolderAccess(grantedById, input.folderId, \"WRITE\");\n\n const [targetSchoolId, principalSchool] = await Promise.all([\n resolveTargetSchoolId(input.folderId),\n principalSchoolId(input.principal),\n ]);\n\n if (input.principal.kind !== \"USER\") {\n if (!targetSchoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message:\n \"Personal-scope items can only be shared with specific users, not groups\",\n });\n }\n if (principalSchool !== targetSchoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Cannot share with a principal from a different school\",\n });\n }\n } else if (targetSchoolId && principalSchool && principalSchool !== targetSchoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Cannot share with a user from a different school\",\n });\n }\n\n // Re-granting the same (folder, principal) pair updates the existing row's\n // level instead of throwing P2002 against the @@unique. Prisma's composite-\n // unique-key types refuse nullable columns, so we go through findFirst +\n // update/create rather than a single upsert.\n const principalCols = principalToColumns(input.principal);\n const existing = await prisma.permission.findFirst({\n where: {\n folderId: input.folderId,\n principalType: principalCols.principalType,\n userId: principalCols.userId,\n tagId: principalCols.tagId,\n classId: principalCols.classId,\n departmentId: principalCols.departmentId,\n schoolId: principalCols.schoolId,\n },\n select: { id: true },\n });\n if (existing) {\n return prisma.permission.update({\n where: { id: existing.id },\n data: { level: input.level, grantedById },\n });\n }\n return prisma.permission.create({\n data: {\n folderId: input.folderId,\n ...principalCols,\n level: input.level,\n grantedById,\n },\n });\n}\n\n/** Revoke a grant. Allowed for the granter or anyone with WRITE on the folder. */\nexport async function revokePermission(userId: string, permissionId: string) {\n const grant = await prisma.permission.findUnique({\n where: { id: permissionId },\n select: { id: true, grantedById: true, folderId: true },\n });\n if (!grant) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Permission not found\" });\n }\n if (grant.grantedById !== userId) {\n await requireFolderAccess(userId, grant.folderId, \"WRITE\");\n }\n await prisma.permission.delete({ where: { id: permissionId } });\n return { success: true };\n}\n\n/** List all explicit grants on a folder. Caller must have WRITE on it. */\nexport async function listPermissions(userId: string, folderId: string) {\n await requireFolderAccess(userId, folderId, \"WRITE\");\n return prisma.permission.findMany({\n where: { folderId },\n include: {\n user: { select: { id: true, username: true, email: true } },\n tag: { select: { id: true, name: true, color: true } },\n class: { select: { id: true, name: true, section: true } },\n department: { select: { id: true, name: true, color: true } },\n school: { select: { id: true, name: true } },\n },\n orderBy: { createdAt: \"desc\" },\n });\n}\n"],"names":[],"mappings":"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","debug_id":"2ac7304e-3502-58ed-af8e-db3b64af3009"}
@@ -4,35 +4,43 @@
4
4
  import { SchoolMembershipRole } from "@prisma/client";
5
5
  export declare function getCurrentSchool(userId: string, schoolId?: string): Promise<{
6
6
  activeSchool: {
7
- name: string;
8
7
  id: string;
9
- logoId: string | null;
8
+ name: string;
9
+ description: string | null;
10
10
  subdomain: string | null;
11
- createdAt: Date;
12
- updatedAt: Date;
11
+ logoId: string | null;
12
+ logoPath: string | null;
13
+ logoType: string | null;
13
14
  } | null;
14
15
  activeRole: import(".prisma/client").$Enums.SchoolMembershipRole | null;
15
16
  memberships: ({
16
17
  school: {
17
18
  name: string;
18
19
  id: string;
20
+ description: string | null;
19
21
  logoId: string | null;
20
22
  subdomain: string | null;
21
23
  createdAt: Date;
22
24
  updatedAt: Date;
25
+ logo: {
26
+ path: string;
27
+ type: string;
28
+ id: string;
29
+ } | null;
23
30
  };
24
31
  } & {
25
32
  status: import(".prisma/client").$Enums.SchoolMembershipStatus;
26
33
  id: string;
27
34
  createdAt: Date;
28
35
  updatedAt: Date;
29
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
30
36
  schoolId: string;
31
37
  userId: string;
38
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
32
39
  })[];
33
40
  }>;
34
41
  export declare function createSchoolRecord(userId: string, input: {
35
42
  name: string;
43
+ description?: string;
36
44
  subdomain?: string;
37
45
  logoId?: string;
38
46
  }): Promise<{
@@ -42,19 +50,35 @@ export declare function createSchoolRecord(userId: string, input: {
42
50
  id: string;
43
51
  createdAt: Date;
44
52
  updatedAt: Date;
45
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
46
53
  schoolId: string;
47
54
  userId: string;
55
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
48
56
  }[];
49
57
  } & {
50
58
  name: string;
51
59
  id: string;
60
+ description: string | null;
52
61
  logoId: string | null;
53
62
  subdomain: string | null;
54
63
  createdAt: Date;
55
64
  updatedAt: Date;
56
65
  };
57
66
  }>;
67
+ export declare function updateSchoolDetails(userId: string, input: {
68
+ schoolId: string;
69
+ name?: string;
70
+ description?: string | null;
71
+ subdomain?: string | null;
72
+ logoId?: string | null;
73
+ }): Promise<{
74
+ school: {
75
+ name: string;
76
+ id: string;
77
+ description: string | null;
78
+ logoId: string | null;
79
+ subdomain: string | null;
80
+ };
81
+ }>;
58
82
  export declare function getAdminOverview(userId: string, schoolId: string): Promise<{
59
83
  school: {
60
84
  id: string;
@@ -115,6 +139,7 @@ export declare function listClasses(userId: string, schoolId: string): Promise<{
115
139
  color: string | null;
116
140
  section: string;
117
141
  syllabus: string | null;
142
+ departmentId: string | null;
118
143
  })[];
119
144
  }>;
120
145
  export declare function createSchoolClass(userId: string, input: {
@@ -123,6 +148,7 @@ export declare function createSchoolClass(userId: string, input: {
123
148
  section: string;
124
149
  subject: string;
125
150
  color?: string;
151
+ departmentId?: string;
126
152
  teachers?: string[];
127
153
  students?: string[];
128
154
  }): Promise<{
@@ -133,7 +159,6 @@ export declare function createSchoolClass(userId: string, input: {
133
159
  email: string;
134
160
  password: string;
135
161
  verified: boolean;
136
- role: import(".prisma/client").$Enums.UserRole;
137
162
  schoolId: string | null;
138
163
  }[];
139
164
  students: {
@@ -142,7 +167,6 @@ export declare function createSchoolClass(userId: string, input: {
142
167
  email: string;
143
168
  password: string;
144
169
  verified: boolean;
145
- role: import(".prisma/client").$Enums.UserRole;
146
170
  schoolId: string | null;
147
171
  }[];
148
172
  } & {
@@ -153,6 +177,7 @@ export declare function createSchoolClass(userId: string, input: {
153
177
  color: string | null;
154
178
  section: string;
155
179
  syllabus: string | null;
180
+ departmentId: string | null;
156
181
  };
157
182
  }>;
158
183
  export declare function listMembers(userId: string, schoolId: string): Promise<{
@@ -184,9 +209,9 @@ export declare function addMember(userId: string, input: {
184
209
  id: string;
185
210
  createdAt: Date;
186
211
  updatedAt: Date;
187
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
188
212
  schoolId: string;
189
213
  userId: string;
214
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
190
215
  };
191
216
  }>;
192
217
  export declare function updateMemberRole(userId: string, input: {
@@ -199,9 +224,9 @@ export declare function updateMemberRole(userId: string, input: {
199
224
  id: string;
200
225
  createdAt: Date;
201
226
  updatedAt: Date;
202
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
203
227
  schoolId: string;
204
228
  userId: string;
229
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
205
230
  };
206
231
  }>;
207
232
  export declare function removeMember(userId: string, input: {
@@ -229,12 +254,113 @@ export declare function listInvites(userId: string, schoolId: string): Promise<{
229
254
  };
230
255
  }[];
231
256
  }>;
257
+ /**
258
+ * Issue a direct-upload URL for a school-level asset (e.g. logo). The file
259
+ * is created unattached and is owned by the requester until they associate
260
+ * it via school.create or school.update.
261
+ */
262
+ export declare function getSchoolAssetUploadUrl(userId: string, input: {
263
+ fileName: string;
264
+ fileType: string;
265
+ fileSize: number;
266
+ }): Promise<import("../lib/fileUpload.js").DirectUploadFile>;
267
+ export declare function confirmSchoolAssetUpload(userId: string, fileId: string, uploadSuccess: boolean): Promise<{
268
+ success: boolean;
269
+ }>;
270
+ /**
271
+ * Lightweight ID-only listing used to mask external user names in the UI.
272
+ * Any active institution member can fetch this.
273
+ */
274
+ export declare function listMemberIds(userId: string, schoolId: string): Promise<string[]>;
275
+ /** Search active institution members by username, displayName, or email. */
276
+ export declare function searchMembers(userId: string, schoolId: string, query: string, limit?: number, role?: "ADMIN" | "TEACHER" | "STUDENT"): Promise<{
277
+ id: string;
278
+ username: string;
279
+ profile: {
280
+ displayName: string | null;
281
+ profilePicture: string | null;
282
+ profilePictureThumbnail: string | null;
283
+ } | null;
284
+ schoolMemberships: {
285
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
286
+ }[];
287
+ }[]>;
288
+ /**
289
+ * Combined student timeline: calendar events + assignments + attendance.
290
+ * Visible to school admins (any student) and to teachers who share at least
291
+ * one class with the student.
292
+ */
293
+ export declare function getStudentTimeline(userId: string, input: {
294
+ schoolId: string;
295
+ studentId: string;
296
+ from?: Date;
297
+ to?: Date;
298
+ }): Promise<{
299
+ student: {
300
+ id: string;
301
+ username: string;
302
+ profile: {
303
+ displayName: string | null;
304
+ profilePicture: string | null;
305
+ } | null;
306
+ };
307
+ events: {
308
+ name: string | null;
309
+ id: string;
310
+ class: {
311
+ name: string;
312
+ id: string;
313
+ color: string | null;
314
+ } | null;
315
+ color: string | null;
316
+ startTime: Date;
317
+ endTime: Date;
318
+ location: string | null;
319
+ remarks: string | null;
320
+ }[];
321
+ assignments: {
322
+ type: import(".prisma/client").$Enums.AssignmentType;
323
+ id: string;
324
+ class: {
325
+ name: string;
326
+ id: string;
327
+ subject: string;
328
+ color: string | null;
329
+ section: string;
330
+ };
331
+ submissions: {
332
+ id: string;
333
+ gradeReceived: number | null;
334
+ submittedAt: Date | null;
335
+ submitted: boolean | null;
336
+ returned: boolean | null;
337
+ }[];
338
+ title: string;
339
+ dueDate: Date;
340
+ graded: boolean;
341
+ maxGrade: number | null;
342
+ weight: number;
343
+ }[];
344
+ attendance: {
345
+ id: string;
346
+ date: Date;
347
+ class: {
348
+ name: string;
349
+ id: string;
350
+ color: string | null;
351
+ };
352
+ status: "PRESENT" | "LATE" | "ABSENT";
353
+ }[];
354
+ }>;
232
355
  export declare function createInvite(userId: string, input: {
233
356
  schoolId: string;
234
357
  email: string;
235
358
  role: SchoolMembershipRole;
236
- username?: string;
359
+ /** Optional display name set by the inviting admin. If omitted the user
360
+ * picks their own when they complete the password reset flow. */
237
361
  displayName?: string;
362
+ /** Optional username; if omitted we generate a friendly random one. */
363
+ username?: string;
238
364
  }): Promise<{
239
365
  invite: {
240
366
  school: {
@@ -247,8 +373,8 @@ export declare function createInvite(userId: string, input: {
247
373
  createdAt: Date;
248
374
  updatedAt: Date;
249
375
  email: string;
250
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
251
376
  schoolId: string;
377
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
252
378
  token: string;
253
379
  expiresAt: Date;
254
380
  acceptedAt: Date | null;
@@ -258,7 +384,8 @@ export declare function createInvite(userId: string, input: {
258
384
  createdUser: {
259
385
  id: string;
260
386
  username: string;
261
- } | null;
387
+ };
388
+ passwordResetUrl: string;
262
389
  }>;
263
390
  export declare function revokeInvite(userId: string, input: {
264
391
  schoolId: string;
@@ -270,8 +397,8 @@ export declare function revokeInvite(userId: string, input: {
270
397
  createdAt: Date;
271
398
  updatedAt: Date;
272
399
  email: string;
273
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
274
400
  schoolId: string;
401
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
275
402
  token: string;
276
403
  expiresAt: Date;
277
404
  acceptedAt: Date | null;
@@ -297,9 +424,9 @@ export declare function acceptInvite(userId: string, token: string): Promise<{
297
424
  id: string;
298
425
  createdAt: Date;
299
426
  updatedAt: Date;
300
- role: import(".prisma/client").$Enums.SchoolMembershipRole;
301
427
  schoolId: string;
302
428
  userId: string;
429
+ role: import(".prisma/client").$Enums.SchoolMembershipRole;
303
430
  };
304
431
  }>;
305
432
  //# sourceMappingURL=school.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["services/school.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAe,MAAM,gBAAgB,CAAC;AA2DnE,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAWvE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;GAU7D;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BtE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjE;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqBF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;GAGjE;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,oBAAoB,CAAA;CAAE;;;;;;;;;;GAS9E;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,oBAAoB,CAAA;CAAE;;;;;;;;;;GAwB9E;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE;;GAoBlD;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;GAGjE;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,oBAAoB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;;;;;;;;;;;;;;;;;;;;;YAMsB,MAAM;kBAAY,MAAM;;GA2FhD;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;GAI9C;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM;;;;;;;;;;;GAiB5C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;GAsB/D"}
1
+ {"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["services/school.ts"],"names":[],"mappings":"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"}