@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.
- package/LICENSE.md +674 -0
- package/dist/api/app-specific/base/application-specific-base.d.ts +45 -0
- package/dist/api/app-specific/base/application-specific-base.d.ts.map +1 -0
- package/dist/api/app-specific/base/application-specific-base.js +503 -0
- package/dist/api/app-specific/base/application-specific-base.js.map +1 -0
- package/dist/api/app-specific/base/cheerio-helper.d.ts +5 -0
- package/dist/api/app-specific/base/cheerio-helper.d.ts.map +1 -0
- package/dist/api/app-specific/base/cheerio-helper.js +16 -0
- package/dist/api/app-specific/base/cheerio-helper.js.map +1 -0
- package/dist/api/app-specific/baseImplementation.d.ts +6 -0
- package/dist/api/app-specific/baseImplementation.d.ts.map +1 -0
- package/dist/api/app-specific/baseImplementation.js +11 -0
- package/dist/api/app-specific/baseImplementation.js.map +1 -0
- package/dist/api/app-specific/index.d.ts +4 -0
- package/dist/api/app-specific/index.d.ts.map +1 -0
- package/dist/api/app-specific/index.js +4 -0
- package/dist/api/app-specific/index.js.map +1 -0
- package/dist/api/app-specific/interface/IApplicationSpecific.d.ts +31 -0
- package/dist/api/app-specific/interface/IApplicationSpecific.d.ts.map +1 -0
- package/dist/api/app-specific/interface/IApplicationSpecific.js +2 -0
- package/dist/api/app-specific/interface/IApplicationSpecific.js.map +1 -0
- package/dist/api/app-specific/specific.d.ts +1 -0
- package/dist/api/app-specific/specific.d.ts.map +1 -0
- package/dist/api/app-specific/specific.js +31 -0
- package/dist/api/app-specific/specific.js.map +1 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +15 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/qti-data.d.ts +4 -0
- package/dist/api/qti-data.d.ts.map +1 -0
- package/dist/api/qti-data.js +622 -0
- package/dist/api/qti-data.js.map +1 -0
- package/dist/api/qti-resources.d.ts +4 -0
- package/dist/api/qti-resources.d.ts.map +1 -0
- package/dist/api/qti-resources.js +348 -0
- package/dist/api/qti-resources.js.map +1 -0
- package/dist/api/qti-teacher.d.ts +6 -0
- package/dist/api/qti-teacher.d.ts.map +1 -0
- package/dist/api/qti-teacher.js +807 -0
- package/dist/api/qti-teacher.js.map +1 -0
- package/dist/api/qti-tools.d.ts +3 -0
- package/dist/api/qti-tools.d.ts.map +1 -0
- package/dist/api/qti-tools.js +450 -0
- package/dist/api/qti-tools.js.map +1 -0
- package/dist/console.d.ts +2 -0
- package/dist/console.d.ts.map +1 -0
- package/dist/console.js +30 -0
- package/dist/console.js.map +1 -0
- package/dist/express-test.d.ts +2 -0
- package/dist/express-test.d.ts.map +1 -0
- package/dist/express-test.js +19 -0
- package/dist/express-test.js.map +1 -0
- package/dist/helpers/ci-bootstap.d.ts +4 -0
- package/dist/helpers/ci-bootstap.d.ts.map +1 -0
- package/dist/helpers/ci-bootstap.js +96 -0
- package/dist/helpers/ci-bootstap.js.map +1 -0
- package/dist/helpers/database.d.ts +110 -0
- package/dist/helpers/database.d.ts.map +1 -0
- package/dist/helpers/database.js +151 -0
- package/dist/helpers/database.js.map +1 -0
- package/dist/helpers/db.d.ts +3 -0
- package/dist/helpers/db.d.ts.map +1 -0
- package/dist/helpers/db.js +10 -0
- package/dist/helpers/db.js.map +1 -0
- package/dist/helpers/endpoint-helpers.d.ts +33 -0
- package/dist/helpers/endpoint-helpers.d.ts.map +1 -0
- package/dist/helpers/endpoint-helpers.js +149 -0
- package/dist/helpers/endpoint-helpers.js.map +1 -0
- package/dist/helpers/firebase.d.ts +7 -0
- package/dist/helpers/firebase.d.ts.map +1 -0
- package/dist/helpers/firebase.js +15 -0
- package/dist/helpers/firebase.js.map +1 -0
- package/dist/helpers/index.d.ts +11 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +11 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/local-helpers.d.ts +2 -0
- package/dist/helpers/local-helpers.d.ts.map +1 -0
- package/dist/helpers/local-helpers.js +11 -0
- package/dist/helpers/local-helpers.js.map +1 -0
- package/dist/helpers/logic.d.ts +73 -0
- package/dist/helpers/logic.d.ts.map +1 -0
- package/dist/helpers/logic.js +759 -0
- package/dist/helpers/logic.js.map +1 -0
- package/dist/helpers/package-upload.d.ts +16 -0
- package/dist/helpers/package-upload.d.ts.map +1 -0
- package/dist/helpers/package-upload.js +160 -0
- package/dist/helpers/package-upload.js.map +1 -0
- package/dist/helpers/package.d.ts +32 -0
- package/dist/helpers/package.d.ts.map +1 -0
- package/dist/helpers/package.js +373 -0
- package/dist/helpers/package.js.map +1 -0
- package/dist/helpers/request-headers.d.ts +27 -0
- package/dist/helpers/request-headers.d.ts.map +1 -0
- package/dist/helpers/request-headers.js +144 -0
- package/dist/helpers/request-headers.js.map +1 -0
- package/dist/helpers/storage.d.ts +10 -0
- package/dist/helpers/storage.d.ts.map +1 -0
- package/dist/helpers/storage.js +132 -0
- package/dist/helpers/storage.js.map +1 -0
- package/dist/helpers/utils.d.ts +42 -0
- package/dist/helpers/utils.d.ts.map +1 -0
- package/dist/helpers/utils.js +228 -0
- package/dist/helpers/utils.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +14 -0
- package/dist/main.js.map +1 -0
- package/package.json +101 -0
- package/readme.md +11 -0
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
import { checkAssessmentCode, getPlannedStudent, getStartableAssessments, getStudentSessionInfo, getTeacherIdByCode, isStartable, updateStudentSessionState, } from "./../helpers/logic";
|
|
2
|
+
import { dateId } from "./../helpers/utils";
|
|
3
|
+
import { getAssessmentId, getName } from "./../helpers/request-headers";
|
|
4
|
+
import NodeCache from "node-cache";
|
|
5
|
+
import { getDatabase, getStudentGroupSessionInfo } from "../helpers";
|
|
6
|
+
import { getFirestore, getStorage } from "../helpers/firebase";
|
|
7
|
+
import { body, param } from "express-validator";
|
|
8
|
+
import { errorHandler, generalRateLimit, handleValidationErrors, heavyOperationLimit, imageUploadConfig, requireAuth, sendError, sendSuccess, } from "../helpers/endpoint-helpers";
|
|
9
|
+
import { BaseImplementation } from "./app-specific/baseImplementation";
|
|
10
|
+
export function addQtiDataEndpoints(app, specificImplementation = new BaseImplementation()) {
|
|
11
|
+
const cache = new NodeCache({
|
|
12
|
+
stdTTL: 300, // 5 minutes
|
|
13
|
+
checkperiod: 60, // Check for expired keys every minute
|
|
14
|
+
});
|
|
15
|
+
// Apply global error handler
|
|
16
|
+
app.use(errorHandler);
|
|
17
|
+
/**
|
|
18
|
+
* @openapi
|
|
19
|
+
* /checkCode:
|
|
20
|
+
* post:
|
|
21
|
+
* tags:
|
|
22
|
+
* - Session
|
|
23
|
+
* summary: Use to login by code. The code is used to identify the student. Can be created by the teacher or by Cito
|
|
24
|
+
* description: Checks if the provided assessment code is valid and retrieves session information for the student.
|
|
25
|
+
* requestBody:
|
|
26
|
+
* required: true
|
|
27
|
+
* content:
|
|
28
|
+
* application/json:
|
|
29
|
+
* schema:
|
|
30
|
+
* type: object
|
|
31
|
+
* properties:
|
|
32
|
+
* code:
|
|
33
|
+
* type: string
|
|
34
|
+
* description: The assessment code.
|
|
35
|
+
* minLength: 1
|
|
36
|
+
* maxLength: 50
|
|
37
|
+
* responses:
|
|
38
|
+
* 200:
|
|
39
|
+
* description: Successfully retrieved session information or null if not found.
|
|
40
|
+
* 400:
|
|
41
|
+
* description: Validation error
|
|
42
|
+
* 401:
|
|
43
|
+
* description: Authentication failed
|
|
44
|
+
* 500:
|
|
45
|
+
* description: Internal server error
|
|
46
|
+
*/
|
|
47
|
+
app.post("/checkCode", [
|
|
48
|
+
generalRateLimit,
|
|
49
|
+
body("code")
|
|
50
|
+
.isString()
|
|
51
|
+
.trim()
|
|
52
|
+
.isLength({ min: 1, max: 50 })
|
|
53
|
+
.withMessage("Code must be between 1 and 50 characters"),
|
|
54
|
+
handleValidationErrors,
|
|
55
|
+
requireAuth,
|
|
56
|
+
], async (req, res) => {
|
|
57
|
+
try {
|
|
58
|
+
const { code } = req.body;
|
|
59
|
+
const db = getDatabase(req.appId);
|
|
60
|
+
const sessionInfo = await getStudentSessionInfo(code.toUpperCase(), db, req.user.uid);
|
|
61
|
+
if (sessionInfo) {
|
|
62
|
+
return sendSuccess(res, { ...sessionInfo, userId: req.user.uid });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return sendSuccess(res, null);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error("Error in checkCode:", error);
|
|
70
|
+
return sendError(res, 500, "Failed to check code");
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* @openapi
|
|
75
|
+
* /checkGroupCode:
|
|
76
|
+
* post:
|
|
77
|
+
* tags:
|
|
78
|
+
* - Session
|
|
79
|
+
* summary: Use to login by group code. Creates a student session for group delivery.
|
|
80
|
+
* description: Checks if the provided group code is valid and creates/retrieves session information for the student.
|
|
81
|
+
* requestBody:
|
|
82
|
+
* required: true
|
|
83
|
+
* content:
|
|
84
|
+
* application/json:
|
|
85
|
+
* schema:
|
|
86
|
+
* type: object
|
|
87
|
+
* required:
|
|
88
|
+
* - groupCode
|
|
89
|
+
* properties:
|
|
90
|
+
* groupCode:
|
|
91
|
+
* type: string
|
|
92
|
+
* description: The group delivery code.
|
|
93
|
+
* minLength: 1
|
|
94
|
+
* maxLength: 50
|
|
95
|
+
* studentIdentification:
|
|
96
|
+
* type: string
|
|
97
|
+
* description: Optional student identification
|
|
98
|
+
* maxLength: 100
|
|
99
|
+
* responses:
|
|
100
|
+
* 200:
|
|
101
|
+
* description: Successfully retrieved/created session information or null if not found.
|
|
102
|
+
* 400:
|
|
103
|
+
* description: Validation error
|
|
104
|
+
* 401:
|
|
105
|
+
* description: Authentication failed
|
|
106
|
+
* 500:
|
|
107
|
+
* description: Internal server error
|
|
108
|
+
*/
|
|
109
|
+
app.post("/checkGroupCode", [
|
|
110
|
+
generalRateLimit,
|
|
111
|
+
body("groupCode")
|
|
112
|
+
.isString()
|
|
113
|
+
.trim()
|
|
114
|
+
.isLength({ min: 1, max: 50 })
|
|
115
|
+
.withMessage("Group code must be between 1 and 50 characters"),
|
|
116
|
+
body("studentIdentification")
|
|
117
|
+
.optional()
|
|
118
|
+
.isString()
|
|
119
|
+
.trim()
|
|
120
|
+
.isLength({ max: 100 })
|
|
121
|
+
.withMessage("Student identification must not exceed 100 characters"),
|
|
122
|
+
handleValidationErrors,
|
|
123
|
+
requireAuth,
|
|
124
|
+
], async (req, res) => {
|
|
125
|
+
try {
|
|
126
|
+
const { groupCode, studentIdentification } = req.body;
|
|
127
|
+
const db = getDatabase(req.appId);
|
|
128
|
+
const sessionInfo = await getStudentGroupSessionInfo(groupCode.toUpperCase(), db, req.user.uid, studentIdentification);
|
|
129
|
+
if (sessionInfo) {
|
|
130
|
+
return sendSuccess(res, { ...sessionInfo, userId: req.user.uid });
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
return sendSuccess(res, null);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.error("Error in checkGroupCode:", error);
|
|
138
|
+
return sendError(res, 500, "Failed to check group code");
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
/**
|
|
142
|
+
* POST /feedback
|
|
143
|
+
* Endpoint to submit user feedback with optional screenshot
|
|
144
|
+
*/
|
|
145
|
+
app.post("/feedback", [
|
|
146
|
+
heavyOperationLimit,
|
|
147
|
+
requireAuth,
|
|
148
|
+
imageUploadConfig.single("screenshot"),
|
|
149
|
+
body("type")
|
|
150
|
+
.isString()
|
|
151
|
+
.trim()
|
|
152
|
+
.isLength({ min: 1, max: 50 })
|
|
153
|
+
.withMessage("Type is required and must be between 1 and 50 characters"),
|
|
154
|
+
body("description")
|
|
155
|
+
.isString()
|
|
156
|
+
.trim()
|
|
157
|
+
.isLength({ min: 1, max: 2000 })
|
|
158
|
+
.withMessage("Description is required and must be between 1 and 2000 characters"),
|
|
159
|
+
body("feedbackId")
|
|
160
|
+
.isString()
|
|
161
|
+
.trim()
|
|
162
|
+
.isLength({ min: 1, max: 100 })
|
|
163
|
+
.withMessage("Feedback ID is required"),
|
|
164
|
+
body("email")
|
|
165
|
+
.optional()
|
|
166
|
+
.isEmail()
|
|
167
|
+
.withMessage("Must be a valid email address"),
|
|
168
|
+
body("pageUrl").optional().isURL().withMessage("Must be a valid URL"),
|
|
169
|
+
handleValidationErrors,
|
|
170
|
+
], async (req, res) => {
|
|
171
|
+
try {
|
|
172
|
+
const { type, description, feedbackId, email, pageUrl } = req.body;
|
|
173
|
+
const userId = req.user.uid;
|
|
174
|
+
const file = req.file;
|
|
175
|
+
// Create feedback document in Firestore
|
|
176
|
+
const firestore = getFirestore();
|
|
177
|
+
const db = getDatabase(req.appId);
|
|
178
|
+
const firebaseDocPath = db.FEEDBACK.DOC(`${feedbackId}_${userId}`);
|
|
179
|
+
const feedbackRef = firestore.doc(firebaseDocPath);
|
|
180
|
+
await feedbackRef.set({
|
|
181
|
+
type,
|
|
182
|
+
description,
|
|
183
|
+
userId,
|
|
184
|
+
email: email || null,
|
|
185
|
+
pageUrl: pageUrl || null,
|
|
186
|
+
hasScreenshot: !!file,
|
|
187
|
+
createdAt: new Date().toISOString(),
|
|
188
|
+
});
|
|
189
|
+
// If there's a screenshot, upload it to Firebase Storage
|
|
190
|
+
if (file) {
|
|
191
|
+
const storage = getStorage();
|
|
192
|
+
const bucket = storage.bucket();
|
|
193
|
+
const storagePath = firebaseDocPath.replace(/^\//, "");
|
|
194
|
+
const storageFile = bucket.file(`${storagePath}.png`);
|
|
195
|
+
await storageFile.save(file.buffer, {
|
|
196
|
+
metadata: {
|
|
197
|
+
contentType: file.mimetype,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return sendSuccess(res, undefined, "Feedback submitted successfully");
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.error("Error submitting feedback:", error);
|
|
205
|
+
return sendError(res, 500, "Failed to submit feedback");
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
/**
|
|
209
|
+
* @openapi
|
|
210
|
+
* /student/log:
|
|
211
|
+
* post:
|
|
212
|
+
* tags:
|
|
213
|
+
* - Student
|
|
214
|
+
* summary: Log student activity
|
|
215
|
+
* description: Logs student activity data for debugging and analytics purposes.
|
|
216
|
+
* requestBody:
|
|
217
|
+
* required: true
|
|
218
|
+
* content:
|
|
219
|
+
* application/json:
|
|
220
|
+
* schema:
|
|
221
|
+
* type: object
|
|
222
|
+
* required:
|
|
223
|
+
* - type
|
|
224
|
+
* - data
|
|
225
|
+
* properties:
|
|
226
|
+
* type:
|
|
227
|
+
* type: string
|
|
228
|
+
* minLength: 1
|
|
229
|
+
* maxLength: 100
|
|
230
|
+
* description: The type/category of the log entry
|
|
231
|
+
* data:
|
|
232
|
+
* description: Any data to be logged
|
|
233
|
+
* responses:
|
|
234
|
+
* 200:
|
|
235
|
+
* description: Successfully logged the data.
|
|
236
|
+
* 400:
|
|
237
|
+
* description: Invalid request data
|
|
238
|
+
* 401:
|
|
239
|
+
* description: Unauthorized
|
|
240
|
+
* 500:
|
|
241
|
+
* description: Internal server error
|
|
242
|
+
*/
|
|
243
|
+
app.post("/student/log", [
|
|
244
|
+
generalRateLimit,
|
|
245
|
+
body("type")
|
|
246
|
+
.isString()
|
|
247
|
+
.trim()
|
|
248
|
+
.isLength({ min: 1, max: 100 })
|
|
249
|
+
.withMessage("Type must be a string between 1-100 characters"),
|
|
250
|
+
body("data").exists().withMessage("Data field is required"),
|
|
251
|
+
handleValidationErrors,
|
|
252
|
+
requireAuth,
|
|
253
|
+
], async (req, res) => {
|
|
254
|
+
try {
|
|
255
|
+
const { type, data } = req.body;
|
|
256
|
+
const db = getDatabase(req.appId);
|
|
257
|
+
// Create log entry with timestamp and student ID
|
|
258
|
+
const logEntry = {
|
|
259
|
+
type,
|
|
260
|
+
data,
|
|
261
|
+
timestamp: new Date().toISOString(),
|
|
262
|
+
studentId: req.user.uid,
|
|
263
|
+
appId: req.appId,
|
|
264
|
+
};
|
|
265
|
+
const firestore = getFirestore();
|
|
266
|
+
await firestore
|
|
267
|
+
.doc(db.STUDENT.LOG.DOC(req.user.uid, dateId()))
|
|
268
|
+
.set(logEntry);
|
|
269
|
+
return sendSuccess(res, undefined, "Log entry created successfully");
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
console.error("Error creating log entry:", error);
|
|
273
|
+
return sendError(res, 500, "Failed to create log entry");
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
/**
|
|
277
|
+
* @openapi
|
|
278
|
+
* /assessment/checkCode:
|
|
279
|
+
* post:
|
|
280
|
+
* tags:
|
|
281
|
+
* - Session
|
|
282
|
+
* summary: Use to login by code. The code is used to identify the assessment.
|
|
283
|
+
* description: Checks if the provided assessment code is valid and retrieves session information for the student.
|
|
284
|
+
* requestBody:
|
|
285
|
+
* required: true
|
|
286
|
+
* content:
|
|
287
|
+
* application/json:
|
|
288
|
+
* schema:
|
|
289
|
+
* type: object
|
|
290
|
+
* properties:
|
|
291
|
+
* code:
|
|
292
|
+
* type: string
|
|
293
|
+
* description: The assessment code.
|
|
294
|
+
* identification:
|
|
295
|
+
* type: string
|
|
296
|
+
* description: Student identification.
|
|
297
|
+
* responses:
|
|
298
|
+
* 200:
|
|
299
|
+
* description: Successfully retrieved session information.
|
|
300
|
+
* 404:
|
|
301
|
+
* description: Assessment not found
|
|
302
|
+
* 500:
|
|
303
|
+
* description: Error creating session
|
|
304
|
+
*/
|
|
305
|
+
app.post("/assessment/checkCode", [
|
|
306
|
+
generalRateLimit,
|
|
307
|
+
body("code")
|
|
308
|
+
.isString()
|
|
309
|
+
.trim()
|
|
310
|
+
.isLength({ min: 1, max: 50 })
|
|
311
|
+
.withMessage("Code is required"),
|
|
312
|
+
body("identification")
|
|
313
|
+
.optional()
|
|
314
|
+
.isString()
|
|
315
|
+
.trim()
|
|
316
|
+
.isLength({ max: 100 }),
|
|
317
|
+
handleValidationErrors,
|
|
318
|
+
requireAuth,
|
|
319
|
+
], async (req, res) => {
|
|
320
|
+
try {
|
|
321
|
+
const { code, identification } = req.body;
|
|
322
|
+
const db = getDatabase(req.appId);
|
|
323
|
+
const assessmentInfo = await checkAssessmentCode(db, code.toUpperCase());
|
|
324
|
+
if (!assessmentInfo) {
|
|
325
|
+
return sendError(res, 404, "Assessment not found");
|
|
326
|
+
}
|
|
327
|
+
if (assessmentInfo.isDemo) {
|
|
328
|
+
const demoInfo = {
|
|
329
|
+
appId: req.appId,
|
|
330
|
+
code,
|
|
331
|
+
currentAssessmentId: assessmentInfo.assessmentId,
|
|
332
|
+
sessions: [
|
|
333
|
+
{
|
|
334
|
+
assessmentId: assessmentInfo.assessmentId,
|
|
335
|
+
assessmentName: assessmentInfo.name,
|
|
336
|
+
sessionState: "not_started",
|
|
337
|
+
packageId: assessmentInfo.packageId,
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
teacherId: assessmentInfo.teacherId || "general",
|
|
341
|
+
isDemo: true,
|
|
342
|
+
};
|
|
343
|
+
return sendSuccess(res, demoInfo);
|
|
344
|
+
}
|
|
345
|
+
const studentInfo = await specificImplementation.createSessionInfoForStudent({
|
|
346
|
+
userId: req.user.uid,
|
|
347
|
+
assessmentId: assessmentInfo.assessmentId,
|
|
348
|
+
identification,
|
|
349
|
+
metadata: {
|
|
350
|
+
isDemo: assessmentInfo.isDemo,
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
if (!studentInfo) {
|
|
354
|
+
return sendError(res, 500, "Error creating session");
|
|
355
|
+
}
|
|
356
|
+
return sendSuccess(res, studentInfo);
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
console.error("Error in assessment checkCode:", error);
|
|
360
|
+
return sendError(res, 500, "Failed to check assessment code");
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
/**
|
|
364
|
+
* @openapi
|
|
365
|
+
* /session/start:
|
|
366
|
+
* post:
|
|
367
|
+
* tags:
|
|
368
|
+
* - Session
|
|
369
|
+
* summary: Start a session
|
|
370
|
+
* description: Starts a session for a student with the given assessment ID and identification.
|
|
371
|
+
*/
|
|
372
|
+
app.post("/session/start", [
|
|
373
|
+
generalRateLimit,
|
|
374
|
+
body("assessmentId")
|
|
375
|
+
.isString()
|
|
376
|
+
.trim()
|
|
377
|
+
.isLength({ min: 1 })
|
|
378
|
+
.withMessage("Assessment ID is required"),
|
|
379
|
+
body("identification").optional().isString().trim(),
|
|
380
|
+
body("metadata").optional().isObject(),
|
|
381
|
+
handleValidationErrors,
|
|
382
|
+
requireAuth,
|
|
383
|
+
], async (req, res) => {
|
|
384
|
+
try {
|
|
385
|
+
const { metadata, assessmentId, identification } = req.body;
|
|
386
|
+
const db = getDatabase(req.appId);
|
|
387
|
+
const assessments = await getStartableAssessments(db);
|
|
388
|
+
const assessment = assessments.find((a) => a.assessmentId === assessmentId);
|
|
389
|
+
if (!assessment) {
|
|
390
|
+
return sendError(res, 404, "Assessment not found");
|
|
391
|
+
}
|
|
392
|
+
const validMetadata = metadata && typeof metadata === "object" ? metadata : undefined;
|
|
393
|
+
let sessionInfo = await specificImplementation.getSessionInfoForStudent(req.user.uid, assessmentId, identification);
|
|
394
|
+
const canStart = isStartable(assessment);
|
|
395
|
+
if (!sessionInfo && canStart) {
|
|
396
|
+
sessionInfo =
|
|
397
|
+
await specificImplementation.createSessionInfoForStudent({
|
|
398
|
+
userId: req.user.uid,
|
|
399
|
+
identification,
|
|
400
|
+
assessmentId: assessmentId,
|
|
401
|
+
metadata: validMetadata,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
if ((sessionInfo && canStart) || sessionInfo?.isDemo) {
|
|
405
|
+
return sendSuccess(res, { ...sessionInfo, userId: req.user.uid });
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
return sendSuccess(res, null);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
console.error("Error starting session:", error);
|
|
413
|
+
return sendError(res, 500, "Failed to start session");
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
/**
|
|
417
|
+
* @openapi
|
|
418
|
+
* /session/info:
|
|
419
|
+
* get:
|
|
420
|
+
* tags:
|
|
421
|
+
* - Session
|
|
422
|
+
* summary: Get session info
|
|
423
|
+
* description: Retrieves session information for the authenticated student.
|
|
424
|
+
*/
|
|
425
|
+
app.get("/session/info", [generalRateLimit, requireAuth], async (req, res) => {
|
|
426
|
+
try {
|
|
427
|
+
const assessmentId = getAssessmentId(req);
|
|
428
|
+
const identification = getName(req);
|
|
429
|
+
const sessionInfo = await specificImplementation.getSessionInfoForStudent(req.user.uid, assessmentId, identification);
|
|
430
|
+
if (sessionInfo) {
|
|
431
|
+
return sendSuccess(res, sessionInfo);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
return sendError(res, 404, "Session not found");
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
console.error("Error getting session info:", error);
|
|
439
|
+
return sendError(res, 500, "Failed to get session info");
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
/**
|
|
443
|
+
* @openapi
|
|
444
|
+
* /session/{assessmentId}/context:
|
|
445
|
+
* get:
|
|
446
|
+
* tags:
|
|
447
|
+
* - Session
|
|
448
|
+
* summary: Get session context
|
|
449
|
+
* description: Retrieves session context for a specific assessment.
|
|
450
|
+
*/
|
|
451
|
+
app.get("/session/:assessmentId/context", [
|
|
452
|
+
generalRateLimit,
|
|
453
|
+
param("assessmentId")
|
|
454
|
+
.isString()
|
|
455
|
+
.trim()
|
|
456
|
+
.isLength({ min: 1 })
|
|
457
|
+
.withMessage("Assessment ID is required"),
|
|
458
|
+
handleValidationErrors,
|
|
459
|
+
requireAuth,
|
|
460
|
+
], async (req, res) => {
|
|
461
|
+
try {
|
|
462
|
+
const { assessmentId } = req.params;
|
|
463
|
+
const db = getDatabase(req.appId);
|
|
464
|
+
const code = await specificImplementation.getCodeByUserId(req.user.uid, assessmentId);
|
|
465
|
+
const firestore = getFirestore();
|
|
466
|
+
const sessionRef = firestore.doc(db.STUDENT.SESSION.DOC(code, assessmentId));
|
|
467
|
+
const context = await sessionRef.get();
|
|
468
|
+
return sendSuccess(res, context.exists ? context.data() : null);
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
console.error("Error getting session context:", error);
|
|
472
|
+
return sendError(res, 500, "Failed to get session context");
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
/**
|
|
476
|
+
* @openapi
|
|
477
|
+
* /session/{assessmentId}/context:
|
|
478
|
+
* post:
|
|
479
|
+
* tags:
|
|
480
|
+
* - Session
|
|
481
|
+
* summary: Update session context
|
|
482
|
+
* description: Updates session context for a specific assessment.
|
|
483
|
+
*/
|
|
484
|
+
app.post("/session/:assessmentId/context", [
|
|
485
|
+
generalRateLimit,
|
|
486
|
+
param("assessmentId")
|
|
487
|
+
.isString()
|
|
488
|
+
.trim()
|
|
489
|
+
.isLength({ min: 1 })
|
|
490
|
+
.withMessage("Assessment ID is required"),
|
|
491
|
+
body("state").optional().isString(),
|
|
492
|
+
body("items").optional().isArray(),
|
|
493
|
+
handleValidationErrors,
|
|
494
|
+
requireAuth,
|
|
495
|
+
], async (req, res) => {
|
|
496
|
+
try {
|
|
497
|
+
const { assessmentId } = req.params;
|
|
498
|
+
const testContext = req.body;
|
|
499
|
+
const db = getDatabase(req.appId);
|
|
500
|
+
const code = await specificImplementation.getCodeByUserId(req.user.uid, assessmentId);
|
|
501
|
+
const cacheKey = `test-context-${req.appId}-${code}-${assessmentId}`;
|
|
502
|
+
let previousState = cache.get(cacheKey);
|
|
503
|
+
const firestore = getFirestore();
|
|
504
|
+
const sessionRef = firestore.doc(db.STUDENT.SESSION.DOC(code, assessmentId));
|
|
505
|
+
if (!previousState) {
|
|
506
|
+
const previousContext = await sessionRef.get();
|
|
507
|
+
if (previousContext.exists) {
|
|
508
|
+
previousState = previousContext.data()
|
|
509
|
+
?.state;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
const batch = firestore.batch();
|
|
513
|
+
if (previousState !== testContext.state) {
|
|
514
|
+
cache.set(cacheKey, testContext.state, 60 * 60 * 1000); // 1 hour
|
|
515
|
+
const teacherId = await getTeacherIdByCode(db, code);
|
|
516
|
+
if (!teacherId) {
|
|
517
|
+
return sendError(res, 404, "Teacher not found for this code");
|
|
518
|
+
}
|
|
519
|
+
await Promise.all([
|
|
520
|
+
specificImplementation.testContextToTeacher(code, assessmentId, testContext, batch),
|
|
521
|
+
updateStudentSessionState(db, code, assessmentId, testContext?.state ?? "not_started", batch),
|
|
522
|
+
specificImplementation.updateItemStats(teacherId, assessmentId, code, testContext.items, "teacher", batch),
|
|
523
|
+
]);
|
|
524
|
+
}
|
|
525
|
+
batch.set(sessionRef, testContext);
|
|
526
|
+
await batch.commit();
|
|
527
|
+
return sendSuccess(res, undefined, "Context updated successfully");
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
console.error("Error updating session context:", error);
|
|
531
|
+
return sendError(res, 500, "Failed to update session context");
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
/**
|
|
535
|
+
* @openapi
|
|
536
|
+
* /session/{assessmentId}/sessionState:
|
|
537
|
+
* post:
|
|
538
|
+
* tags:
|
|
539
|
+
* - Session
|
|
540
|
+
* summary: Update session state
|
|
541
|
+
* description: Updates the session state for a specific session.
|
|
542
|
+
*/
|
|
543
|
+
app.post("/session/:assessmentId/sessionState", [
|
|
544
|
+
generalRateLimit,
|
|
545
|
+
param("assessmentId")
|
|
546
|
+
.isString()
|
|
547
|
+
.trim()
|
|
548
|
+
.isLength({ min: 1 })
|
|
549
|
+
.withMessage("Assessment ID is required"),
|
|
550
|
+
body("sessionState")
|
|
551
|
+
.isString()
|
|
552
|
+
.trim()
|
|
553
|
+
.isLength({ min: 1 })
|
|
554
|
+
.withMessage("Session state is required"),
|
|
555
|
+
handleValidationErrors,
|
|
556
|
+
requireAuth,
|
|
557
|
+
], async (req, res) => {
|
|
558
|
+
try {
|
|
559
|
+
const { assessmentId } = req.params;
|
|
560
|
+
const { sessionState } = req.body;
|
|
561
|
+
const db = getDatabase(req.appId);
|
|
562
|
+
const code = await specificImplementation.getCodeByUserId(req.user.uid, assessmentId);
|
|
563
|
+
const firestore = getFirestore();
|
|
564
|
+
const batch = firestore.batch();
|
|
565
|
+
await updateStudentSessionState(db, code, assessmentId, sessionState, batch);
|
|
566
|
+
const teacherId = await getTeacherIdByCode(db, code);
|
|
567
|
+
if (!teacherId) {
|
|
568
|
+
return sendError(res, 404, "Teacher not found for this code");
|
|
569
|
+
}
|
|
570
|
+
const studentSessions = await getPlannedStudent(db, teacherId, code);
|
|
571
|
+
const session = studentSessions.sessions.find((s) => s.assessmentId === assessmentId);
|
|
572
|
+
if (session) {
|
|
573
|
+
await specificImplementation.updatePlannedSession(teacherId, code, { ...session, sessionState }, batch);
|
|
574
|
+
}
|
|
575
|
+
await batch.commit();
|
|
576
|
+
return sendSuccess(res, undefined, "Session state updated successfully");
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
console.error("Error updating session state:", error);
|
|
580
|
+
return sendError(res, 500, "Failed to update session state");
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
/**
|
|
584
|
+
* @openapi
|
|
585
|
+
* /session/{assessmentId}/log:
|
|
586
|
+
* post:
|
|
587
|
+
* tags:
|
|
588
|
+
* - Session
|
|
589
|
+
* summary: Log session data
|
|
590
|
+
* description: Logs session data for a specific assessment.
|
|
591
|
+
*/
|
|
592
|
+
app.post("/session/:assessmentId/log", [
|
|
593
|
+
generalRateLimit,
|
|
594
|
+
param("assessmentId")
|
|
595
|
+
.isString()
|
|
596
|
+
.trim()
|
|
597
|
+
.isLength({ min: 1 })
|
|
598
|
+
.withMessage("Assessment ID is required"),
|
|
599
|
+
body("logData").isObject().withMessage("Log data must be an object"),
|
|
600
|
+
handleValidationErrors,
|
|
601
|
+
requireAuth,
|
|
602
|
+
], async (req, res) => {
|
|
603
|
+
try {
|
|
604
|
+
const { assessmentId } = req.params;
|
|
605
|
+
const db = getDatabase(req.appId);
|
|
606
|
+
const code = await specificImplementation.getCodeByUserId(req.user.uid, assessmentId);
|
|
607
|
+
const firestore = getFirestore();
|
|
608
|
+
const sessionRef = firestore.doc(db.STUDENT.SESSION.LOG(code, assessmentId, dateId()));
|
|
609
|
+
await sessionRef.set({
|
|
610
|
+
...req.body,
|
|
611
|
+
timestamp: new Date().toISOString(),
|
|
612
|
+
userId: req.user.uid,
|
|
613
|
+
});
|
|
614
|
+
return sendSuccess(res, undefined, "Log data saved successfully");
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
console.error("Error logging session data:", error);
|
|
618
|
+
return sendError(res, 500, "Failed to log session data");
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
//# sourceMappingURL=qti-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-data.js","sourceRoot":"","sources":["../../src/api/qti-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-resources.d.ts","sourceRoot":"","sources":["../../src/api/qti-resources.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAmC,MAAM,SAAS,CAAC;AASnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAqDtD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,sBAAsB,GAAE,oBAA+C,QAmXxE"}
|