dce-reactkit 3.1.14 → 3.1.16

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/cjs/index.js CHANGED
@@ -11,29 +11,29 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
11
11
 
12
12
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
13
13
 
14
- /******************************************************************************
15
- Copyright (c) Microsoft Corporation.
16
-
17
- Permission to use, copy, modify, and/or distribute this software for any
18
- purpose with or without fee is hereby granted.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
23
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
24
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26
- PERFORMANCE OF THIS SOFTWARE.
27
- ***************************************************************************** */
28
-
29
- function __awaiter(thisArg, _arguments, P, generator) {
30
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
- return new (P || (P = Promise))(function (resolve, reject) {
32
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
34
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
35
- step((generator = generator.apply(thisArg, _arguments || [])).next());
36
- });
14
+ /******************************************************************************
15
+ Copyright (c) Microsoft Corporation.
16
+
17
+ Permission to use, copy, modify, and/or distribute this software for any
18
+ purpose with or without fee is hereby granted.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
23
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
24
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26
+ PERFORMANCE OF THIS SOFTWARE.
27
+ ***************************************************************************** */
28
+
29
+ function __awaiter(thisArg, _arguments, P, generator) {
30
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
+ return new (P || (P = Promise))(function (resolve, reject) {
32
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
34
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
35
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
36
+ });
37
37
  }
38
38
 
39
39
  // Highest error code = DRK10
@@ -2229,6 +2229,134 @@ const handleSuccess = (res, body) => {
2229
2229
  return undefined;
2230
2230
  };
2231
2231
 
2232
+ // Import shared types
2233
+ /**
2234
+ * Generate a static error page
2235
+ * @author Gabe Abrams
2236
+ * @param opts object containing all arguments
2237
+ * @param [opts.title=An Error Occurred] title of the error box
2238
+ * @param [opts.description=An unknown server error occurred. Please contact support.]
2239
+ * a human-readable description of the error
2240
+ * @param [opts.code=ReactKitErrorCode.NoCode] error code to show
2241
+ * @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
2242
+ * the title of the error
2243
+ * @returns html of the page
2244
+ */
2245
+ const genErrorPage = (opts = {}) => {
2246
+ var _a, _b, _c, _d;
2247
+ const title = ((_a = opts.title) !== null && _a !== void 0 ? _a : 'An Error Occurred');
2248
+ const pageTitle = ((_b = opts.pageTitle) !== null && _b !== void 0 ? _b : title);
2249
+ const description = ((_c = opts.description) !== null && _c !== void 0 ? _c : 'An unknown server error occurred. Please contact support.');
2250
+ const code = ((_d = opts.code) !== null && _d !== void 0 ? _d : ReactKitErrorCode$1.NoCode);
2251
+ return `
2252
+ <head>
2253
+ <!-- Metadata -->
2254
+ <meta
2255
+ name="viewport"
2256
+ content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0"
2257
+ >
2258
+
2259
+ <!-- Title -->
2260
+ <title>${pageTitle}</title>
2261
+
2262
+ <!-- Bootstrap -->
2263
+ <link
2264
+ rel="stylesheet"
2265
+ href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/css/bootstrap.min.css"
2266
+ integrity="sha512-siwe/oXMhSjGCwLn+scraPOWrJxHlUgMBMZXdPe2Tnk3I0x3ESCoLz7WZ5NTH6SZrywMY+PB1cjyqJ5jAluCOg=="
2267
+ crossorigin="anonymous"
2268
+ referrerpolicy="no-referrer"
2269
+ />
2270
+ <script
2271
+ src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/js/bootstrap.min.js"
2272
+ integrity="sha512-vyRAVI0IEm6LI/fVSv/Wq/d0KUfrg3hJq2Qz5FlfER69sf3ZHlOrsLriNm49FxnpUGmhx+TaJKwJ+ByTLKT+Yg=="
2273
+ crossorigin="anonymous"
2274
+ referrerpolicy="no-referrer"
2275
+ ></script>
2276
+
2277
+ <!-- FontAwesome -->
2278
+ <link
2279
+ rel="stylesheet"
2280
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
2281
+ integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
2282
+ crossorigin="anonymous"
2283
+ referrerpolicy="no-referrer"
2284
+ />
2285
+
2286
+ <!-- Style -->
2287
+ <style>
2288
+ .DCEReactKit-pop-in {
2289
+ animation-name: DCEReactKit-pop-in;
2290
+ animation-duration: 0.5s;
2291
+ animation-iteration-count: 1;
2292
+ animation-timing-function: ease-out;
2293
+ animation-fill-mode: both;
2294
+
2295
+ transform-origin: center;
2296
+ }
2297
+
2298
+ @keyframes DCEReactKit-pop-in {
2299
+ 0% {
2300
+ opacity: 0;
2301
+ transform: scale(0.9);
2302
+ }
2303
+ 100% {
2304
+ opacity: 1;
2305
+ transform: scale(1);
2306
+ }
2307
+ }
2308
+
2309
+ .DCEReactKit-slide-in {
2310
+ animation-name: DCEReactKit-slide-in;
2311
+ animation-duration: 1s;
2312
+ animation-iteration-count: 1;
2313
+ animation-timing-function: ease-out;
2314
+ animation-fill-mode: both;
2315
+ animation-delay: 0.2s;
2316
+ }
2317
+
2318
+ @keyframes DCEReactKit-slide-in {
2319
+ 0% {
2320
+ opacity: 0;
2321
+ transform: translate(0, 0.3em);
2322
+ }
2323
+ 100% {
2324
+ opacity: 1;
2325
+ transform: translate(0, 0);
2326
+ }
2327
+ }
2328
+ </style>
2329
+ </head>
2330
+
2331
+ <!-- Body -->
2332
+ <body class="bg-dark text-center pt-3 ps-3 pe-3">
2333
+ <!-- Alert -->
2334
+ <div
2335
+ class="DCEReactKit-pop-in alert alert-warning d-inline-block"
2336
+ style="width: 50em; max-width: 100%"
2337
+ >
2338
+ <!-- Title -->
2339
+ <h2>
2340
+ <i class="me-1 fa-solid fa-triangle-exclamation"></i>
2341
+ ${title}
2342
+ </h2>
2343
+ <!-- Description -->
2344
+ <div>
2345
+ ${description}
2346
+ </div>
2347
+ </div>
2348
+
2349
+ <!-- Error Code -->
2350
+ <div class="DCEReactKit-slide-in text-light">
2351
+ <strong>
2352
+ Error Code:
2353
+ </strong>
2354
+ ${code}
2355
+ </div>
2356
+ </body>
2357
+ `;
2358
+ };
2359
+
2232
2360
  /**
2233
2361
  * Generate an express API route handler
2234
2362
  * @author Gabe Abrams
@@ -2236,21 +2364,23 @@ const handleSuccess = (res, body) => {
2236
2364
  * @param opts.paramTypes map containing the types for each parameter that is
2237
2365
  * included in the request (map: param name => type)
2238
2366
  * @param opts.handler function that processes the request
2239
- * @param [opts.allowNotLoggedIn] if true, allow the user to not be logged
2240
- * in (the user will be allowed to not have launched via LTI)
2241
2367
  * @returns express route handler that takes the following arguments:
2242
- * params (map: param name => value), handleSuccess (function for handling
2243
- * successful requests), handleError (function for handling failed requests),
2244
- * req (express request object), redirect (a function that takes a url and
2245
- * redirects the user to the url), and send (a function that sends a string
2246
- * and optional http status code). Params also has userId, userFirstName,
2368
+ * params (map: param name => value),
2369
+ * req (express request object),
2370
+ * next (express next function),
2371
+ * send (a function that sends a string to the client),
2372
+ * redirect (takes a url and redirects the user to that url),
2373
+ * renderErrorPage (shows a static error page to the user),
2374
+ * and returns the value to send to the client as a JSON API response, or
2375
+ * calls next() or redirect(...) or send(...) or renderErrorPage(...).
2376
+ * Note: params also has userId, userFirstName,
2247
2377
  * userLastName, isLearner, isTTM, isAdmin, and any other variables that
2248
2378
  * are directly added to the session
2249
2379
  */
2250
2380
  const genRouteHandler = (opts) => {
2251
2381
  // Return a route handler
2252
2382
  return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
2253
- var _a, _b, _c;
2383
+ var _a, _b;
2254
2384
  // Output params
2255
2385
  const output = {};
2256
2386
  /*----------------------------------------*/
@@ -2417,52 +2547,40 @@ const genRouteHandler = (opts) => {
2417
2547
  /*----------------------------------------*/
2418
2548
  // Get launch info
2419
2549
  const { launched, launchInfo } = cacclGetLaunchInfo(req);
2420
- if (
2421
- // Requiring user to be logged in
2422
- !opts.allowNotLoggedIn
2423
- // User is not logged in
2424
- && (!launched || !launchInfo)) {
2425
- // Throw an error
2550
+ if (!launched || !launchInfo) {
2426
2551
  return handleError(res, {
2427
2552
  message: 'Your session has expired. Please refresh the page and try again.',
2428
2553
  code: ReactKitErrorCode$1.SessionExpired,
2429
- status: 440,
2554
+ status: 401,
2430
2555
  });
2431
2556
  }
2432
2557
  // Error if user info cannot be found
2433
- if (launched && launchInfo) {
2434
- if (!launchInfo.userId
2435
- || !launchInfo.userFirstName
2436
- || !launchInfo.userLastName
2437
- || (launchInfo.notInCourse
2438
- && !launchInfo.isAdmin)
2439
- || (!launchInfo.isTTM
2440
- && !launchInfo.isLearner
2441
- && !launchInfo.isAdmin)) {
2442
- return handleError(res, {
2443
- message: 'Your session was invalid. Please refresh the page and try again.',
2444
- code: ReactKitErrorCode$1.SessionExpired,
2445
- status: 440,
2446
- });
2447
- }
2448
- else {
2449
- // Add launch info to output
2450
- output.userId = launchInfo.userId;
2451
- output.userFirstName = launchInfo.userFirstName;
2452
- output.userLastName = launchInfo.userLastName;
2453
- output.userEmail = launchInfo.userEmail;
2454
- output.isLearner = !!launchInfo.isLearner;
2455
- output.isTTM = !!launchInfo.isTTM;
2456
- output.isAdmin = !!launchInfo.isAdmin;
2457
- output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
2458
- output.courseName = launchInfo.contextLabel;
2459
- }
2558
+ if (!launchInfo.userId
2559
+ || !launchInfo.userFirstName
2560
+ || !launchInfo.userLastName
2561
+ || (launchInfo.notInCourse
2562
+ && !launchInfo.isAdmin)
2563
+ || (!launchInfo.isTTM
2564
+ && !launchInfo.isLearner
2565
+ && !launchInfo.isAdmin)) {
2566
+ return handleError(res, {
2567
+ message: 'Your session was invalid. Please refresh the page and try again.',
2568
+ code: ReactKitErrorCode$1.SessionExpired,
2569
+ status: 401,
2570
+ });
2460
2571
  }
2461
- /*----------------------------------------*/
2462
- /* Session */
2463
- /*----------------------------------------*/
2572
+ // Add launch info to output
2573
+ output.userId = launchInfo.userId;
2574
+ output.userFirstName = launchInfo.userFirstName;
2575
+ output.userLastName = launchInfo.userLastName;
2576
+ output.userEmail = launchInfo.userEmail;
2577
+ output.isLearner = !!launchInfo.isLearner;
2578
+ output.isTTM = !!launchInfo.isTTM;
2579
+ output.isAdmin = !!launchInfo.isAdmin;
2580
+ output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
2581
+ output.courseName = launchInfo.contextLabel;
2464
2582
  // Add other session variables
2465
- Object.keys((_c = req.session) !== null && _c !== void 0 ? _c : {}).forEach((propName) => {
2583
+ Object.keys(req.session).forEach((propName) => {
2466
2584
  // Skip if prop already in output
2467
2585
  if (output[propName] !== undefined) {
2468
2586
  return;
@@ -2480,7 +2598,6 @@ const genRouteHandler = (opts) => {
2480
2598
  /*----------------------------------------*/
2481
2599
  // Make sure the user actually launched from the appropriate course
2482
2600
  if (output.courseId
2483
- && launchInfo
2484
2601
  && launchInfo.courseId
2485
2602
  && output.courseId !== launchInfo.courseId
2486
2603
  && !output.isTTM
@@ -2549,6 +2666,23 @@ const genRouteHandler = (opts) => {
2549
2666
  responseSent = true;
2550
2667
  res.status(status).send(text);
2551
2668
  };
2669
+ /**
2670
+ * Render an error page
2671
+ * @author Gabe Abrams
2672
+ * @param opts object containing all arguments
2673
+ * @param [opts.title=An Error Occurred] title of the error box
2674
+ * @param [opts.description=An unknown server error occurred. Please contact support.]
2675
+ * a human-readable description of the error
2676
+ * @param [opts.code=ReactKitErrorCode.NoCode] error code to show
2677
+ * @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
2678
+ * the title of the error
2679
+ * @param [opts.status=500] http status code
2680
+ */
2681
+ const renderErrorPage = (opts = {}) => {
2682
+ var _a;
2683
+ const html = genErrorPage(opts);
2684
+ send(html, (_a = opts.status) !== null && _a !== void 0 ? _a : 500);
2685
+ };
2552
2686
  // Call the handler
2553
2687
  try {
2554
2688
  const results = yield opts.handler({
@@ -2560,6 +2694,7 @@ const genRouteHandler = (opts) => {
2560
2694
  next();
2561
2695
  },
2562
2696
  redirect,
2697
+ renderErrorPage,
2563
2698
  });
2564
2699
  // Send results to client (only if next wasn't called)
2565
2700
  if (!responseSent) {