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 +100 -26
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/helpers/genRouteHandler.d.ts +8 -0
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +2 -0
- package/dist/esm/index.js +100 -26
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/helpers/genRouteHandler.d.ts +8 -0
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +2 -0
- package/dist/index.d.ts +10 -0
- package/package.json +1 -1
- package/src/helpers/genRouteHandler.ts +109 -10
- package/src/types/ReactKitErrorCode.tsx +3 -1
|
@@ -9,6 +9,12 @@ import LogFunction from '../types/LogFunction';
|
|
|
9
9
|
* @param opts.handler function that processes the request
|
|
10
10
|
* @param [opts.skipSessionCheck] if true, skip the session check (allow users
|
|
11
11
|
* to not be logged in and launched via LTI)
|
|
12
|
+
* @param [opts.allowedHosts] if included, only allow requests from these hosts
|
|
13
|
+
* (start a hostname with a "*" to only check the end of the hostname)
|
|
14
|
+
* you can include just one string instead of an array
|
|
15
|
+
* @param [opts.bannedHosts] if included, do not allow requests from these hosts
|
|
16
|
+
* (start a hostname with a "*" to only check the end of the hostname)
|
|
17
|
+
* you can include just one string instead of an array
|
|
12
18
|
* @param [opts.unhandledErrorMessagePrefix] if included, when an error that
|
|
13
19
|
* is not of type ErrorWithCode is thrown, the client will receive an error
|
|
14
20
|
* where the error message is prefixed with this string. For example,
|
|
@@ -63,6 +69,8 @@ declare const genRouteHandler: (opts: {
|
|
|
63
69
|
logServerEvent: LogFunction;
|
|
64
70
|
}) => any;
|
|
65
71
|
skipSessionCheck?: boolean | undefined;
|
|
72
|
+
allowedHosts?: string | string[] | undefined;
|
|
73
|
+
bannedHosts?: string | string[] | undefined;
|
|
66
74
|
unhandledErrorMessagePrefix?: string | undefined;
|
|
67
75
|
}) => (req: any, res: any, next: () => void) => Promise<undefined>;
|
|
68
76
|
export default genRouteHandler;
|
|
@@ -8,6 +8,8 @@ declare enum ReactKitErrorCode {
|
|
|
8
8
|
SessionExpired = "DRK3",
|
|
9
9
|
MissingParameter = "DRK4",
|
|
10
10
|
InvalidParameter = "DRK5",
|
|
11
|
+
HostNotAllowed = "DRK17",
|
|
12
|
+
HostBanned = "DRK18",
|
|
11
13
|
WrongCourse = "DRK6",
|
|
12
14
|
NoCACCLSendRequestFunction = "DRK7",
|
|
13
15
|
NoCACCLGetLaunchInfoFunction = "DRK8",
|
package/dist/esm/index.js
CHANGED
|
@@ -31,7 +31,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// Highest error code =
|
|
34
|
+
// Highest error code = DRK18
|
|
35
35
|
/**
|
|
36
36
|
* List of error codes built into the react kit
|
|
37
37
|
* @author Gabe Abrams
|
|
@@ -43,6 +43,8 @@ var ReactKitErrorCode;
|
|
|
43
43
|
ReactKitErrorCode["SessionExpired"] = "DRK3";
|
|
44
44
|
ReactKitErrorCode["MissingParameter"] = "DRK4";
|
|
45
45
|
ReactKitErrorCode["InvalidParameter"] = "DRK5";
|
|
46
|
+
ReactKitErrorCode["HostNotAllowed"] = "DRK17";
|
|
47
|
+
ReactKitErrorCode["HostBanned"] = "DRK18";
|
|
46
48
|
ReactKitErrorCode["WrongCourse"] = "DRK6";
|
|
47
49
|
ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
|
|
48
50
|
ReactKitErrorCode["NoCACCLGetLaunchInfoFunction"] = "DRK8";
|
|
@@ -14441,6 +14443,12 @@ const parseUserAgent = (userAgent) => {
|
|
|
14441
14443
|
* @param opts.handler function that processes the request
|
|
14442
14444
|
* @param [opts.skipSessionCheck] if true, skip the session check (allow users
|
|
14443
14445
|
* to not be logged in and launched via LTI)
|
|
14446
|
+
* @param [opts.allowedHosts] if included, only allow requests from these hosts
|
|
14447
|
+
* (start a hostname with a "*" to only check the end of the hostname)
|
|
14448
|
+
* you can include just one string instead of an array
|
|
14449
|
+
* @param [opts.bannedHosts] if included, do not allow requests from these hosts
|
|
14450
|
+
* (start a hostname with a "*" to only check the end of the hostname)
|
|
14451
|
+
* you can include just one string instead of an array
|
|
14444
14452
|
* @param [opts.unhandledErrorMessagePrefix] if included, when an error that
|
|
14445
14453
|
* is not of type ErrorWithCode is thrown, the client will receive an error
|
|
14446
14454
|
* where the error message is prefixed with this string. For example,
|
|
@@ -14468,10 +14476,76 @@ const parseUserAgent = (userAgent) => {
|
|
|
14468
14476
|
const genRouteHandler = (opts) => {
|
|
14469
14477
|
// Return a route handler
|
|
14470
14478
|
return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
14471
|
-
var _a, _b, _c;
|
|
14479
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
14472
14480
|
// Output params
|
|
14473
14481
|
const output = {};
|
|
14474
14482
|
/*----------------------------------------*/
|
|
14483
|
+
/* ----------- Hostname Check ----------- */
|
|
14484
|
+
/*----------------------------------------*/
|
|
14485
|
+
// Get hostnames
|
|
14486
|
+
const originURL = String(req.get('origin')
|
|
14487
|
+
|| req.headers.origin
|
|
14488
|
+
|| req.headers.referer);
|
|
14489
|
+
const originHostname = (originURL
|
|
14490
|
+
// Remove protocol
|
|
14491
|
+
.replace(/(^\w+:|^)\/\//, '')
|
|
14492
|
+
// Remove port
|
|
14493
|
+
.replace(/:\d+$/, ''));
|
|
14494
|
+
const serverHostname = String(req.hostname);
|
|
14495
|
+
// Check allowed
|
|
14496
|
+
if (opts.allowedHosts) {
|
|
14497
|
+
// Only accept requests from allowed hosts
|
|
14498
|
+
const allowedArray = (Array.isArray(opts.allowedHosts)
|
|
14499
|
+
? opts.allowedHosts
|
|
14500
|
+
: [opts.allowedHosts]);
|
|
14501
|
+
// Check if server is localhost
|
|
14502
|
+
if (serverHostname === 'localhost') {
|
|
14503
|
+
// Allow localhost
|
|
14504
|
+
allowedArray.push('localhost');
|
|
14505
|
+
}
|
|
14506
|
+
// Check if current host is allowed
|
|
14507
|
+
const allowed = allowedArray.some((allowedHost) => {
|
|
14508
|
+
if (allowedHost.startsWith('*')) {
|
|
14509
|
+
// Check end of hostname
|
|
14510
|
+
return originHostname.endsWith(allowedHost.substring(1));
|
|
14511
|
+
}
|
|
14512
|
+
// Check full hostname
|
|
14513
|
+
return originHostname.toLowerCase() === allowedHost.toLowerCase();
|
|
14514
|
+
});
|
|
14515
|
+
// If not allowed, return error
|
|
14516
|
+
if (!allowed) {
|
|
14517
|
+
return handleError(res, {
|
|
14518
|
+
message: 'You are not allowed to access this endpoint.',
|
|
14519
|
+
code: ReactKitErrorCode$1.HostNotAllowed,
|
|
14520
|
+
status: 403,
|
|
14521
|
+
});
|
|
14522
|
+
}
|
|
14523
|
+
}
|
|
14524
|
+
// Check banned
|
|
14525
|
+
if (opts.bannedHosts) {
|
|
14526
|
+
// Do not allow requests from banned hosts
|
|
14527
|
+
const bannedArray = (Array.isArray(opts.bannedHosts)
|
|
14528
|
+
? opts.bannedHosts
|
|
14529
|
+
: [opts.bannedHosts]);
|
|
14530
|
+
// Check if current host is banned
|
|
14531
|
+
const banned = bannedArray.some((bannedHost) => {
|
|
14532
|
+
if (bannedHost.startsWith('*')) {
|
|
14533
|
+
// Check end of hostname
|
|
14534
|
+
return originHostname.endsWith(bannedHost.substring(1));
|
|
14535
|
+
}
|
|
14536
|
+
// Check full hostname
|
|
14537
|
+
return originHostname.toLowerCase() === bannedHost.toLowerCase();
|
|
14538
|
+
});
|
|
14539
|
+
// If banned, return error
|
|
14540
|
+
if (banned) {
|
|
14541
|
+
return handleError(res, {
|
|
14542
|
+
message: 'You are not allowed to access this endpoint.',
|
|
14543
|
+
code: ReactKitErrorCode$1.HostBanned,
|
|
14544
|
+
status: 403,
|
|
14545
|
+
});
|
|
14546
|
+
}
|
|
14547
|
+
}
|
|
14548
|
+
/*----------------------------------------*/
|
|
14475
14549
|
/* ------------ Parse Params ------------ */
|
|
14476
14550
|
/*----------------------------------------*/
|
|
14477
14551
|
// Process items one by one
|
|
@@ -14669,34 +14743,34 @@ const genRouteHandler = (opts) => {
|
|
|
14669
14743
|
// Add launch info to output
|
|
14670
14744
|
output.userId = (launchInfo
|
|
14671
14745
|
? launchInfo.userId
|
|
14672
|
-
: undefined);
|
|
14746
|
+
: ((_b = output.userId) !== null && _b !== void 0 ? _b : undefined));
|
|
14673
14747
|
output.userFirstName = (launchInfo
|
|
14674
14748
|
? launchInfo.userFirstName
|
|
14675
|
-
: undefined);
|
|
14749
|
+
: ((_c = output.userFirstName) !== null && _c !== void 0 ? _c : undefined));
|
|
14676
14750
|
output.userLastName = (launchInfo
|
|
14677
14751
|
? launchInfo.userLastName
|
|
14678
|
-
: undefined);
|
|
14752
|
+
: ((_d = output.userLastName) !== null && _d !== void 0 ? _d : undefined));
|
|
14679
14753
|
output.userEmail = (launchInfo
|
|
14680
14754
|
? launchInfo.userEmail
|
|
14681
|
-
: undefined);
|
|
14755
|
+
: ((_e = output.userEmail) !== null && _e !== void 0 ? _e : undefined));
|
|
14682
14756
|
output.userAvatarURL = (launchInfo
|
|
14683
|
-
? ((
|
|
14684
|
-
: undefined);
|
|
14757
|
+
? ((_f = launchInfo.userImage) !== null && _f !== void 0 ? _f : 'http://www.gravatar.com/avatar/?d=identicon')
|
|
14758
|
+
: ((_g = output.userAvatarURL) !== null && _g !== void 0 ? _g : undefined));
|
|
14685
14759
|
output.isLearner = (launchInfo
|
|
14686
14760
|
? !!launchInfo.isLearner
|
|
14687
|
-
: undefined);
|
|
14761
|
+
: ((_h = output.isLearner) !== null && _h !== void 0 ? _h : undefined));
|
|
14688
14762
|
output.isTTM = (launchInfo
|
|
14689
14763
|
? !!launchInfo.isTTM
|
|
14690
|
-
: undefined);
|
|
14764
|
+
: ((_j = output.isTTM) !== null && _j !== void 0 ? _j : undefined));
|
|
14691
14765
|
output.isAdmin = (launchInfo
|
|
14692
14766
|
? !!launchInfo.isAdmin
|
|
14693
|
-
: undefined);
|
|
14767
|
+
: ((_k = output.isAdmin) !== null && _k !== void 0 ? _k : undefined));
|
|
14694
14768
|
output.courseId = (launchInfo
|
|
14695
|
-
? ((
|
|
14696
|
-
: undefined);
|
|
14769
|
+
? ((_l = output.courseId) !== null && _l !== void 0 ? _l : launchInfo.courseId)
|
|
14770
|
+
: ((_m = output.courseId) !== null && _m !== void 0 ? _m : undefined));
|
|
14697
14771
|
output.courseName = (launchInfo
|
|
14698
14772
|
? launchInfo.contextLabel
|
|
14699
|
-
: undefined);
|
|
14773
|
+
: ((_o = output.courseName) !== null && _o !== void 0 ? _o : undefined));
|
|
14700
14774
|
// Add other session variables
|
|
14701
14775
|
Object.keys(req.session).forEach((propName) => {
|
|
14702
14776
|
// Skip if prop already in output
|
|
@@ -14770,7 +14844,7 @@ const genRouteHandler = (opts) => {
|
|
|
14770
14844
|
* @author Gabe Abrams
|
|
14771
14845
|
*/
|
|
14772
14846
|
const logServerEvent = (logOpts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
14773
|
-
var
|
|
14847
|
+
var _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
|
14774
14848
|
// NOTE: internally, we slip through an opts.overrideAsClientEvent boolean
|
|
14775
14849
|
// that indicates that this is actually a client event, but we don't
|
|
14776
14850
|
// include that in the LogFunction type because this is internal and
|
|
@@ -14802,24 +14876,24 @@ const genRouteHandler = (opts) => {
|
|
|
14802
14876
|
timestamp,
|
|
14803
14877
|
context: (typeof logOpts.context === 'string'
|
|
14804
14878
|
? logOpts.context
|
|
14805
|
-
: ((
|
|
14806
|
-
subcontext: ((
|
|
14807
|
-
tags: ((
|
|
14808
|
-
level: ((
|
|
14809
|
-
metadata: ((
|
|
14879
|
+
: ((_q = ((_p = logOpts.context) !== null && _p !== void 0 ? _p : {})._) !== null && _q !== void 0 ? _q : LogBuiltInMetadata.Context.Uncategorized)),
|
|
14880
|
+
subcontext: ((_r = logOpts.subcontext) !== null && _r !== void 0 ? _r : LogBuiltInMetadata.Context.Uncategorized),
|
|
14881
|
+
tags: ((_s = logOpts.tags) !== null && _s !== void 0 ? _s : []),
|
|
14882
|
+
level: ((_t = logOpts.level) !== null && _t !== void 0 ? _t : LogLevel$1.Info),
|
|
14883
|
+
metadata: ((_u = logOpts.metadata) !== null && _u !== void 0 ? _u : {}),
|
|
14810
14884
|
};
|
|
14811
14885
|
// Type-specific info
|
|
14812
14886
|
const typeSpecificInfo = (('error' in opts && opts.error)
|
|
14813
14887
|
? {
|
|
14814
14888
|
type: LogType$1.Error,
|
|
14815
|
-
errorMessage: (
|
|
14816
|
-
errorCode: (
|
|
14817
|
-
errorStack: (
|
|
14889
|
+
errorMessage: (_v = logOpts.error.message) !== null && _v !== void 0 ? _v : 'Unknown message',
|
|
14890
|
+
errorCode: (_w = logOpts.error.code) !== null && _w !== void 0 ? _w : ReactKitErrorCode$1.NoCode,
|
|
14891
|
+
errorStack: (_x = logOpts.error.stack) !== null && _x !== void 0 ? _x : 'No stack',
|
|
14818
14892
|
}
|
|
14819
14893
|
: {
|
|
14820
14894
|
type: LogType$1.Action,
|
|
14821
|
-
target: ((
|
|
14822
|
-
action: ((
|
|
14895
|
+
target: ((_y = logOpts.target) !== null && _y !== void 0 ? _y : LogBuiltInMetadata.Target.NoTarget),
|
|
14896
|
+
action: ((_z = logOpts.action) !== null && _z !== void 0 ? _z : LogAction$1.Unknown),
|
|
14823
14897
|
});
|
|
14824
14898
|
// Source-specific info
|
|
14825
14899
|
const sourceSpecificInfo = (logOpts.overrideAsClientEvent
|
|
@@ -14854,7 +14928,7 @@ const genRouteHandler = (opts) => {
|
|
|
14854
14928
|
catch (err) {
|
|
14855
14929
|
// Print because we cannot store the error
|
|
14856
14930
|
// eslint-disable-next-line no-console
|
|
14857
|
-
console.error('Could not log the following:', logOpts, 'due to this error:', ((
|
|
14931
|
+
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);
|
|
14858
14932
|
// Create a dummy log to return
|
|
14859
14933
|
const dummyMainInfo = {
|
|
14860
14934
|
id: '-1',
|