dce-reactkit 3.9.1 → 3.9.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/dist/cjs/index.js CHANGED
@@ -59,7 +59,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
59
59
  });
60
60
  }
61
61
 
62
- // Highest error code = DRK16
62
+ // Highest error code = DRK18
63
63
  /**
64
64
  * List of error codes built into the react kit
65
65
  * @author Gabe Abrams
@@ -71,6 +71,8 @@ var ReactKitErrorCode;
71
71
  ReactKitErrorCode["SessionExpired"] = "DRK3";
72
72
  ReactKitErrorCode["MissingParameter"] = "DRK4";
73
73
  ReactKitErrorCode["InvalidParameter"] = "DRK5";
74
+ ReactKitErrorCode["HostNotAllowed"] = "DRK17";
75
+ ReactKitErrorCode["HostBanned"] = "DRK18";
74
76
  ReactKitErrorCode["WrongCourse"] = "DRK6";
75
77
  ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
76
78
  ReactKitErrorCode["NoCACCLGetLaunchInfoFunction"] = "DRK8";
@@ -14469,6 +14471,12 @@ const parseUserAgent = (userAgent) => {
14469
14471
  * @param opts.handler function that processes the request
14470
14472
  * @param [opts.skipSessionCheck] if true, skip the session check (allow users
14471
14473
  * to not be logged in and launched via LTI)
14474
+ * @param [opts.allowedHosts] if included, only allow requests from these hosts
14475
+ * (start a hostname with a "*" to only check the end of the hostname)
14476
+ * you can include just one string instead of an array
14477
+ * @param [opts.bannedHosts] if included, do not allow requests from these hosts
14478
+ * (start a hostname with a "*" to only check the end of the hostname)
14479
+ * you can include just one string instead of an array
14472
14480
  * @param [opts.unhandledErrorMessagePrefix] if included, when an error that
14473
14481
  * is not of type ErrorWithCode is thrown, the client will receive an error
14474
14482
  * where the error message is prefixed with this string. For example,
@@ -14496,10 +14504,76 @@ const parseUserAgent = (userAgent) => {
14496
14504
  const genRouteHandler = (opts) => {
14497
14505
  // Return a route handler
14498
14506
  return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
14499
- var _a, _b, _c;
14507
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
14500
14508
  // Output params
14501
14509
  const output = {};
14502
14510
  /*----------------------------------------*/
