@citolab/qti-backend-firebase 0.0.3

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 (111) hide show
  1. package/LICENSE.md +674 -0
  2. package/dist/api/app-specific/base/application-specific-base.d.ts +45 -0
  3. package/dist/api/app-specific/base/application-specific-base.d.ts.map +1 -0
  4. package/dist/api/app-specific/base/application-specific-base.js +503 -0
  5. package/dist/api/app-specific/base/application-specific-base.js.map +1 -0
  6. package/dist/api/app-specific/base/cheerio-helper.d.ts +5 -0
  7. package/dist/api/app-specific/base/cheerio-helper.d.ts.map +1 -0
  8. package/dist/api/app-specific/base/cheerio-helper.js +16 -0
  9. package/dist/api/app-specific/base/cheerio-helper.js.map +1 -0
  10. package/dist/api/app-specific/baseImplementation.d.ts +6 -0
  11. package/dist/api/app-specific/baseImplementation.d.ts.map +1 -0
  12. package/dist/api/app-specific/baseImplementation.js +11 -0
  13. package/dist/api/app-specific/baseImplementation.js.map +1 -0
  14. package/dist/api/app-specific/index.d.ts +4 -0
  15. package/dist/api/app-specific/index.d.ts.map +1 -0
  16. package/dist/api/app-specific/index.js +4 -0
  17. package/dist/api/app-specific/index.js.map +1 -0
  18. package/dist/api/app-specific/interface/IApplicationSpecific.d.ts +31 -0
  19. package/dist/api/app-specific/interface/IApplicationSpecific.d.ts.map +1 -0
  20. package/dist/api/app-specific/interface/IApplicationSpecific.js +2 -0
  21. package/dist/api/app-specific/interface/IApplicationSpecific.js.map +1 -0
  22. package/dist/api/app-specific/specific.d.ts +1 -0
  23. package/dist/api/app-specific/specific.d.ts.map +1 -0
  24. package/dist/api/app-specific/specific.js +31 -0
  25. package/dist/api/app-specific/specific.js.map +1 -0
  26. package/dist/api/index.d.ts +3 -0
  27. package/dist/api/index.d.ts.map +1 -0
  28. package/dist/api/index.js +15 -0
  29. package/dist/api/index.js.map +1 -0
  30. package/dist/api/qti-data.d.ts +4 -0
  31. package/dist/api/qti-data.d.ts.map +1 -0
  32. package/dist/api/qti-data.js +622 -0
  33. package/dist/api/qti-data.js.map +1 -0
  34. package/dist/api/qti-resources.d.ts +4 -0
  35. package/dist/api/qti-resources.d.ts.map +1 -0
  36. package/dist/api/qti-resources.js +348 -0
  37. package/dist/api/qti-resources.js.map +1 -0
  38. package/dist/api/qti-teacher.d.ts +6 -0
  39. package/dist/api/qti-teacher.d.ts.map +1 -0
  40. package/dist/api/qti-teacher.js +807 -0
  41. package/dist/api/qti-teacher.js.map +1 -0
  42. package/dist/api/qti-tools.d.ts +3 -0
  43. package/dist/api/qti-tools.d.ts.map +1 -0
  44. package/dist/api/qti-tools.js +450 -0
  45. package/dist/api/qti-tools.js.map +1 -0
  46. package/dist/console.d.ts +2 -0
  47. package/dist/console.d.ts.map +1 -0
  48. package/dist/console.js +30 -0
  49. package/dist/console.js.map +1 -0
  50. package/dist/express-test.d.ts +2 -0
  51. package/dist/express-test.d.ts.map +1 -0
  52. package/dist/express-test.js +19 -0
  53. package/dist/express-test.js.map +1 -0
  54. package/dist/helpers/ci-bootstap.d.ts +4 -0
  55. package/dist/helpers/ci-bootstap.d.ts.map +1 -0
  56. package/dist/helpers/ci-bootstap.js +96 -0
  57. package/dist/helpers/ci-bootstap.js.map +1 -0
  58. package/dist/helpers/database.d.ts +110 -0
  59. package/dist/helpers/database.d.ts.map +1 -0
  60. package/dist/helpers/database.js +151 -0
  61. package/dist/helpers/database.js.map +1 -0
  62. package/dist/helpers/db.d.ts +3 -0
  63. package/dist/helpers/db.d.ts.map +1 -0
  64. package/dist/helpers/db.js +10 -0
  65. package/dist/helpers/db.js.map +1 -0
  66. package/dist/helpers/endpoint-helpers.d.ts +33 -0
  67. package/dist/helpers/endpoint-helpers.d.ts.map +1 -0
  68. package/dist/helpers/endpoint-helpers.js +149 -0
  69. package/dist/helpers/endpoint-helpers.js.map +1 -0
  70. package/dist/helpers/firebase.d.ts +7 -0
  71. package/dist/helpers/firebase.d.ts.map +1 -0
  72. package/dist/helpers/firebase.js +15 -0
  73. package/dist/helpers/firebase.js.map +1 -0
  74. package/dist/helpers/index.d.ts +11 -0
  75. package/dist/helpers/index.d.ts.map +1 -0
  76. package/dist/helpers/index.js +11 -0
  77. package/dist/helpers/index.js.map +1 -0
  78. package/dist/helpers/local-helpers.d.ts +2 -0
  79. package/dist/helpers/local-helpers.d.ts.map +1 -0
  80. package/dist/helpers/local-helpers.js +11 -0
  81. package/dist/helpers/local-helpers.js.map +1 -0
  82. package/dist/helpers/logic.d.ts +73 -0
  83. package/dist/helpers/logic.d.ts.map +1 -0
  84. package/dist/helpers/logic.js +759 -0
  85. package/dist/helpers/logic.js.map +1 -0
  86. package/dist/helpers/package-upload.d.ts +16 -0
  87. package/dist/helpers/package-upload.d.ts.map +1 -0
  88. package/dist/helpers/package-upload.js +160 -0
  89. package/dist/helpers/package-upload.js.map +1 -0
  90. package/dist/helpers/package.d.ts +32 -0
  91. package/dist/helpers/package.d.ts.map +1 -0
  92. package/dist/helpers/package.js +373 -0
  93. package/dist/helpers/package.js.map +1 -0
  94. package/dist/helpers/request-headers.d.ts +27 -0
  95. package/dist/helpers/request-headers.d.ts.map +1 -0
  96. package/dist/helpers/request-headers.js +144 -0
  97. package/dist/helpers/request-headers.js.map +1 -0
  98. package/dist/helpers/storage.d.ts +10 -0
  99. package/dist/helpers/storage.d.ts.map +1 -0
  100. package/dist/helpers/storage.js +132 -0
  101. package/dist/helpers/storage.js.map +1 -0
  102. package/dist/helpers/utils.d.ts +42 -0
  103. package/dist/helpers/utils.d.ts.map +1 -0
  104. package/dist/helpers/utils.js +228 -0
  105. package/dist/helpers/utils.js.map +1 -0
  106. package/dist/main.d.ts +2 -0
  107. package/dist/main.d.ts.map +1 -0
  108. package/dist/main.js +14 -0
  109. package/dist/main.js.map +1 -0
  110. package/package.json +101 -0
  111. package/readme.md +11 -0
