@vue-skuilder/express 0.1.11-0 → 0.1.11-12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-factory.d.ts +22 -0
- package/dist/app-factory.d.ts.map +1 -0
- package/dist/app-factory.js +250 -0
- package/dist/app-factory.js.map +1 -0
- package/dist/app.d.ts +1 -5
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +39 -193
- package/dist/app.js.map +1 -1
- package/dist/assets/classroomDesignDoc.js +24 -0
- package/dist/assets/courseValidateDocUpdate.js +56 -0
- package/dist/assets/get-tagsDesignDoc.json +9 -0
- package/dist/attachment-preprocessing/index.d.ts +1 -1
- package/dist/attachment-preprocessing/index.d.ts.map +1 -1
- package/dist/attachment-preprocessing/index.js +94 -27
- package/dist/attachment-preprocessing/index.js.map +1 -1
- package/dist/client-requests/classroom-requests.d.ts.map +1 -1
- package/dist/client-requests/classroom-requests.js +2 -2
- package/dist/client-requests/classroom-requests.js.map +1 -1
- package/dist/client-requests/course-requests.js +5 -5
- package/dist/client-requests/course-requests.js.map +1 -1
- package/dist/couchdb/authentication.d.ts +1 -1
- package/dist/couchdb/authentication.d.ts.map +1 -1
- package/dist/couchdb/authentication.js +4 -4
- package/dist/couchdb/authentication.js.map +1 -1
- package/dist/couchdb/index.d.ts +4 -3
- package/dist/couchdb/index.d.ts.map +1 -1
- package/dist/couchdb/index.js +32 -27
- package/dist/couchdb/index.js.map +1 -1
- package/dist/design-docs.d.ts.map +1 -1
- package/dist/design-docs.js +9 -4
- package/dist/design-docs.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/env.d.ts +2 -1
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/env.js +3 -21
- package/dist/utils/env.js.map +1 -1
- package/package.json +17 -7
- package/src/app-factory.ts +307 -0
- package/src/app.ts +44 -240
- package/src/attachment-preprocessing/index.ts +108 -36
- package/src/client-requests/classroom-requests.ts +3 -2
- package/src/client-requests/course-requests.ts +5 -5
- package/src/couchdb/authentication.ts +5 -5
- package/src/couchdb/index.ts +54 -37
- package/src/design-docs.ts +10 -4
- package/src/index.ts +23 -0
- package/src/types.ts +65 -0
- package/src/utils/env.ts +5 -26
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ServerRequest } from '@vue-skuilder/common';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import type { ExpressServerConfig, EnvironmentConfig } from './types.js';
|
|
4
|
+
export interface VueClientRequest extends express.Request {
|
|
5
|
+
body: ServerRequest;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Configuration options for creating an Express app.
|
|
9
|
+
* Can be provided either as ExpressServerConfig (programmatic) or EnvironmentConfig (env vars).
|
|
10
|
+
*/
|
|
11
|
+
export type AppConfig = ExpressServerConfig | EnvironmentConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Create and configure Express application with all routes and middleware.
|
|
14
|
+
* This is the shared logic used by both standalone and programmatic modes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createExpressApp(config: AppConfig): express.Application;
|
|
17
|
+
/**
|
|
18
|
+
* Initialize background services and database connections.
|
|
19
|
+
* This should be called after the server starts listening.
|
|
20
|
+
*/
|
|
21
|
+
export declare function initializeServices(config: AppConfig): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=app-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-factory.d.ts","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAK9B,OAAO,OAAO,MAAM,SAAS,CAAC;AAmB9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,gBAAiB,SAAQ,OAAO,CAAC,OAAO;IACvD,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAwBhE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CA6LvE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CzE"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { initializeDataLayer } from '@vue-skuilder/db';
|
|
2
|
+
import { ServerRequestType as RequestEnum, prepareNote55, } from '@vue-skuilder/common';
|
|
3
|
+
import { CourseLookup } from '@vue-skuilder/db';
|
|
4
|
+
import cookieParser from 'cookie-parser';
|
|
5
|
+
import cors from 'cors';
|
|
6
|
+
import express from 'express';
|
|
7
|
+
import morgan from 'morgan';
|
|
8
|
+
import PostProcess from './attachment-preprocessing/index.js';
|
|
9
|
+
import { ClassroomCreationQueue, ClassroomJoinQueue, ClassroomLeaveQueue, } from './client-requests/classroom-requests.js';
|
|
10
|
+
import { CourseCreationQueue, initCourseDBDesignDocInsert, } from './client-requests/course-requests.js';
|
|
11
|
+
import { packCourse } from './client-requests/pack-requests.js';
|
|
12
|
+
import { requestIsAuthenticated } from './couchdb/authentication.js';
|
|
13
|
+
import { getCouchDB, initializeCouchDB, useOrCreateCourseDB, useOrCreateDB } from './couchdb/index.js';
|
|
14
|
+
import { classroomDbDesignDoc } from './design-docs.js';
|
|
15
|
+
import logger from './logger.js';
|
|
16
|
+
import logsRouter from './routes/logs.js';
|
|
17
|
+
/**
|
|
18
|
+
* Type guard to determine if config is ExpressServerConfig (programmatic usage)
|
|
19
|
+
*/
|
|
20
|
+
function isExpressServerConfig(config) {
|
|
21
|
+
return 'couchdb' in config && typeof config.couchdb === 'object';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Convert ExpressServerConfig to environment-style config for internal usage
|
|
25
|
+
*/
|
|
26
|
+
function convertToEnvConfig(config) {
|
|
27
|
+
return {
|
|
28
|
+
COUCHDB_SERVER: config.couchdb.server,
|
|
29
|
+
COUCHDB_PROTOCOL: config.couchdb.protocol,
|
|
30
|
+
COUCHDB_ADMIN: config.couchdb.username,
|
|
31
|
+
COUCHDB_PASSWORD: config.couchdb.password,
|
|
32
|
+
VERSION: config.version,
|
|
33
|
+
NODE_ENV: config.nodeEnv || 'development',
|
|
34
|
+
COURSE_IDS: config.courseIDs || [],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create and configure Express application with all routes and middleware.
|
|
39
|
+
* This is the shared logic used by both standalone and programmatic modes.
|
|
40
|
+
*/
|
|
41
|
+
export function createExpressApp(config) {
|
|
42
|
+
const app = express();
|
|
43
|
+
// Normalize config to environment format for internal usage
|
|
44
|
+
const envConfig = isExpressServerConfig(config)
|
|
45
|
+
? convertToEnvConfig(config)
|
|
46
|
+
: config;
|
|
47
|
+
// Initialize CouchDB connection
|
|
48
|
+
initializeCouchDB(envConfig);
|
|
49
|
+
// Configure CORS - use config if available, otherwise defaults
|
|
50
|
+
const corsOptions = isExpressServerConfig(config) && config.cors
|
|
51
|
+
? config.cors
|
|
52
|
+
: { credentials: true, origin: true };
|
|
53
|
+
// Middleware setup
|
|
54
|
+
app.use(cookieParser());
|
|
55
|
+
app.use(express.json());
|
|
56
|
+
app.use(cors(corsOptions));
|
|
57
|
+
app.use(morgan('combined', {
|
|
58
|
+
stream: { write: (message) => logger.info(message.trim()) },
|
|
59
|
+
}));
|
|
60
|
+
app.use('/logs', logsRouter);
|
|
61
|
+
// Routes
|
|
62
|
+
app.get('/courses', (_req, res) => {
|
|
63
|
+
void (async () => {
|
|
64
|
+
try {
|
|
65
|
+
const courses = await CourseLookup.allCourseWare();
|
|
66
|
+
res.send(courses.map((c) => `${c._id} - ${c.name}`));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
logger.error('Error fetching courses:', error);
|
|
70
|
+
res.status(500).send('Failed to fetch courses');
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
});
|
|
74
|
+
app.get('/course/:courseID/config', (req, res) => {
|
|
75
|
+
void (async () => {
|
|
76
|
+
try {
|
|
77
|
+
const courseDB = await useOrCreateCourseDB(req.params.courseID);
|
|
78
|
+
const cfg = await courseDB.get('CourseConfig'); // [ ] pull courseConfig docName into global const
|
|
79
|
+
res.json(cfg);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
logger.error('Error fetching course config:', error);
|
|
83
|
+
res.status(500).send('Failed to fetch course config');
|
|
84
|
+
}
|
|
85
|
+
})();
|
|
86
|
+
});
|
|
87
|
+
app.delete('/course/:courseID', (req, res) => {
|
|
88
|
+
void (async () => {
|
|
89
|
+
try {
|
|
90
|
+
logger.info(`Delete request made on course ${req.params.courseID}...`);
|
|
91
|
+
const auth = await requestIsAuthenticated(req);
|
|
92
|
+
if (auth) {
|
|
93
|
+
logger.info(` Authenticated delete request made...`);
|
|
94
|
+
const dbResp = await getCouchDB().db.destroy(`coursedb-${req.params.courseID}`);
|
|
95
|
+
if (!dbResp.ok) {
|
|
96
|
+
res.json({ success: false, error: dbResp });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const delResp = await CourseLookup.delete(req.params.courseID);
|
|
100
|
+
if (delResp.ok) {
|
|
101
|
+
res.json({ success: true });
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
res.json({ success: false, error: delResp });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
res.json({ success: false, error: 'Not authenticated' });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
logger.error('Error deleting course:', error);
|
|
113
|
+
res.status(500).json({ success: false, error: 'Failed to delete course' });
|
|
114
|
+
}
|
|
115
|
+
})();
|
|
116
|
+
});
|
|
117
|
+
async function postHandler(req, res) {
|
|
118
|
+
const auth = await requestIsAuthenticated(req);
|
|
119
|
+
if (auth) {
|
|
120
|
+
const body = req.body;
|
|
121
|
+
logger.info(`Authorized ${body.type ? body.type : '[unspecified request type]'} request made...`);
|
|
122
|
+
if (body.type === RequestEnum.CREATE_CLASSROOM) {
|
|
123
|
+
const id = ClassroomCreationQueue.addRequest(body.data);
|
|
124
|
+
body.response = await ClassroomCreationQueue.getResult(id);
|
|
125
|
+
res.json(body.response);
|
|
126
|
+
}
|
|
127
|
+
else if (body.type === RequestEnum.DELETE_CLASSROOM) {
|
|
128
|
+
// [ ] add delete classroom request
|
|
129
|
+
}
|
|
130
|
+
else if (body.type === RequestEnum.JOIN_CLASSROOM) {
|
|
131
|
+
const id = ClassroomJoinQueue.addRequest(body.data);
|
|
132
|
+
body.response = await ClassroomJoinQueue.getResult(id);
|
|
133
|
+
res.json(body.response);
|
|
134
|
+
}
|
|
135
|
+
else if (body.type === RequestEnum.LEAVE_CLASSROOM) {
|
|
136
|
+
const id = ClassroomLeaveQueue.addRequest({
|
|
137
|
+
username: req.body.user,
|
|
138
|
+
...body.data,
|
|
139
|
+
});
|
|
140
|
+
body.response = await ClassroomLeaveQueue.getResult(id);
|
|
141
|
+
res.json(body.response);
|
|
142
|
+
}
|
|
143
|
+
else if (body.type === RequestEnum.CREATE_COURSE) {
|
|
144
|
+
const id = CourseCreationQueue.addRequest(body.data);
|
|
145
|
+
body.response = await CourseCreationQueue.getResult(id);
|
|
146
|
+
res.json(body.response);
|
|
147
|
+
}
|
|
148
|
+
else if (body.type === RequestEnum.ADD_COURSE_DATA) {
|
|
149
|
+
const payload = prepareNote55(body.data.courseID, body.data.codeCourse, body.data.shape, body.data.data, body.data.author, body.data.tags, body.data.uploads);
|
|
150
|
+
getCouchDB().use(`coursedb-${body.data.courseID}`)
|
|
151
|
+
.insert(payload)
|
|
152
|
+
.then((r) => {
|
|
153
|
+
logger.info(`\t\t\tCouchDB insert result: ${JSON.stringify(r)}`);
|
|
154
|
+
res.json(r);
|
|
155
|
+
})
|
|
156
|
+
.catch((e) => {
|
|
157
|
+
logger.info(`\t\t\tCouchDB insert error: ${JSON.stringify(e)}`);
|
|
158
|
+
res.json(e);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else if (body.type === RequestEnum.PACK_COURSE) {
|
|
162
|
+
if (envConfig.NODE_ENV !== 'studio') {
|
|
163
|
+
logger.info(`\tPACK_COURSE request received in production mode, but this is not supported!`);
|
|
164
|
+
res.status(400);
|
|
165
|
+
res.statusMessage = 'Packing courses is not supported in production mode.';
|
|
166
|
+
res.send();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
body.response = await packCourse({
|
|
170
|
+
courseId: body.courseId,
|
|
171
|
+
outputPath: body.outputPath
|
|
172
|
+
});
|
|
173
|
+
res.json(body.response);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
logger.info(`\tREQUEST UNAUTHORIZED!`);
|
|
178
|
+
res.status(401);
|
|
179
|
+
res.statusMessage = 'Unauthorized';
|
|
180
|
+
res.send();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
app.post('/', (req, res) => {
|
|
184
|
+
void postHandler(req, res);
|
|
185
|
+
});
|
|
186
|
+
app.get('/version', (_req, res) => {
|
|
187
|
+
res.send(envConfig.VERSION);
|
|
188
|
+
});
|
|
189
|
+
app.get('/', (_req, res) => {
|
|
190
|
+
let status = `Express service is running.\nVersion: ${envConfig.VERSION}\n`;
|
|
191
|
+
getCouchDB().session()
|
|
192
|
+
.then((s) => {
|
|
193
|
+
if (s.ok) {
|
|
194
|
+
status += 'Couchdb is running.\n';
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
status += 'Couchdb session is NOT ok.\n';
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
.catch((e) => {
|
|
201
|
+
status += `Problems in the couch session! ${JSON.stringify(e)}`;
|
|
202
|
+
})
|
|
203
|
+
.finally(() => {
|
|
204
|
+
res.send(status);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
return app;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Initialize background services and database connections.
|
|
211
|
+
* This should be called after the server starts listening.
|
|
212
|
+
*/
|
|
213
|
+
export async function initializeServices(config) {
|
|
214
|
+
// Initialize data layer first
|
|
215
|
+
const envConfig = isExpressServerConfig(config)
|
|
216
|
+
? convertToEnvConfig(config)
|
|
217
|
+
: config;
|
|
218
|
+
await initializeDataLayer({
|
|
219
|
+
type: 'couch',
|
|
220
|
+
options: {
|
|
221
|
+
COUCHDB_PASSWORD: envConfig.COUCHDB_PASSWORD,
|
|
222
|
+
COUCHDB_USERNAME: envConfig.COUCHDB_ADMIN,
|
|
223
|
+
COUCHDB_SERVER_PROTOCOL: envConfig.COUCHDB_PROTOCOL,
|
|
224
|
+
COUCHDB_SERVER_URL: envConfig.COUCHDB_SERVER,
|
|
225
|
+
},
|
|
226
|
+
}).catch((e) => {
|
|
227
|
+
logger.error('Error initializing data layer:', e);
|
|
228
|
+
// In programmatic mode, we shouldn't exit the process, but let the error propagate
|
|
229
|
+
throw e;
|
|
230
|
+
});
|
|
231
|
+
try {
|
|
232
|
+
// start the change-listener that does post-processing on user
|
|
233
|
+
// media uploads
|
|
234
|
+
void PostProcess();
|
|
235
|
+
void initCourseDBDesignDocInsert();
|
|
236
|
+
void useOrCreateDB('classdb-lookup');
|
|
237
|
+
try {
|
|
238
|
+
await (await useOrCreateDB('coursedb')).insert({
|
|
239
|
+
validate_doc_update: classroomDbDesignDoc,
|
|
240
|
+
}, '_design/_auth');
|
|
241
|
+
}
|
|
242
|
+
catch (e) {
|
|
243
|
+
logger.info(`Error: ${e}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch (e) {
|
|
247
|
+
logger.info(`Error: ${JSON.stringify(e)}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=app-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-factory.js","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"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"}
|
package/dist/app.d.ts
CHANGED
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":""}
|
package/dist/app.js
CHANGED
|
@@ -1,209 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CourseLookup } from '@vue-skuilder/db';
|
|
3
|
-
import cookieParser from 'cookie-parser';
|
|
4
|
-
import cors from 'cors';
|
|
5
|
-
import express from 'express';
|
|
6
|
-
import morgan from 'morgan';
|
|
7
|
-
import PostProcess from './attachment-preprocessing/index.js';
|
|
8
|
-
import { ClassroomCreationQueue, ClassroomJoinQueue, ClassroomLeaveQueue, } from './client-requests/classroom-requests.js';
|
|
9
|
-
import { CourseCreationQueue, initCourseDBDesignDocInsert, } from './client-requests/course-requests.js';
|
|
10
|
-
import { packCourse } from './client-requests/pack-requests.js';
|
|
11
|
-
import { requestIsAuthenticated } from './couchdb/authentication.js';
|
|
12
|
-
import CouchDB, { useOrCreateCourseDB, useOrCreateDB, } from './couchdb/index.js';
|
|
1
|
+
import { createExpressApp, initializeServices } from './app-factory.js';
|
|
13
2
|
import logger from './logger.js';
|
|
14
|
-
import logsRouter from './routes/logs.js';
|
|
15
3
|
import ENV from './utils/env.js';
|
|
4
|
+
import dotenv from 'dotenv';
|
|
5
|
+
import { initializeCouchDB } from './couchdb/index.js';
|
|
6
|
+
import { initializeDataLayer } from '@vue-skuilder/db';
|
|
7
|
+
dotenv.config({
|
|
8
|
+
path: process.argv && process.argv.length == 3
|
|
9
|
+
? process.argv[2]
|
|
10
|
+
: '.env.development',
|
|
11
|
+
});
|
|
12
|
+
// Now that dotenv is configured, we can validate the environment
|
|
13
|
+
const requiredVars = ['COUCHDB_SERVER', 'COUCHDB_PROTOCOL', 'COUCHDB_ADMIN', 'COUCHDB_PASSWORD', 'VERSION', 'NODE_ENV'];
|
|
14
|
+
const missingVars = requiredVars.filter(v => !process.env[v]);
|
|
15
|
+
if (missingVars.length > 0) {
|
|
16
|
+
missingVars.forEach(v => logger.error(`${v} not defined in environment`));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
// Initialize CouchDB connection
|
|
20
|
+
initializeCouchDB(ENV);
|
|
21
|
+
initializeDataLayer({
|
|
22
|
+
type: 'couch',
|
|
23
|
+
options: {
|
|
24
|
+
COUCHDB_PASSWORD: ENV.COUCHDB_PASSWORD,
|
|
25
|
+
COUCHDB_USERNAME: ENV.COUCHDB_ADMIN,
|
|
26
|
+
COUCHDB_SERVER_PROTOCOL: ENV.COUCHDB_PROTOCOL,
|
|
27
|
+
COUCHDB_SERVER_URL: ENV.COUCHDB_SERVER,
|
|
28
|
+
},
|
|
29
|
+
}).catch((e) => {
|
|
30
|
+
logger.error('Error initializing data layer:', e);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
});
|
|
16
33
|
process.on('unhandledRejection', (reason, promise) => {
|
|
17
34
|
logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
18
35
|
});
|
|
19
36
|
logger.info(`Express app running version: ${ENV.VERSION}`);
|
|
20
37
|
const port = 3000;
|
|
21
|
-
import { classroomDbDesignDoc } from './design-docs.js';
|
|
22
|
-
const app = express();
|
|
23
|
-
app.use(cookieParser());
|
|
24
|
-
app.use(express.json());
|
|
25
|
-
app.use(cors({
|
|
26
|
-
credentials: true,
|
|
27
|
-
origin: true,
|
|
28
|
-
}));
|
|
29
|
-
app.use(morgan('combined', {
|
|
30
|
-
stream: { write: (message) => logger.info(message.trim()) },
|
|
31
|
-
}));
|
|
32
|
-
app.use('/logs', logsRouter);
|
|
33
|
-
app.get('/courses', (_req, res) => {
|
|
34
|
-
void (async () => {
|
|
35
|
-
try {
|
|
36
|
-
const courses = await CourseLookup.allCourseWare();
|
|
37
|
-
res.send(courses.map((c) => `${c._id} - ${c.name}`));
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
logger.error('Error fetching courses:', error);
|
|
41
|
-
res.status(500).send('Failed to fetch courses');
|
|
42
|
-
}
|
|
43
|
-
})();
|
|
44
|
-
});
|
|
45
|
-
app.get('/course/:courseID/config', (req, res) => {
|
|
46
|
-
void (async () => {
|
|
47
|
-
try {
|
|
48
|
-
const courseDB = await useOrCreateCourseDB(req.params.courseID);
|
|
49
|
-
const cfg = await courseDB.get('CourseConfig'); // [ ] pull courseConfig docName into global const
|
|
50
|
-
res.json(cfg);
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
logger.error('Error fetching course config:', error);
|
|
54
|
-
res.status(500).send('Failed to fetch course config');
|
|
55
|
-
}
|
|
56
|
-
})();
|
|
57
|
-
});
|
|
58
|
-
app.delete('/course/:courseID', (req, res) => {
|
|
59
|
-
void (async () => {
|
|
60
|
-
try {
|
|
61
|
-
logger.info(`Delete request made on course ${req.params.courseID}...`);
|
|
62
|
-
const auth = await requestIsAuthenticated(req);
|
|
63
|
-
if (auth) {
|
|
64
|
-
logger.info(`\tAuthenticated delete request made...`);
|
|
65
|
-
const dbResp = await CouchDB.db.destroy(`coursedb-${req.params.courseID}`);
|
|
66
|
-
if (!dbResp.ok) {
|
|
67
|
-
res.json({ success: false, error: dbResp });
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const delResp = await CourseLookup.delete(req.params.courseID);
|
|
71
|
-
if (delResp.ok) {
|
|
72
|
-
res.json({ success: true });
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
res.json({ success: false, error: delResp });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
res.json({ success: false, error: 'Not authenticated' });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
logger.error('Error deleting course:', error);
|
|
84
|
-
res.status(500).json({ success: false, error: 'Failed to delete course' });
|
|
85
|
-
}
|
|
86
|
-
})();
|
|
87
|
-
});
|
|
88
|
-
async function postHandler(req, res) {
|
|
89
|
-
const auth = await requestIsAuthenticated(req);
|
|
90
|
-
if (auth) {
|
|
91
|
-
const body = req.body;
|
|
92
|
-
logger.info(`Authorized ${body.type ? body.type : '[unspecified request type]'} request made...`);
|
|
93
|
-
if (body.type === RequestEnum.CREATE_CLASSROOM) {
|
|
94
|
-
const id = ClassroomCreationQueue.addRequest(body.data);
|
|
95
|
-
body.response = await ClassroomCreationQueue.getResult(id);
|
|
96
|
-
res.json(body.response);
|
|
97
|
-
}
|
|
98
|
-
else if (body.type === RequestEnum.DELETE_CLASSROOM) {
|
|
99
|
-
// [ ] add delete classroom request
|
|
100
|
-
}
|
|
101
|
-
else if (body.type === RequestEnum.JOIN_CLASSROOM) {
|
|
102
|
-
const id = ClassroomJoinQueue.addRequest(body.data);
|
|
103
|
-
body.response = await ClassroomJoinQueue.getResult(id);
|
|
104
|
-
res.json(body.response);
|
|
105
|
-
}
|
|
106
|
-
else if (body.type === RequestEnum.LEAVE_CLASSROOM) {
|
|
107
|
-
const id = ClassroomLeaveQueue.addRequest({
|
|
108
|
-
username: req.body.user,
|
|
109
|
-
...body.data,
|
|
110
|
-
});
|
|
111
|
-
body.response = await ClassroomLeaveQueue.getResult(id);
|
|
112
|
-
res.json(body.response);
|
|
113
|
-
}
|
|
114
|
-
else if (body.type === RequestEnum.CREATE_COURSE) {
|
|
115
|
-
const id = CourseCreationQueue.addRequest(body.data);
|
|
116
|
-
body.response = await CourseCreationQueue.getResult(id);
|
|
117
|
-
res.json(body.response);
|
|
118
|
-
}
|
|
119
|
-
else if (body.type === RequestEnum.ADD_COURSE_DATA) {
|
|
120
|
-
const payload = prepareNote55(body.data.courseID, body.data.codeCourse, body.data.shape, body.data.data, body.data.author, body.data.tags, body.data.uploads);
|
|
121
|
-
CouchDB.use(`coursedb-${body.data.courseID}`)
|
|
122
|
-
.insert(payload)
|
|
123
|
-
.then((r) => {
|
|
124
|
-
logger.info(`\t\t\tCouchDB insert result: ${JSON.stringify(r)}`);
|
|
125
|
-
res.json(r);
|
|
126
|
-
})
|
|
127
|
-
.catch((e) => {
|
|
128
|
-
logger.info(`\t\t\tCouchDB insert error: ${JSON.stringify(e)}`);
|
|
129
|
-
res.json(e);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
else if (body.type === RequestEnum.PACK_COURSE) {
|
|
133
|
-
if (process.env.NODE_ENV !== 'studio') {
|
|
134
|
-
logger.info(`\tPACK_COURSE request received in production mode, but this is not supported!`);
|
|
135
|
-
res.status(400);
|
|
136
|
-
res.statusMessage = 'Packing courses is not supported in production mode.';
|
|
137
|
-
res.send();
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
body.response = await packCourse({
|
|
141
|
-
courseId: body.courseId,
|
|
142
|
-
outputPath: body.outputPath
|
|
143
|
-
});
|
|
144
|
-
res.json(body.response);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
logger.info(`\tREQUEST UNAUTHORIZED!`);
|
|
149
|
-
res.status(401);
|
|
150
|
-
res.statusMessage = 'Unauthorized';
|
|
151
|
-
res.send();
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
app.post('/', (req, res) => {
|
|
155
|
-
void postHandler(req, res);
|
|
156
|
-
});
|
|
157
|
-
app.get('/version', (_req, res) => {
|
|
158
|
-
res.send(ENV.VERSION);
|
|
159
|
-
});
|
|
160
|
-
app.get('/', (_req, res) => {
|
|
161
|
-
let status = `Express service is running.\nVersion: ${ENV.VERSION}\n`;
|
|
162
|
-
CouchDB.session()
|
|
163
|
-
.then((s) => {
|
|
164
|
-
if (s.ok) {
|
|
165
|
-
status += 'Couchdb is running.\n';
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
status += 'Couchdb session is NOT ok.\n';
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
.catch((e) => {
|
|
172
|
-
status += `Problems in the couch session! ${JSON.stringify(e)}`;
|
|
173
|
-
})
|
|
174
|
-
.finally(() => {
|
|
175
|
-
res.send(status);
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
38
|
let listening = false;
|
|
39
|
+
// Use the factory with environment config
|
|
40
|
+
const app = createExpressApp(ENV);
|
|
179
41
|
app.listen(port, () => {
|
|
180
42
|
listening = true;
|
|
181
43
|
logger.info(`Express app listening on port ${port}!`);
|
|
182
44
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
});
|
|
186
|
-
async function init() {
|
|
45
|
+
// Initialize services after startup
|
|
46
|
+
const init = async () => {
|
|
187
47
|
while (!listening) {
|
|
188
48
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
189
49
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
void useOrCreateDB('classdb-lookup');
|
|
196
|
-
try {
|
|
197
|
-
await (await useOrCreateDB('coursedb')).insert({
|
|
198
|
-
validate_doc_update: classroomDbDesignDoc,
|
|
199
|
-
}, '_design/_auth');
|
|
200
|
-
}
|
|
201
|
-
catch (e) {
|
|
202
|
-
logger.info(`Error: ${e}`);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
catch (e) {
|
|
206
|
-
logger.info(`Error: ${JSON.stringify(e)}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
50
|
+
await initializeServices(ENV);
|
|
51
|
+
};
|
|
52
|
+
init().catch((e) => {
|
|
53
|
+
logger.error(`Error initializing app: ${JSON.stringify(e)}`);
|
|
54
|
+
});
|
|
209
55
|
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,GAAG,MAAM,gBAAgB,CAAC;AACjC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,CAAC,MAAM,CAAC;IACZ,IAAI,EACF,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC;QACtC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjB,CAAC,CAAC,kBAAkB;CACzB,CAAC,CAAC;AAEH,iEAAiE;AACjE,MAAM,YAAY,GAAG,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AACxH,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IACzB,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,gCAAgC;AAChC,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAEvB,mBAAmB,CAAC;IAClB,IAAI,EAAE,OAAO;IACb,OAAO,EAAE;QACP,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,gBAAgB,EAAE,GAAG,CAAC,aAAa;QACnC,uBAAuB,EAAE,GAAG,CAAC,gBAAgB;QAC7C,kBAAkB,EAAE,GAAG,CAAC,cAAc;KACvC;CACF,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACb,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IACnD,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CAAC,gCAAgC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AAE3D,MAAM,IAAI,GAAG,IAAI,CAAC;AAClB,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,0CAA0C;AAC1C,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAElC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,SAAS,GAAG,IAAI,CAAC;IACjB,MAAM,CAAC,IAAI,CAAC,iCAAiC,IAAI,GAAG,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH,oCAAoC;AACpC,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;IACrC,OAAO,CAAC,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,MAAM,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function (newDoc, oldDoc, userCtx, secObj) {
|
|
2
|
+
// from https://github.com/iriscouch/manage_couchdb/blob/master/js/validate_doc_update.js
|
|
3
|
+
|
|
4
|
+
var ddoc = this;
|
|
5
|
+
|
|
6
|
+
secObj.admins = secObj.admins || {};
|
|
7
|
+
secObj.admins.names = secObj.admins.names || [];
|
|
8
|
+
secObj.admins.roles = secObj.admins.roles || [];
|
|
9
|
+
|
|
10
|
+
var IS_DB_ADMIN = false;
|
|
11
|
+
if (~userCtx.roles.indexOf('_admin'))
|
|
12
|
+
IS_DB_ADMIN = true;
|
|
13
|
+
if (~secObj.admins.names.indexOf(userCtx.name))
|
|
14
|
+
IS_DB_ADMIN = true;
|
|
15
|
+
for (var i = 0; i < userCtx.roles; i++)
|
|
16
|
+
if (~secObj.admins.roles.indexOf(userCtx.roles[i]))
|
|
17
|
+
IS_DB_ADMIN = true;
|
|
18
|
+
|
|
19
|
+
if (ddoc.access && ddoc.access.read_only)
|
|
20
|
+
if (IS_DB_ADMIN)
|
|
21
|
+
log('Admin change on read-only db: ' + newDoc._id);
|
|
22
|
+
else
|
|
23
|
+
throw { 'forbidden': 'This database is read-only' };
|
|
24
|
+
}
|