@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,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"}
|