@@ -0,0 +1,348 @@
1
+ // get package resources
2
+ // for resources other than .xml it should be returned from storage
3
+ // for xml files: the application should have it's own implementation of how to get the xml
4
+ import mime from "mime";
5
+ import { getStartableAssessments } from "./../helpers/logic";
6
+ import path from "path";
7
+ import { getAppId, tryAuthenticateStudent } from "./../helpers/request-headers";
8
+ import { getDatabase } from "../helpers/db";
9
+ import { getStorageRef } from "../helpers/package";
10
+ import { IsTrue, trim } from "../helpers/utils";
11
+ import { getStorage, getFirestore } from "../helpers/firebase";
12
+ import { BaseImplementation } from "./app-specific/baseImplementation";
13
+ import { param, validationResult } from "express-validator";
14
+ import { generalRateLimit, sendError, sendSuccess, validateAssessmentId, } from "../helpers/endpoint-helpers";
15
+ // this could be from storage, but also from a database, and it could do manipulations on the xml with cheerio before returning it.
16
+ // Validation middleware
17
+ const handleValidationErrors = (req, res, next) => {
18
+ const errors = validationResult(req);
19
+ if (!errors.isEmpty()) {
20
+ return sendError(res, 400, "Validation failed", errors.array());
21
+ }
22
+ next();
23
+ };
24
+ // Validation helpers
25
+ const validateGroupCode = (code) => {
26
+ return (typeof code === "string" &&
27
+ code.length > 0 &&
28
+ code.length <= 50 &&
29
+ /^[a-zA-Z0-9_-]+$/.test(code));
30
+ };
31
+ const validateApplicationId = (appId) => {
32
+ return (typeof appId === "string" &&
33
+ appId.length > 0 &&
34
+ appId.length <= 100 &&
35
+ /^[a-zA-Z0-9_.-]+$/.test(appId));
36
+ };
37
+ const validatePackageId = (packageId) => {
38
+ return (typeof packageId === "string" &&
39
+ packageId.length > 0 &&
40
+ packageId.length <= 100 &&
41
+ /^[a-zA-Z0-9_.-]+$/.test(packageId));
42
+ };
43
+ export function addQtiResourcesEndpoint(app, specificImplementation = new BaseImplementation()) {
44
+ function getAssessmentById(appId, assessmentId, code) {
45
+ return specificImplementation.getAssessmentInfo(assessmentId, code);
46
+ }
47
+ async function getAssessmentByGroupCode(appId, groupCode) {
48
+ const db = getDatabase(appId);
49
+ const firestore = getFirestore();
50
+ if (!db || !firestore) {
51
+ throw new Error("Database or Firestore not initialized");
52
+ }
53
+ const assessmentDoc = await firestore
54
+ .doc(db.GROUP_DELIVERY.DOC(groupCode))
55
+ .get();
56
+ if (!assessmentDoc.exists) {
57
+ console.warn(`No assessment found for group code: ${groupCode}`);
58
+ return null;
59
+ }
60
+ const assessmentData = assessmentDoc.data();
61
+ return specificImplementation.getAssessmentInfo(assessmentData.assessmentId);
62
+ }
63
+ /**
64
+ * @openapi
65
+ * /assessment/{assessmentId}:
66
+ * get:
67
+ * tags:
68
+ * - Assessment
69
+ * summary: Get assessment by ID
70
+ * description: Retrieves assessment information by its ID.
71
+ * parameters:
72
+ * - in: path
73
+ * name: assessmentId
74
+ * required: true
75
+ * schema:
76
+ * type: string
77
+ * description: The ID of the assessment.
78
+ * responses:
79
+ * 200:
80
+ * description: Successfully retrieved assessment information.
81
+ * content:
82
+ * application/json:
83
+ * schema:
84
+ * $ref: '#/components/schemas/AssessmentInfo'
85
+ * 400:
86
+ * description: Invalid assessment ID format
87
+ * 404:
88
+ * description: Assessment not found
89
+ * 500:
90
+ * description: Internal server error
91
+ */
92
+ app.get("/assessment/:assessmentId", [
93
+ generalRateLimit,
94
+ param("assessmentId").custom((value) => {
95
+ if (!validateAssessmentId(value)) {
96
+ throw new Error("Invalid assessment ID format");
97
+ }
98
+ return true;
99
+ }),
100
+ handleValidationErrors,
101
+ ], async (req, res) => {
102
+ try {
103
+ const assessmentId = req.params.assessmentId;
104
+ const appId = getAppId(req);
105
+ const user = await tryAuthenticateStudent(req, res);
106
+ let code = "";
107
+ if (user) {
108
+ const userId = user.uid;
109
+ code = await specificImplementation.getCodeByUserId(userId, assessmentId);
110
+ }
111
+ const assessmentInfo = await getAssessmentById(appId, assessmentId, code);
112
+ if (!assessmentInfo) {
113
+ return sendError(res, 404, `Assessment not found: ${assessmentId}`);
114
+ }
115
+ return sendSuccess(res, assessmentInfo);
116
+ }
117
+ catch (error) {
118
+ console.error("Error retrieving assessment:", error);
119
+ return sendError(res, 500, "Failed to retrieve assessment");
120
+ }
121
+ });
122
+ /**
123
+ * @openapi
124
+ * /assessment/byGroupCode/{groupCode}:
125
+ * get:
126
+ * tags:
127
+ * - Assessment
128
+ * summary: Get assessment by group code
129
+ * description: Retrieves assessment information by its group code.
130
+ * parameters:
131
+ * - in: path
132
+ * name: groupCode
133
+ * required: true
134
+ * schema:
135
+ * type: string
136
+ * description: The group code of the assessment.
137
+ * responses:
138
+ * 200:
139
+ * description: Successfully retrieved assessment information.
140
+ * content:
141
+ * application/json:
142
+ * schema:
143
+ * $ref: '#/components/schemas/AssessmentInfo'
144
+ * 400:
145
+ * description: Invalid group code format
146
+ * 404:
147
+ * description: Assessment not found
148
+ * 500:
149
+ * description: Internal server error
150
+ */
151
+ app.get("/assessment/byGroupCode/:groupCode", [
152
+ generalRateLimit,
153
+ param("groupCode").custom((value) => {
154
+ if (!validateGroupCode(value)) {
155
+ throw new Error("Invalid group code format");
156
+ }
157
+ return true;
158
+ }),
159
+ handleValidationErrors,
160
+ ], async (req, res) => {
161
+ try {
162
+ const groupCode = req.params.groupCode;
163
+ const appId = getAppId(req);
164
+ const user = await tryAuthenticateStudent(req, res);
165
+ const assessmentInfo = await getAssessmentByGroupCode(appId, groupCode);
166
+ if (!assessmentInfo) {
167
+ return sendError(res, 404, `Assessment not found for group code: ${groupCode}`);
168
+ }
169
+ return sendSuccess(res, assessmentInfo);
170
+ }
171
+ catch (error) {
172
+ console.error("Error retrieving assessment by group code:", error);
173
+ return sendError(res, 500, "Failed to retrieve assessment");
174
+ }
175
+ });
176
+ /**
177
+ * @openapi
178
+ * /assessments:
179
+ * get:
180
+ * tags:
181
+ * - Assessment
182
+ * summary: Get startable assessments
183
+ * description: Retrieves a list of assessments that can be started.
184
+ * responses:
185
+ * 200:
186
+ * description: Successfully retrieved list of startable assessments.
187
+ * content:
188
+ * application/json:
189
+ * schema:
190
+ * type: array
191
+ * items:
192
+ * $ref: '#/components/schemas/AssessmentInfo'
193
+ * 500:
194
+ * description: Internal server error
195
+ */
196
+ app.get("/assessments", [generalRateLimit], async (req, res) => {
197
+ try {
198
+ // TODO: authentication here?
199
+ const appId = getAppId(req);
200
+ const db = getDatabase(appId);
201
+ const startableAssessments = await getStartableAssessments(db);
202
+ return sendSuccess(res, startableAssessments);
203
+ }
204
+ catch (error) {
205
+ console.error("Error retrieving startable assessments:", error);
206
+ return sendError(res, 500, "Failed to retrieve assessments");
207
+ }
208
+ });
209
+ /**
210
+ * @openapi
211
+ * /application/{applicationId}/package/{packageId}/*:
212
+ * get:
213
+ * tags:
214
+ * - Assessment
215
+ * summary: Get package resources
216
+ * description: Retrieves package resources, including handling XML files but also images and videos etc. from a QTI package that is uploaded to FireStorage
217
+ * parameters:
218
+ * - in: path
219
+ * name: applicationId
220
+ * required: true
221
+ * schema:
222
+ * type: string
223
+ * description: The ID of the application.
224
+ * - in: path
225
+ * name: packageId
226
+ * required: true
227
+ * schema:
228
+ * type: string
229
+ * description: The ID of the package.
230
+ * - in: path
231
+ * name: '*'
232
+ * required: true
233
+ * schema:
234
+ * type: string
235
+ * description: The relative path to the resource within the package.
236
+ * responses:
237
+ * 200:
238
+ * description: Successfully retrieved the resource.
239
+ * 400:
240
+ * description: Invalid parameters
241
+ * 404:
242
+ * description: Resource not found
243
+ * 500:
244
+ * description: Internal server error
245
+ */
246
+ app.get("/application/:applicationId/package/:packageId/*", [
247
+ generalRateLimit, // Use general rate limit for resource requests
248
+ param("applicationId").custom((value) => {
249
+ if (!validateApplicationId(value)) {
250
+ throw new Error("Invalid application ID format");
251
+ }
252
+ return true;
253
+ }),
254
+ param("packageId").custom((value) => {
255
+ if (!validatePackageId(value)) {
256
+ throw new Error("Invalid package ID format");
257
+ }
258
+ return true;
259
+ }),
260
+ handleValidationErrors,
261
+ ], async (req, res) => {
262
+ try {
263
+ const applicationId = req.params.applicationId;
264
+ const packageId = req.params.packageId;
265
+ let relativeUrl = trim(req.params[0].toString(), "/")
266
+ .trim()
267
+ .normalize("NFD");
268
+ // Validate and sanitize the relative URL
269
+ if (!relativeUrl || relativeUrl.length === 0) {
270
+ sendError(res, 400, "Invalid resource path");
271
+ return;
272
+ }
273
+ // Security check: prevent directory traversal
274
+ if (relativeUrl.includes("..") || relativeUrl.includes("//")) {
275
+ sendError(res, 400, "Invalid resource path");
276
+ return;
277
+ }
278
+ relativeUrl = decodeURIComponent(relativeUrl);
279
+ const isSingleTenant = IsTrue(process.env.SINGLE_TENANT);
280
+ const storageRef = getStorageRef(relativeUrl, isSingleTenant, packageId, applicationId);
281
+ const bucket = getStorage().bucket();
282
+ const ext = path.extname(relativeUrl).toLowerCase();
283
+ const type = mime.getType(ext) || "application/octet-stream";
284
+ const shouldStream = type.startsWith("video/") || type.startsWith("audio/");
285
+ // Check if file exists in cloud storage
286
+ const fileRef = bucket.file(storageRef);
287
+ const [exists] = await fileRef.exists();
288
+ if (!exists) {
289
+ console.warn(`File not found in storage: ${storageRef}`);
290
+ sendError(res, 404, `Resource not found: ${relativeUrl}`);
291
+ return;
292
+ }
293
+ res.set("Cache-Control", "public, max-age=86400, s-maxage=86400");
294
+ // Handle audio and video files with byte-range streaming
295
+ if (shouldStream) {
296
+ const [metadata] = await fileRef.getMetadata();
297
+ const fileSize = Number(metadata.size);
298
+ const range = req.headers.range;
299
+ if (range) {
300
+ const parts = range.replace(/bytes=/, "").split("-");
301
+ const start = parseInt(parts[0], 10);
302
+ const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
303
+ // Validate range values
304
+ if (isNaN(start) ||
305
+ isNaN(end) ||
306
+ start >= fileSize ||
307
+ end >= fileSize ||
308
+ start > end) {
309
+ sendError(res, 400, "Invalid range request");
310
+ return;
311
+ }
312
+ const chunkSize = end - start + 1;
313
+ const stream = fileRef.createReadStream({ start, end });
314
+ res.writeHead(206, {
315
+ "Content-Range": `bytes ${start}-${end}/${fileSize}`,
316
+ "Accept-Ranges": "bytes",
317
+ "Content-Length": chunkSize,
318
+ "Content-Type": type,
319
+ });
320
+ stream.pipe(res);
321
+ return;
322
+ }
323
+ // No Range header — send full video
324
+ res.writeHead(200, {
325
+ "Content-Length": fileSize,
326
+ "Content-Type": type,
327
+ "Accept-Ranges": "bytes",
328
+ });
329
+ fileRef.createReadStream().pipe(res);
330
+ return;
331
+ }
332
+ // For non-XML, non-video files — buffer and send
333
+ const content = await fileRef.download();
334
+ const buffer = content[0];
335
+ if (type) {
336
+ res.set("Content-Type", type);
337
+ }
338
+ res.send(buffer);
339
+ return;
340
+ }
341
+ catch (error) {
342
+ console.error("Error retrieving package resource:", error);
343
+ sendError(res, 500, "Failed to retrieve resource");
344
+ return;
345
+ }
346
+ });
347
+ }
348
+ //# sourceMappingURL=qti-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qti-resources.js","sourceRoot":"","sources":["../../src/api/qti-resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Express, Response, NextFunction } from "express";
2
+ import { AuthenticatedRequest } from "../helpers/endpoint-helpers";
3
+ import { IApplicationSpecific } from "./app-specific";
4
+ export declare const requireTeacherAuth: (req: AuthenticatedRequest, res: Response, next: NextFunction) => Promise<void>;
5
+ export declare function addQtiTeacherEndpoints(app: Express, specificImplementation?: IApplicationSpecific): void;
6
+ //# sourceMappingURL=qti-teacher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qti-teacher.d.ts","sourceRoot":"","sources":["../../src/api/qti-teacher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAW,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAkBnE,OAAO,EACL,oBAAoB,EAOrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAItD,eAAO,MAAM,kBAAkB,GAC7B,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,MAAM,YAAY,kBAcnB,CAAC;AAmEF,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,sBAAsB,GAAE,oBAA+C,QAg3BxE"}