14511
+ /* ----------- Hostname Check ----------- */
14512
+ /*----------------------------------------*/
14513
+ // Get hostnames
14514
+ const originURL = String(req.get('origin')
14515
+ || req.headers.origin
14516
+ || req.headers.referer);
14517
+ const originHostname = (originURL
14518
+ // Remove protocol
14519
+ .replace(/(^\w+:|^)\/\//, '')
14520
+ // Remove port
14521
+ .replace(/:\d+$/, ''));
14522
+ const serverHostname = String(req.hostname);
14523
+ // Check allowed
14524
+ if (opts.allowedHosts) {
14525
+ // Only accept requests from allowed hosts
14526
+ const allowedArray = (Array.isArray(opts.allowedHosts)
14527
+ ? opts.allowedHosts
14528
+ : [opts.allowedHosts]);
14529
+ // Check if server is localhost
14530
+ if (serverHostname === 'localhost') {
14531
+ // Allow localhost
14532
+ allowedArray.push('localhost');
14533
+ }
14534
+ // Check if current host is allowed
14535
+ const allowed = allowedArray.some((allowedHost) => {
14536
+ if (allowedHost.startsWith('*')) {
14537
+ // Check end of hostname
14538
+ return originHostname.endsWith(allowedHost.substring(1));
14539
+ }
14540
+ // Check full hostname
14541
+ return originHostname.toLowerCase() === allowedHost.toLowerCase();
14542
+ });
14543
+ // If not allowed, return error
14544
+ if (!allowed) {
14545
+ return handleError(res, {
14546
+ message: 'You are not allowed to access this endpoint.',
14547
+ code: ReactKitErrorCode$1.HostNotAllowed,
14548
+ status: 403,
14549
+ });
14550
+ }
14551
+ }
14552
+ // Check banned
14553
+ if (opts.bannedHosts) {
14554
+ // Do not allow requests from banned hosts
14555
+ const bannedArray = (Array.isArray(opts.bannedHosts)
14556
+ ? opts.bannedHosts
14557
+ : [opts.bannedHosts]);
14558
+ // Check if current host is banned
14559
+ const banned = bannedArray.some((bannedHost) => {
14560
+ if (bannedHost.startsWith('*')) {
14561
+ // Check end of hostname
14562
+ return originHostname.endsWith(bannedHost.substring(1));
14563
+ }
14564
+ // Check full hostname
14565
+ return originHostname.toLowerCase() === bannedHost.toLowerCase();
14566
+ });
14567
+ // If banned, return error
14568
+ if (banned) {
14569
+ return handleError(res, {
14570
+ message: 'You are not allowed to access this endpoint.',
14571
+ code: ReactKitErrorCode$1.HostBanned,
14572
+ status: 403,
14573
+ });
14574
+ }
14575
+ }
14576
+ /*----------------------------------------*/
14503
14577
  /* ------------ Parse Params ------------ */
14504
14578
  /*----------------------------------------*/
14505
14579
  // Process items one by one
@@ -14697,34 +14771,34 @@ const genRouteHandler = (opts) => {
14697
14771
  // Add launch info to output
14698
14772
  output.userId = (launchInfo
14699
14773
  ? launchInfo.userId
14700
- : undefined);
14774
+ : ((_b = output.userId) !== null && _b !== void 0 ? _b : undefined));
14701
14775
  output.userFirstName = (launchInfo
14702
14776
  ? launchInfo.userFirstName
14703
- : undefined);
14777
+ : ((_c = output.userFirstName) !== null && _c !== void 0 ? _c : undefined));
14704
14778
  output.userLastName = (launchInfo
14705
14779
  ? launchInfo.userLastName
14706
- : undefined);
14780
+ : ((_d = output.userLastName) !== null && _d !== void 0 ? _d : undefined));
14707
14781
  output.userEmail = (launchInfo
14708
14782
  ? launchInfo.userEmail
14709
- : undefined);
14783
+ : ((_e = output.userEmail) !== null && _e !== void 0 ? _e : undefined));
14710
14784
  output.userAvatarURL = (launchInfo
14711
- ? ((_b = launchInfo.userImage) !== null && _b !== void 0 ? _b : 'http://www.gravatar.com/avatar/?d=identicon')
14712
- : undefined);
14785
+ ? ((_f = launchInfo.userImage) !== null && _f !== void 0 ? _f : 'http://www.gravatar.com/avatar/?d=identicon')
14786
+ : ((_g = output.userAvatarURL) !== null && _g !== void 0 ? _g : undefined));
14713
14787
  output.isLearner = (launchInfo
14714
14788
  ? !!launchInfo.isLearner
14715
- : undefined);
14789
+ : ((_h = output.isLearner) !== null && _h !== void 0 ? _h : undefined));
14716
14790
  output.isTTM = (launchInfo
14717
14791
  ? !!launchInfo.isTTM
14718
- : undefined);
14792
+ : ((_j = output.isTTM) !== null && _j !== void 0 ? _j : undefined));
14719
14793
  output.isAdmin = (launchInfo
14720
14794
  ? !!launchInfo.isAdmin
14721
- : undefined);
14795
+ : ((_k = output.isAdmin) !== null && _k !== void 0 ? _k : undefined));
14722
14796
  output.courseId = (launchInfo
14723
- ? ((_c = output.courseId) !== null && _c !== void 0 ? _c : launchInfo.courseId)
14724
- : undefined);
14797
+ ? ((_l = output.courseId) !== null && _l !== void 0 ? _l : launchInfo.courseId)
14798
+ : ((_m = output.courseId) !== null && _m !== void 0 ? _m : undefined));
14725
14799
  output.courseName = (launchInfo
14726
14800
  ? launchInfo.contextLabel
14727
- : undefined);
14801
+ : ((_o = output.courseName) !== null && _o !== void 0 ? _o : undefined));
14728
14802
  // Add other session variables
14729
14803
  Object.keys(req.session).forEach((propName) => {
14730
14804
  // Skip if prop already in output
@@ -14798,7 +14872,7 @@ const genRouteHandler = (opts) => {
14798
14872
  * @author Gabe Abrams
14799
14873
  */
14800
14874
  const logServerEvent = (logOpts) => __awaiter(void 0, void 0, void 0, function* () {
14801
- var _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
14875
+ var _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
14802
14876
  // NOTE: internally, we slip through an opts.overrideAsClientEvent boolean
14803
14877
  // that indicates that this is actually a client event, but we don't
14804
14878
  // include that in the LogFunction type because this is internal and
@@ -14830,24 +14904,24 @@ const genRouteHandler = (opts) => {
14830
14904
  timestamp,
14831
14905
  context: (typeof logOpts.context === 'string'
14832
14906
  ? logOpts.context
14833
- : ((_e = ((_d = logOpts.context) !== null && _d !== void 0 ? _d : {})._) !== null && _e !== void 0 ? _e : LogBuiltInMetadata.Context.Uncategorized)),
14834
- subcontext: ((_f = logOpts.subcontext) !== null && _f !== void 0 ? _f : LogBuiltInMetadata.Context.Uncategorized),
14835
- tags: ((_g = logOpts.tags) !== null && _g !== void 0 ? _g : []),
14836
- level: ((_h = logOpts.level) !== null && _h !== void 0 ? _h : LogLevel$1.Info),
14837
- metadata: ((_j = logOpts.metadata) !== null && _j !== void 0 ? _j : {}),
14907
+ : ((_q = ((_p = logOpts.context) !== null && _p !== void 0 ? _p : {})._) !== null && _q !== void 0 ? _q : LogBuiltInMetadata.Context.Uncategorized)),
14908
+ subcontext: ((_r = logOpts.subcontext) !== null && _r !== void 0 ? _r : LogBuiltInMetadata.Context.Uncategorized),
14909
+ tags: ((_s = logOpts.tags) !== null && _s !== void 0 ? _s : []),
14910
+ level: ((_t = logOpts.level) !== null && _t !== void 0 ? _t : LogLevel$1.Info),
14911
+ metadata: ((_u = logOpts.metadata) !== null && _u !== void 0 ? _u : {}),
14838
14912
  };
14839
14913
  // Type-specific info
14840
14914
  const typeSpecificInfo = (('error' in opts && opts.error)
14841
14915
  ? {
14842
14916
  type: LogType$1.Error,
14843
- errorMessage: (_k = logOpts.error.message) !== null && _k !== void 0 ? _k : 'Unknown message',
14844
- errorCode: (_l = logOpts.error.code) !== null && _l !== void 0 ? _l : ReactKitErrorCode$1.NoCode,
14845
- errorStack: (_m = logOpts.error.stack) !== null && _m !== void 0 ? _m : 'No stack',
14917
+ errorMessage: (_v = logOpts.error.message) !== null && _v !== void 0 ? _v : 'Unknown message',
14918
+ errorCode: (_w = logOpts.error.code) !== null && _w !== void 0 ? _w : ReactKitErrorCode$1.NoCode,
14919
+ errorStack: (_x = logOpts.error.stack) !== null && _x !== void 0 ? _x : 'No stack',
14846
14920
  }
14847
14921
  : {
14848
14922
  type: LogType$1.Action,
14849
- target: ((_o = logOpts.target) !== null && _o !== void 0 ? _o : LogBuiltInMetadata.Target.NoTarget),
14850
- action: ((_p = logOpts.action) !== null && _p !== void 0 ? _p : LogAction$1.Unknown),
14923
+ target: ((_y = logOpts.target) !== null && _y !== void 0 ? _y : LogBuiltInMetadata.Target.NoTarget),
14924
+ action: ((_z = logOpts.action) !== null && _z !== void 0 ? _z : LogAction$1.Unknown),
14851
14925
  });
14852
14926
  // Source-specific info
14853
14927
  const sourceSpecificInfo = (logOpts.overrideAsClientEvent
@@ -14882,7 +14956,7 @@ const genRouteHandler = (opts) => {
14882
14956
  catch (err) {
14883
14957
  // Print because we cannot store the error
14884
14958
  // eslint-disable-next-line no-console
14885
- console.error('Could not log the following:', logOpts, 'due to this error:', ((_q = err) !== null && _q !== void 0 ? _q : {}).message, ((_r = err) !== null && _r !== void 0 ? _r : {}).stack);
14959
+ console.error('Could not log the following:', logOpts, 'due to this error:', ((_0 = err) !== null && _0 !== void 0 ? _0 : {}).message, ((_1 = err) !== null && _1 !== void 0 ? _1 : {}).stack);
14886
14960
  // Create a dummy log to return
14887
14961
  const dummyMainInfo = {
14888
14962
  id: '-1',