dce-expresskit 4.0.0-beta.8 → 4.0.0-log-reviewer-beta.10
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/genEncodedSecret.ts +75 -98
- package/lib/constants/LOG_REVIEW_PAGE_SIZE.d.ts +6 -0
- package/lib/constants/LOG_REVIEW_PAGE_SIZE.js +9 -0
- package/lib/constants/LOG_REVIEW_PAGE_SIZE.js.map +1 -0
- package/lib/helpers/dataSigner.js +18 -10
- package/lib/helpers/dataSigner.js.map +1 -1
- package/lib/helpers/getLogReviewerLogs.d.ts +27 -0
- package/lib/helpers/getLogReviewerLogs.js +238 -0
- package/lib/helpers/getLogReviewerLogs.js.map +1 -0
- package/lib/helpers/initServer.d.ts +6 -4
- package/lib/helpers/initServer.js +15 -17
- package/lib/helpers/initServer.js.map +1 -1
- package/package.json +3 -4
- package/src/constants/LOG_REVIEW_PAGE_SIZE.ts +7 -0
- package/src/helpers/dataSigner.ts +28 -8
- package/src/helpers/getLogReviewerLogs.ts +259 -0
- package/src/helpers/initServer.ts +25 -24
- package/genSalt.ts +0 -15
- package/src/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.ts +0 -9
- package/src/constants/LOG_REVIEW_STATUS_ROUTE.ts +0 -10
- package/src/constants/LOG_ROUTE_PATH.ts +0 -9
- package/src/constants/ROUTE_PATH_PREFIX.ts +0 -7
- package/src/errors/ErrorWithCode.tsx +0 -15
package/genEncodedSecret.ts
CHANGED
|
@@ -1,107 +1,84 @@
|
|
|
1
1
|
// Import crypto lib
|
|
2
2
|
import crypto from 'crypto';
|
|
3
3
|
|
|
4
|
-
// Prompt
|
|
5
|
-
import readline from 'readline';
|
|
6
|
-
|
|
7
|
-
// Create a readline interface
|
|
8
|
-
const readlineInterface = readline.createInterface({
|
|
9
|
-
input: process.stdin,
|
|
10
|
-
output: process.stdout
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Prompt user for input
|
|
15
|
-
* @author Gabe Abrams
|
|
16
|
-
* @param question the question to ask the user
|
|
17
|
-
* @returns the text from the user
|
|
18
|
-
*/
|
|
19
|
-
const prompt = (question: string): Promise<string> => {
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
readlineInterface.question(question, (answer: string) => {
|
|
22
|
-
if (!answer || answer.trim().length === 0) {
|
|
23
|
-
console.log('\nValue cannot be empty. Exiting...');
|
|
24
|
-
process.exit(0);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
resolve(answer);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// All chars for randomizer
|
|
33
4
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
34
5
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.log('
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
console.log('
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
console.log('
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
6
|
+
// Get args
|
|
7
|
+
const DCEKIT_CRED_ENCODING_SALT = process.env.npm_config_salt;
|
|
8
|
+
if (!DCEKIT_CRED_ENCODING_SALT) {
|
|
9
|
+
console.log('Encoding salt is required: --salt=...');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Get the key
|
|
14
|
+
let key = process.env.npm_config_key;
|
|
15
|
+
if (!key) {
|
|
16
|
+
console.log('Key is required: --key=...');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Get the description
|
|
21
|
+
let description = process.env.npm_config_description;
|
|
22
|
+
if (!description) {
|
|
23
|
+
console.log('Description is required: --description=...');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Get secret
|
|
28
|
+
let secret = process.env.npm_config_secret;
|
|
29
|
+
if (!secret) {
|
|
59
30
|
// Generate a random secret
|
|
60
|
-
|
|
31
|
+
secret = '';
|
|
61
32
|
for (let i = 0; i < 32; i++) {
|
|
62
33
|
secret += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
63
34
|
}
|
|
64
|
-
secret
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
35
|
+
console.log('Generated a random secret. If you have one in mind, use --secret=...');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Get the host name
|
|
39
|
+
const host = process.env.npm_config_host;
|
|
40
|
+
if (!host) {
|
|
41
|
+
console.log('Host of the receiving server is required: --host=...');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Encryption process based on:
|
|
46
|
+
// https://medium.com/@tony.infisical/guide-to-nodes-crypto-module-for-encryption-decryption-65c077176980
|
|
47
|
+
|
|
48
|
+
// Create a random initialization vector
|
|
49
|
+
const iv = crypto.randomBytes(12).toString('base64');
|
|
50
|
+
|
|
51
|
+
// Create a cipher
|
|
52
|
+
const cipher = crypto.createCipheriv(
|
|
53
|
+
'aes-256-gcm',
|
|
54
|
+
Buffer.from(secret, 'base64'),
|
|
55
|
+
Buffer.from(iv, 'base64'),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Encrypt the string
|
|
59
|
+
let ciphertext = cipher.update(secret, 'utf8', 'base64');
|
|
60
|
+
|
|
61
|
+
// Finalize the encryption
|
|
62
|
+
ciphertext += cipher.final('base64');
|
|
63
|
+
|
|
64
|
+
// Get the authentication tag
|
|
65
|
+
const tag = cipher.getAuthTag();
|
|
66
|
+
|
|
67
|
+
// JSONify the encrypted data
|
|
68
|
+
const encryptionPack = encodeURIComponent(JSON.stringify({
|
|
69
|
+
ciphertext,
|
|
70
|
+
iv,
|
|
71
|
+
tag,
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
// Show the encrypted data
|
|
75
|
+
console.log('\n\n');
|
|
76
|
+
console.log('––––– Done! What\'s Next: –––––');
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log('On the server *sending* the requests, append the following to the DCEKIT_CROSS_SERVER_CREDENTIALS env var:');
|
|
79
|
+
console.log(`|${host}:${key}:${secret}|`);
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log('On the server *receiving* the requests, add an entry to the "CrossServerCredential" collection:');
|
|
82
|
+
console.log(`{ "description": "${description}", "key": "${key}", "encodedeSecret": "${encryptionPack}", "scopes": [] }`);
|
|
83
|
+
console.log('');
|
|
84
|
+
console.log('For all scopes that the server should have access to, add them to the "scopes" array.');
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Log reviewer page size
|
|
5
|
+
* @author Yuen Ler Chow
|
|
6
|
+
*/
|
|
7
|
+
var LOG_REVIEW_PAGE_SIZE = 100;
|
|
8
|
+
exports.default = LOG_REVIEW_PAGE_SIZE;
|
|
9
|
+
//# sourceMappingURL=LOG_REVIEW_PAGE_SIZE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LOG_REVIEW_PAGE_SIZE.js","sourceRoot":"","sources":["../../src/constants/LOG_REVIEW_PAGE_SIZE.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,IAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC,kBAAe,oBAAoB,CAAC"}
|
|
@@ -165,7 +165,7 @@ exports.signRequest = signRequest;
|
|
|
165
165
|
* @returns parsed and validated params
|
|
166
166
|
*/
|
|
167
167
|
var validateSignedRequest = function (opts) { return __awaiter(void 0, void 0, void 0, function () {
|
|
168
|
-
var signature, timestamp, key, method, path, params, crossServerCredentialCollection, crossServerCredential, allowedScopes, secret, expectedSignature, elapsedMs;
|
|
168
|
+
var signature, timestamp, key, method, path, params, scope, crossServerCredentialCollection, crossServerCredentialMatches, crossServerCredential, allowedScopes, secret, paramsToSign, expectedSignature, elapsedMs;
|
|
169
169
|
return __generator(this, function (_a) {
|
|
170
170
|
switch (_a.label) {
|
|
171
171
|
case 0:
|
|
@@ -189,31 +189,39 @@ var validateSignedRequest = function (opts) { return __awaiter(void 0, void 0, v
|
|
|
189
189
|
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request there was no oauth consumer key.', ExpressKitErrorCode_1.default.CrossServerMissingSignedRequestInfo);
|
|
190
190
|
}
|
|
191
191
|
key = opts.params.oauth_consumer_key;
|
|
192
|
-
method = opts.method, path = opts.path, params = opts.params;
|
|
192
|
+
method = opts.method, path = opts.path, params = opts.params, scope = opts.scope;
|
|
193
193
|
crossServerCredentialCollection = (0, initServer_1.internalGetCrossServerCredentialCollection)();
|
|
194
194
|
if (!crossServerCredentialCollection) {
|
|
195
195
|
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request because the cross-server credential collection was not ready in time.', ExpressKitErrorCode_1.default.SignedRequestInvalidCollection);
|
|
196
196
|
}
|
|
197
197
|
return [4 /*yield*/, crossServerCredentialCollection.find({ key: key })];
|
|
198
198
|
case 1:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (!crossServerCredential) {
|
|
199
|
+
crossServerCredentialMatches = _a.sent();
|
|
200
|
+
if (!crossServerCredentialMatches || crossServerCredentialMatches.length === 0) {
|
|
202
201
|
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request because the credential was not found.', ExpressKitErrorCode_1.default.SignedRequestInvalidCredential);
|
|
203
202
|
}
|
|
203
|
+
crossServerCredential = crossServerCredentialMatches[0];
|
|
204
204
|
allowedScopes = crossServerCredential.scopes;
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
if (!allowedScopes || !Array.isArray(allowedScopes)) {
|
|
206
|
+
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request because the credential does not have access to any scopes.', ExpressKitErrorCode_1.default.SignedRequestInvalidScope);
|
|
207
|
+
}
|
|
208
|
+
if (!allowedScopes.includes(scope)) {
|
|
207
209
|
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request because the required scope was not approved for the credential.', ExpressKitErrorCode_1.default.SignedRequestInvalidScope);
|
|
208
210
|
}
|
|
209
211
|
return [4 /*yield*/, decrypt(crossServerCredential.encodedeSecret)];
|
|
210
212
|
case 2:
|
|
211
213
|
secret = _a.sent();
|
|
212
|
-
|
|
214
|
+
paramsToSign = __assign({}, params);
|
|
215
|
+
Object.keys(paramsToSign).forEach(function (key) {
|
|
216
|
+
// Delete oauth params
|
|
217
|
+
if (key.startsWith('oauth_')) {
|
|
218
|
+
delete paramsToSign[key];
|
|
219
|
+
}
|
|
220
|
+
});
|
|
213
221
|
return [4 /*yield*/, genSignature({
|
|
214
222
|
method: method,
|
|
215
223
|
path: path,
|
|
216
|
-
params:
|
|
224
|
+
params: paramsToSign,
|
|
217
225
|
secret: secret,
|
|
218
226
|
})];
|
|
219
227
|
case 3:
|
|
@@ -223,7 +231,7 @@ var validateSignedRequest = function (opts) { return __awaiter(void 0, void 0, v
|
|
|
223
231
|
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request because the signature did not match.', ExpressKitErrorCode_1.default.SignedRequestInvalidSignature);
|
|
224
232
|
}
|
|
225
233
|
elapsedMs = Math.abs(Date.now() - timestamp);
|
|
226
|
-
if (elapsedMs
|
|
234
|
+
if (elapsedMs > dce_reactkit_1.MINUTE_IN_MS) {
|
|
227
235
|
throw new dce_reactkit_1.ErrorWithCode('Could not validate a cross-server request because the request was too old.', ExpressKitErrorCode_1.default.SignedRequestInvalidTimestamp);
|
|
228
236
|
}
|
|
229
237
|
return [2 /*return*/];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataSigner.js","sourceRoot":"","sources":["../../src/helpers/dataSigner.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dataSigner.js","sourceRoot":"","sources":["../../src/helpers/dataSigner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Log, LogReviewerFilterState } from 'dce-reactkit';
|
|
2
|
+
import { Collection } from 'dce-mango';
|
|
3
|
+
/**
|
|
4
|
+
* Get logs for the log reviewer interface
|
|
5
|
+
* @author Yuen Ler Chow
|
|
6
|
+
* @param opts object containing all arguments
|
|
7
|
+
* @param opts.pageNumber the page number to retrieve (1-indexed)
|
|
8
|
+
* @param opts.filters filter criteria for logs
|
|
9
|
+
* @param opts.countDocuments if true, count number of documents matching
|
|
10
|
+
* filters and return num pages (not always required because if changing pages,
|
|
11
|
+
* we don't need to recount documents)
|
|
12
|
+
* @param opts.logCollection MongoDB collection containing logs
|
|
13
|
+
* @returns object with logs for the requested page and optionally total number of pages
|
|
14
|
+
*/
|
|
15
|
+
declare const getLogReviewerLogs: (opts: {
|
|
16
|
+
pageNumber: number;
|
|
17
|
+
filters: LogReviewerFilterState;
|
|
18
|
+
countDocuments: boolean;
|
|
19
|
+
logCollection: Collection<Log>;
|
|
20
|
+
}) => Promise<import("dce-mango/lib/types/PaginatedResponse").default<Log> | {
|
|
21
|
+
numPages: number;
|
|
22
|
+
items: Log[];
|
|
23
|
+
currentPageNumber: number;
|
|
24
|
+
perPage: number;
|
|
25
|
+
hasAnotherPage: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
export default getLogReviewerLogs;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
// Import dce-reactkit
|
|
54
|
+
var dce_reactkit_1 = require("dce-reactkit");
|
|
55
|
+
// Import shared types
|
|
56
|
+
var LOG_REVIEW_PAGE_SIZE_1 = __importDefault(require("../constants/LOG_REVIEW_PAGE_SIZE"));
|
|
57
|
+
/**
|
|
58
|
+
* Get logs for the log reviewer interface
|
|
59
|
+
* @author Yuen Ler Chow
|
|
60
|
+
* @param opts object containing all arguments
|
|
61
|
+
* @param opts.pageNumber the page number to retrieve (1-indexed)
|
|
62
|
+
* @param opts.filters filter criteria for logs
|
|
63
|
+
* @param opts.countDocuments if true, count number of documents matching
|
|
64
|
+
* filters and return num pages (not always required because if changing pages,
|
|
65
|
+
* we don't need to recount documents)
|
|
66
|
+
* @param opts.logCollection MongoDB collection containing logs
|
|
67
|
+
* @returns object with logs for the requested page and optionally total number of pages
|
|
68
|
+
*/
|
|
69
|
+
var getLogReviewerLogs = function (opts) { return __awaiter(void 0, void 0, void 0, function () {
|
|
70
|
+
var pageNumber, filters, countDocuments, logCollection, _a, dateFilterState, contextFilterState, tagFilterState, actionErrorFilterState, advancedFilterState, query, startDate, endDate, startTimestamp, endTimestamp, contextConditions, selectedTags, selectedTargets, selectedActions, roles, response, numPages, _b, _c;
|
|
71
|
+
return __generator(this, function (_d) {
|
|
72
|
+
switch (_d.label) {
|
|
73
|
+
case 0:
|
|
74
|
+
pageNumber = opts.pageNumber, filters = opts.filters, countDocuments = opts.countDocuments, logCollection = opts.logCollection;
|
|
75
|
+
_a = filters, dateFilterState = _a.dateFilterState, contextFilterState = _a.contextFilterState, tagFilterState = _a.tagFilterState, actionErrorFilterState = _a.actionErrorFilterState, advancedFilterState = _a.advancedFilterState;
|
|
76
|
+
query = {};
|
|
77
|
+
startDate = dateFilterState.startDate, endDate = dateFilterState.endDate;
|
|
78
|
+
startTimestamp = new Date("".concat(startDate.month, "/").concat(startDate.day, "/").concat(startDate.year)).getTime();
|
|
79
|
+
endTimestamp = ((new Date("".concat(endDate.month, "/").concat(endDate.day, "/").concat(endDate.year))).getTime()
|
|
80
|
+
+ dce_reactkit_1.DAY_IN_MS);
|
|
81
|
+
// Add a date range condition to the query
|
|
82
|
+
query.timestamp = {
|
|
83
|
+
$gte: startTimestamp,
|
|
84
|
+
$lt: endTimestamp,
|
|
85
|
+
};
|
|
86
|
+
contextConditions = [];
|
|
87
|
+
Object.keys(contextFilterState).forEach(function (context) {
|
|
88
|
+
var value = contextFilterState[context];
|
|
89
|
+
if (typeof value === 'boolean') {
|
|
90
|
+
if (value) {
|
|
91
|
+
// The entire context is selected
|
|
92
|
+
contextConditions.push({ context: context });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// The context has subcontexts
|
|
97
|
+
var subcontexts = Object.keys(value).filter(function (subcontext) {
|
|
98
|
+
return value[subcontext];
|
|
99
|
+
});
|
|
100
|
+
if (subcontexts.length > 0) {
|
|
101
|
+
contextConditions.push({
|
|
102
|
+
context: context,
|
|
103
|
+
subcontext: { $in: subcontexts },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
if (contextConditions.length > 0) {
|
|
109
|
+
query.$or = contextConditions;
|
|
110
|
+
}
|
|
111
|
+
selectedTags = Object.keys(tagFilterState).filter(function (tag) { return tagFilterState[tag]; });
|
|
112
|
+
if (selectedTags.length > 0) {
|
|
113
|
+
query.tags = { $in: selectedTags };
|
|
114
|
+
}
|
|
115
|
+
/* --------- Action/Error Filter ---------- */
|
|
116
|
+
if (actionErrorFilterState.type) {
|
|
117
|
+
query.type = actionErrorFilterState.type;
|
|
118
|
+
}
|
|
119
|
+
if (actionErrorFilterState.type === dce_reactkit_1.LogType.Error) {
|
|
120
|
+
if (actionErrorFilterState.errorMessage) {
|
|
121
|
+
// Add error message to the query.
|
|
122
|
+
// $i is used for case-insensitive search, and $regex is used for partial matching
|
|
123
|
+
query.errorMessage = {
|
|
124
|
+
$regex: actionErrorFilterState.errorMessage,
|
|
125
|
+
$options: 'i',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (actionErrorFilterState.errorCode) {
|
|
129
|
+
query.errorCode = {
|
|
130
|
+
$regex: actionErrorFilterState.errorCode,
|
|
131
|
+
$options: 'i',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (actionErrorFilterState.type === dce_reactkit_1.LogType.Action) {
|
|
136
|
+
selectedTargets = (Object.keys(actionErrorFilterState.target)
|
|
137
|
+
.filter(function (target) {
|
|
138
|
+
return actionErrorFilterState.target[target];
|
|
139
|
+
}));
|
|
140
|
+
selectedActions = (Object.keys(actionErrorFilterState.action)
|
|
141
|
+
.filter(function (action) {
|
|
142
|
+
return actionErrorFilterState.action[action];
|
|
143
|
+
}));
|
|
144
|
+
if (selectedTargets.length > 0) {
|
|
145
|
+
query.target = { $in: selectedTargets };
|
|
146
|
+
}
|
|
147
|
+
if (selectedActions.length > 0) {
|
|
148
|
+
query.action = { $in: selectedActions };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/* ------------ Advanced Filter ----------- */
|
|
152
|
+
if (advancedFilterState.userFirstName) {
|
|
153
|
+
query.userFirstName = {
|
|
154
|
+
$regex: advancedFilterState.userFirstName,
|
|
155
|
+
$options: 'i',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (advancedFilterState.userLastName) {
|
|
159
|
+
query.userLastName = {
|
|
160
|
+
$regex: advancedFilterState.userLastName,
|
|
161
|
+
$options: 'i',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (advancedFilterState.userEmail) {
|
|
165
|
+
query.userEmail = {
|
|
166
|
+
$regex: advancedFilterState.userEmail,
|
|
167
|
+
$options: 'i',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (advancedFilterState.userId) {
|
|
171
|
+
query.userId = Number.parseInt(advancedFilterState.userId, 10);
|
|
172
|
+
}
|
|
173
|
+
roles = [];
|
|
174
|
+
if (advancedFilterState.includeLearners) {
|
|
175
|
+
roles.push({ isLearner: true });
|
|
176
|
+
}
|
|
177
|
+
if (advancedFilterState.includeTTMs) {
|
|
178
|
+
roles.push({ isTTM: true });
|
|
179
|
+
}
|
|
180
|
+
if (advancedFilterState.includeAdmins) {
|
|
181
|
+
roles.push({ isAdmin: true });
|
|
182
|
+
}
|
|
183
|
+
// If any roles are selected, add them to the query
|
|
184
|
+
if (roles.length > 0) {
|
|
185
|
+
// The $or operator is used to match any of the roles
|
|
186
|
+
// The $and operator is to ensure that other conditions in the query are met
|
|
187
|
+
query.$and = [{ $or: roles }];
|
|
188
|
+
}
|
|
189
|
+
if (advancedFilterState.courseId) {
|
|
190
|
+
query.courseId = Number.parseInt(advancedFilterState.courseId, 10);
|
|
191
|
+
}
|
|
192
|
+
if (advancedFilterState.courseName) {
|
|
193
|
+
query.courseName = {
|
|
194
|
+
$regex: advancedFilterState.courseName,
|
|
195
|
+
$options: 'i',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (advancedFilterState.isMobile !== undefined) {
|
|
199
|
+
query['device.isMobile'] = Boolean(advancedFilterState.isMobile);
|
|
200
|
+
}
|
|
201
|
+
if (advancedFilterState.source) {
|
|
202
|
+
query.source = advancedFilterState.source;
|
|
203
|
+
}
|
|
204
|
+
if (advancedFilterState.routePath) {
|
|
205
|
+
query.routePath = {
|
|
206
|
+
$regex: advancedFilterState.routePath,
|
|
207
|
+
$options: 'i',
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
if (advancedFilterState.routeTemplate) {
|
|
211
|
+
query.routeTemplate = {
|
|
212
|
+
$regex: advancedFilterState.routeTemplate,
|
|
213
|
+
$options: 'i',
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return [4 /*yield*/, logCollection.findPaged({
|
|
217
|
+
query: query,
|
|
218
|
+
perPage: LOG_REVIEW_PAGE_SIZE_1.default,
|
|
219
|
+
pageNumber: pageNumber,
|
|
220
|
+
sortDescending: true,
|
|
221
|
+
})];
|
|
222
|
+
case 1:
|
|
223
|
+
response = _d.sent();
|
|
224
|
+
if (!countDocuments) return [3 /*break*/, 3];
|
|
225
|
+
_c = (_b = Math).ceil;
|
|
226
|
+
return [4 /*yield*/, logCollection.count(query)];
|
|
227
|
+
case 2:
|
|
228
|
+
numPages = _c.apply(_b, [(_d.sent())
|
|
229
|
+
/ LOG_REVIEW_PAGE_SIZE_1.default]);
|
|
230
|
+
return [2 /*return*/, __assign(__assign({}, response), { numPages: numPages })];
|
|
231
|
+
case 3:
|
|
232
|
+
// Return response
|
|
233
|
+
return [2 /*return*/, response];
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}); };
|
|
237
|
+
exports.default = getLogReviewerLogs;
|
|
238
|
+
//# sourceMappingURL=getLogReviewerLogs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getLogReviewerLogs.js","sourceRoot":"","sources":["../../src/helpers/getLogReviewerLogs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import { Collection } from 'dce-mango';
|
|
3
|
+
import { Log } from 'dce-reactkit';
|
|
4
|
+
import CrossServerCredential from '../types/CrossServerCredential';
|
|
3
5
|
/**
|
|
4
6
|
* Get log collection
|
|
5
7
|
* @author Gabe Abrams
|
|
6
8
|
* @returns log collection if one was included during launch or null if we don't
|
|
7
9
|
* have a log collection (yet)
|
|
8
10
|
*/
|
|
9
|
-
export declare const internalGetLogCollection: () =>
|
|
11
|
+
export declare const internalGetLogCollection: () => Collection<Log>;
|
|
10
12
|
/**
|
|
11
13
|
* Get cross-server credential collection
|
|
12
14
|
* @author Gabe Abrams
|
|
13
15
|
* @return cross-server credential collection if one was included during launch or null
|
|
14
16
|
* if we don't have a cross-server credential collection (yet)
|
|
15
17
|
*/
|
|
16
|
-
export declare const internalGetCrossServerCredentialCollection: () =>
|
|
18
|
+
export declare const internalGetCrossServerCredentialCollection: () => Collection<CrossServerCredential>;
|
|
17
19
|
/**
|
|
18
20
|
* Prepare dce-reactkit to run on the server
|
|
19
21
|
* @author Gabe Abrams
|
|
@@ -37,7 +39,7 @@ export declare const internalGetCrossServerCredentialCollection: () => any;
|
|
|
37
39
|
declare const initServer: (opts: {
|
|
38
40
|
app: express.Application;
|
|
39
41
|
logReviewAdmins?: (number[] | Collection<any>);
|
|
40
|
-
logCollection?: Collection<
|
|
41
|
-
crossServerCredentialCollection?: Collection<
|
|
42
|
+
logCollection?: Collection<Log>;
|
|
43
|
+
crossServerCredentialCollection?: Collection<CrossServerCredential>;
|
|
42
44
|
}) => void;
|
|
43
45
|
export default initServer;
|
|
@@ -55,7 +55,7 @@ exports.internalGetCrossServerCredentialCollection = exports.internalGetLogColle
|
|
|
55
55
|
var dce_reactkit_1 = require("dce-reactkit");
|
|
56
56
|
// Import shared helpers
|
|
57
57
|
var genRouteHandler_1 = __importDefault(require("./genRouteHandler"));
|
|
58
|
-
|
|
58
|
+
var getLogReviewerLogs_1 = __importDefault(require("./getLogReviewerLogs"));
|
|
59
59
|
var ExpressKitErrorCode_1 = __importDefault(require("../types/ExpressKitErrorCode"));
|
|
60
60
|
// Stored copy of dce-mango log collection
|
|
61
61
|
var _logCollection;
|
|
@@ -247,38 +247,36 @@ var initServer = function (opts) {
|
|
|
247
247
|
}); },
|
|
248
248
|
}));
|
|
249
249
|
/**
|
|
250
|
-
* Get
|
|
251
|
-
* @author Gabe Abrams
|
|
252
|
-
* @param
|
|
253
|
-
* @param
|
|
254
|
-
* @returns {Log[]} list of logs
|
|
250
|
+
* Get filtered logs based on provided filters
|
|
251
|
+
* @author Gabe Abrams, Yuen Ler Chow
|
|
252
|
+
* @param pageNumber the page number to get
|
|
253
|
+
* @param filters the filters to apply to the logs
|
|
254
|
+
* @returns {Log[]} list of logs that match the filters
|
|
255
255
|
*/
|
|
256
|
-
opts.app.get(
|
|
256
|
+
opts.app.get(dce_reactkit_1.LOG_REVIEW_GET_LOGS_ROUTE, (0, genRouteHandler_1.default)({
|
|
257
257
|
paramTypes: {
|
|
258
|
-
year: dce_reactkit_1.ParamType.Int,
|
|
259
|
-
month: dce_reactkit_1.ParamType.Int,
|
|
260
258
|
pageNumber: dce_reactkit_1.ParamType.Int,
|
|
259
|
+
filters: dce_reactkit_1.ParamType.JSON,
|
|
260
|
+
countDocuments: dce_reactkit_1.ParamType.Boolean,
|
|
261
261
|
},
|
|
262
262
|
handler: function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
263
|
-
var
|
|
263
|
+
var pageNumber, userId, isAdmin, filters, countDocuments, canReview, response;
|
|
264
264
|
var params = _b.params;
|
|
265
265
|
return __generator(this, function (_c) {
|
|
266
266
|
switch (_c.label) {
|
|
267
267
|
case 0:
|
|
268
|
-
|
|
268
|
+
pageNumber = params.pageNumber, userId = params.userId, isAdmin = params.isAdmin, filters = params.filters, countDocuments = params.countDocuments;
|
|
269
269
|
return [4 /*yield*/, canReviewLogs(userId, isAdmin)];
|
|
270
270
|
case 1:
|
|
271
271
|
canReview = _c.sent();
|
|
272
272
|
if (!canReview) {
|
|
273
273
|
throw new dce_reactkit_1.ErrorWithCode('You cannot access this resource because you do not have the appropriate permissions.', ExpressKitErrorCode_1.default.NotAllowedToReviewLogs);
|
|
274
274
|
}
|
|
275
|
-
return [4 /*yield*/,
|
|
276
|
-
query: {
|
|
277
|
-
year: year,
|
|
278
|
-
month: month,
|
|
279
|
-
},
|
|
280
|
-
perPage: 1000,
|
|
275
|
+
return [4 /*yield*/, (0, getLogReviewerLogs_1.default)({
|
|
281
276
|
pageNumber: pageNumber,
|
|
277
|
+
filters: filters,
|
|
278
|
+
countDocuments: countDocuments,
|
|
279
|
+
logCollection: _logCollection,
|
|
282
280
|
})];
|
|
283
281
|
case 2:
|
|
284
282
|
response = _c.sent();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initServer.js","sourceRoot":"","sources":["../../src/helpers/initServer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,sBAAsB;AACtB,
|
|
1
|
+
{"version":3,"file":"initServer.js","sourceRoot":"","sources":["../../src/helpers/initServer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dce-expresskit",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-log-reviewer-beta.10",
|
|
4
4
|
"description": "Shared functions, helpers, and tools for Harvard DCE Express-based servers",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc --project ./tsconfig.json",
|
|
9
|
-
"gen-cross-server-secret": "npx tsx genEncodedSecret.ts"
|
|
10
|
-
"gen-cross-server-salt": "npx tsx genSalt.ts"
|
|
9
|
+
"gen-cross-server-secret": "npx tsx genEncodedSecret.ts"
|
|
11
10
|
},
|
|
12
11
|
"repository": {
|
|
13
12
|
"type": "git",
|
|
@@ -25,7 +24,7 @@
|
|
|
25
24
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
|
26
25
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
|
27
26
|
"bootstrap": "^5.3.3",
|
|
28
|
-
"dce-reactkit": "^4.0.0-beta.
|
|
27
|
+
"dce-reactkit": "^4.0.0-beta-logreviewer.1",
|
|
29
28
|
"react": "^19.0.0"
|
|
30
29
|
},
|
|
31
30
|
"peerDependencies": {
|
|
@@ -172,6 +172,7 @@ export const signRequest = async (
|
|
|
172
172
|
// Add signature to the augmented params
|
|
173
173
|
augmentedParams.oauth_signature = signature;
|
|
174
174
|
|
|
175
|
+
|
|
175
176
|
// Return the augmented params
|
|
176
177
|
return augmentedParams;
|
|
177
178
|
};
|
|
@@ -233,6 +234,7 @@ export const validateSignedRequest = async (
|
|
|
233
234
|
method,
|
|
234
235
|
path,
|
|
235
236
|
params,
|
|
237
|
+
scope,
|
|
236
238
|
} = opts;
|
|
237
239
|
|
|
238
240
|
/* ------- Look Up Credential ------- */
|
|
@@ -247,19 +249,25 @@ export const validateSignedRequest = async (
|
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
// Get the cross-server credential
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
if (!crossServerCredential) {
|
|
252
|
+
const crossServerCredentialMatches: CrossServerCredential[] = await crossServerCredentialCollection.find({ key });
|
|
253
|
+
if (!crossServerCredentialMatches || crossServerCredentialMatches.length === 0) {
|
|
253
254
|
throw new ErrorWithCode(
|
|
254
255
|
'Could not validate a cross-server request because the credential was not found.',
|
|
255
256
|
ExpressKitErrorCode.SignedRequestInvalidCredential,
|
|
256
257
|
);
|
|
257
258
|
}
|
|
259
|
+
const crossServerCredential = crossServerCredentialMatches[0];
|
|
258
260
|
|
|
259
261
|
// Make sure the scope is included
|
|
260
262
|
const allowedScopes = crossServerCredential.scopes;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
+
if (!allowedScopes || !Array.isArray(allowedScopes)) {
|
|
264
|
+
throw new ErrorWithCode(
|
|
265
|
+
'Could not validate a cross-server request because the credential does not have access to any scopes.',
|
|
266
|
+
ExpressKitErrorCode.SignedRequestInvalidScope,
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
}
|
|
270
|
+
if (!allowedScopes.includes(scope)) {
|
|
263
271
|
throw new ErrorWithCode(
|
|
264
272
|
'Could not validate a cross-server request because the required scope was not approved for the credential.',
|
|
265
273
|
ExpressKitErrorCode.SignedRequestInvalidScope,
|
|
@@ -268,15 +276,27 @@ export const validateSignedRequest = async (
|
|
|
268
276
|
|
|
269
277
|
// Decode the secret
|
|
270
278
|
const secret = await decrypt(crossServerCredential.encodedeSecret);
|
|
271
|
-
console.log('Decoded secret:', secret);
|
|
272
279
|
|
|
273
280
|
/* -------- Verify Signature -------- */
|
|
274
281
|
|
|
282
|
+
// Curate what goes into the params
|
|
283
|
+
const paramsToSign: {
|
|
284
|
+
[key: string]: any,
|
|
285
|
+
} = {
|
|
286
|
+
...params,
|
|
287
|
+
};
|
|
288
|
+
Object.keys(paramsToSign).forEach((key) => {
|
|
289
|
+
// Delete oauth params
|
|
290
|
+
if (key.startsWith('oauth_')) {
|
|
291
|
+
delete paramsToSign[key];
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
275
295
|
// Generate a new signature to compare
|
|
276
296
|
const expectedSignature = await genSignature({
|
|
277
297
|
method,
|
|
278
298
|
path,
|
|
279
|
-
params,
|
|
299
|
+
params: paramsToSign,
|
|
280
300
|
secret,
|
|
281
301
|
});
|
|
282
302
|
|
|
@@ -290,7 +310,7 @@ export const validateSignedRequest = async (
|
|
|
290
310
|
|
|
291
311
|
// Make sure the timestamp was recent enough
|
|
292
312
|
const elapsedMs = Math.abs(Date.now() - timestamp);
|
|
293
|
-
if (elapsedMs
|
|
313
|
+
if (elapsedMs > MINUTE_IN_MS) {
|
|
294
314
|
throw new ErrorWithCode(
|
|
295
315
|
'Could not validate a cross-server request because the request was too old.',
|
|
296
316
|
ExpressKitErrorCode.SignedRequestInvalidTimestamp,
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// Import dce-reactkit
|
|
2
|
+
import {
|
|
3
|
+
DAY_IN_MS,
|
|
4
|
+
Log,
|
|
5
|
+
LogReviewerFilterState,
|
|
6
|
+
LogType
|
|
7
|
+
} from 'dce-reactkit';
|
|
8
|
+
|
|
9
|
+
// Import shared types
|
|
10
|
+
import LOG_REVIEW_PAGE_SIZE from '../constants/LOG_REVIEW_PAGE_SIZE';
|
|
11
|
+
import { Collection } from 'dce-mango';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get logs for the log reviewer interface
|
|
15
|
+
* @author Yuen Ler Chow
|
|
16
|
+
* @param opts object containing all arguments
|
|
17
|
+
* @param opts.pageNumber the page number to retrieve (1-indexed)
|
|
18
|
+
* @param opts.filters filter criteria for logs
|
|
19
|
+
* @param opts.countDocuments if true, count number of documents matching
|
|
20
|
+
* filters and return num pages (not always required because if changing pages,
|
|
21
|
+
* we don't need to recount documents)
|
|
22
|
+
* @param opts.logCollection MongoDB collection containing logs
|
|
23
|
+
* @returns object with logs for the requested page and optionally total number of pages
|
|
24
|
+
*/
|
|
25
|
+
const getLogReviewerLogs = async (
|
|
26
|
+
opts: {
|
|
27
|
+
pageNumber: number,
|
|
28
|
+
filters: LogReviewerFilterState,
|
|
29
|
+
countDocuments: boolean,
|
|
30
|
+
logCollection: Collection<Log>,
|
|
31
|
+
},
|
|
32
|
+
) => {
|
|
33
|
+
|
|
34
|
+
// Destructure opts
|
|
35
|
+
const {
|
|
36
|
+
pageNumber,
|
|
37
|
+
filters,
|
|
38
|
+
countDocuments,
|
|
39
|
+
logCollection,
|
|
40
|
+
} = opts;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// Destructure filters
|
|
44
|
+
const {
|
|
45
|
+
dateFilterState,
|
|
46
|
+
contextFilterState,
|
|
47
|
+
tagFilterState,
|
|
48
|
+
actionErrorFilterState,
|
|
49
|
+
advancedFilterState,
|
|
50
|
+
} = filters as LogReviewerFilterState;
|
|
51
|
+
|
|
52
|
+
// Build MongoDB query based on filters
|
|
53
|
+
const query: { [k: string]: any } = {};
|
|
54
|
+
|
|
55
|
+
/* -------------- Date Filter ------------- */
|
|
56
|
+
|
|
57
|
+
// Convert start and end dates from the dateFilterState into timestamps
|
|
58
|
+
const { startDate, endDate } = dateFilterState;
|
|
59
|
+
const startTimestamp = new Date(
|
|
60
|
+
`${startDate.month}/${startDate.day}/${startDate.year}`,
|
|
61
|
+
).getTime();
|
|
62
|
+
const endTimestamp = (
|
|
63
|
+
(new Date(`${endDate.month}/${endDate.day}/${endDate.year}`)).getTime()
|
|
64
|
+
+ DAY_IN_MS
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Add a date range condition to the query
|
|
68
|
+
query.timestamp = {
|
|
69
|
+
$gte: startTimestamp,
|
|
70
|
+
$lt: endTimestamp,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/* ------------ Context Filter ------------ */
|
|
74
|
+
|
|
75
|
+
// Process context filters to include selected contexts and subcontexts
|
|
76
|
+
const contextConditions: { [k: string]: any }[] = [];
|
|
77
|
+
Object.keys(contextFilterState).forEach((context) => {
|
|
78
|
+
const value = contextFilterState[context];
|
|
79
|
+
if (typeof value === 'boolean') {
|
|
80
|
+
if (value) {
|
|
81
|
+
// The entire context is selected
|
|
82
|
+
contextConditions.push({ context });
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
// The context has subcontexts
|
|
86
|
+
const subcontexts = Object.keys(value).filter((subcontext) => {
|
|
87
|
+
return value[subcontext];
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (subcontexts.length > 0) {
|
|
91
|
+
contextConditions.push({
|
|
92
|
+
context,
|
|
93
|
+
subcontext: { $in: subcontexts },
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
if (contextConditions.length > 0) {
|
|
99
|
+
query.$or = contextConditions;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* -------------- Tag Filter -------------- */
|
|
103
|
+
|
|
104
|
+
const selectedTags = Object.keys(tagFilterState).filter((tag) => { return tagFilterState[tag]; });
|
|
105
|
+
if (selectedTags.length > 0) {
|
|
106
|
+
query.tags = { $in: selectedTags };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* --------- Action/Error Filter ---------- */
|
|
110
|
+
|
|
111
|
+
if (actionErrorFilterState.type) {
|
|
112
|
+
query.type = actionErrorFilterState.type;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (actionErrorFilterState.type === LogType.Error) {
|
|
116
|
+
if (actionErrorFilterState.errorMessage) {
|
|
117
|
+
// Add error message to the query.
|
|
118
|
+
// $i is used for case-insensitive search, and $regex is used for partial matching
|
|
119
|
+
query.errorMessage = {
|
|
120
|
+
$regex: actionErrorFilterState.errorMessage,
|
|
121
|
+
$options: 'i',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (actionErrorFilterState.errorCode) {
|
|
126
|
+
query.errorCode = {
|
|
127
|
+
$regex: actionErrorFilterState.errorCode,
|
|
128
|
+
$options: 'i',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (actionErrorFilterState.type === LogType.Action) {
|
|
134
|
+
const selectedTargets = (
|
|
135
|
+
Object.keys(actionErrorFilterState.target)
|
|
136
|
+
.filter((target) => {
|
|
137
|
+
return actionErrorFilterState.target[target];
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
const selectedActions = (
|
|
141
|
+
Object.keys(actionErrorFilterState.action)
|
|
142
|
+
.filter((action) => {
|
|
143
|
+
return actionErrorFilterState.action[action];
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
if (selectedTargets.length > 0) {
|
|
147
|
+
query.target = { $in: selectedTargets };
|
|
148
|
+
}
|
|
149
|
+
if (selectedActions.length > 0) {
|
|
150
|
+
query.action = { $in: selectedActions };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ------------ Advanced Filter ----------- */
|
|
155
|
+
|
|
156
|
+
if (advancedFilterState.userFirstName) {
|
|
157
|
+
query.userFirstName = {
|
|
158
|
+
$regex: advancedFilterState.userFirstName,
|
|
159
|
+
$options: 'i',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (advancedFilterState.userLastName) {
|
|
164
|
+
query.userLastName = {
|
|
165
|
+
$regex: advancedFilterState.userLastName,
|
|
166
|
+
$options: 'i',
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (advancedFilterState.userEmail) {
|
|
171
|
+
query.userEmail = {
|
|
172
|
+
$regex: advancedFilterState.userEmail,
|
|
173
|
+
$options: 'i',
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (advancedFilterState.userId) {
|
|
178
|
+
query.userId = Number.parseInt(advancedFilterState.userId, 10);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const roles: {
|
|
182
|
+
isLearner?: boolean,
|
|
183
|
+
isTTM?: boolean,
|
|
184
|
+
isAdmin?: boolean,
|
|
185
|
+
}[] = [];
|
|
186
|
+
if (advancedFilterState.includeLearners) {
|
|
187
|
+
roles.push({ isLearner: true });
|
|
188
|
+
}
|
|
189
|
+
if (advancedFilterState.includeTTMs) {
|
|
190
|
+
roles.push({ isTTM: true });
|
|
191
|
+
}
|
|
192
|
+
if (advancedFilterState.includeAdmins) {
|
|
193
|
+
roles.push({ isAdmin: true });
|
|
194
|
+
}
|
|
195
|
+
// If any roles are selected, add them to the query
|
|
196
|
+
if (roles.length > 0) {
|
|
197
|
+
// The $or operator is used to match any of the roles
|
|
198
|
+
// The $and operator is to ensure that other conditions in the query are met
|
|
199
|
+
query.$and = [{ $or: roles }];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (advancedFilterState.courseId) {
|
|
203
|
+
query.courseId = Number.parseInt(advancedFilterState.courseId, 10);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (advancedFilterState.courseName) {
|
|
207
|
+
query.courseName = {
|
|
208
|
+
$regex: advancedFilterState.courseName,
|
|
209
|
+
$options: 'i',
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (advancedFilterState.isMobile !== undefined) {
|
|
214
|
+
query['device.isMobile'] = Boolean(advancedFilterState.isMobile);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (advancedFilterState.source) {
|
|
218
|
+
query.source = advancedFilterState.source;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (advancedFilterState.routePath) {
|
|
222
|
+
query.routePath = {
|
|
223
|
+
$regex: advancedFilterState.routePath,
|
|
224
|
+
$options: 'i',
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (advancedFilterState.routeTemplate) {
|
|
229
|
+
query.routeTemplate = {
|
|
230
|
+
$regex: advancedFilterState.routeTemplate,
|
|
231
|
+
$options: 'i',
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Query for logs
|
|
236
|
+
const response = await logCollection.findPaged({
|
|
237
|
+
query,
|
|
238
|
+
perPage: LOG_REVIEW_PAGE_SIZE,
|
|
239
|
+
pageNumber,
|
|
240
|
+
sortDescending: true,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Count documents if requested
|
|
244
|
+
if (countDocuments) {
|
|
245
|
+
const numPages = Math.ceil(
|
|
246
|
+
await logCollection.count(query)
|
|
247
|
+
/ LOG_REVIEW_PAGE_SIZE
|
|
248
|
+
);
|
|
249
|
+
return {
|
|
250
|
+
...response,
|
|
251
|
+
numPages,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Return response
|
|
256
|
+
return response;
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export default getLogReviewerLogs;
|
|
@@ -6,25 +6,28 @@ import { Collection } from 'dce-mango';
|
|
|
6
6
|
|
|
7
7
|
// Import dce-reactkit
|
|
8
8
|
import {
|
|
9
|
-
ErrorWithCode,
|
|
10
9
|
ParamType,
|
|
11
10
|
LogFunction,
|
|
12
|
-
LOG_REVIEW_ROUTE_PATH_PREFIX,
|
|
13
11
|
LOG_ROUTE_PATH,
|
|
14
12
|
LOG_REVIEW_STATUS_ROUTE,
|
|
13
|
+
Log,
|
|
14
|
+
LOG_REVIEW_GET_LOGS_ROUTE,
|
|
15
|
+
ErrorWithCode,
|
|
15
16
|
} from 'dce-reactkit';
|
|
16
17
|
|
|
17
18
|
// Import shared helpers
|
|
18
19
|
import genRouteHandler from './genRouteHandler';
|
|
20
|
+
import getLogReviewerLogs from './getLogReviewerLogs';
|
|
19
21
|
|
|
20
22
|
// Import shared types
|
|
23
|
+
import CrossServerCredential from '../types/CrossServerCredential';
|
|
21
24
|
import ExpressKitErrorCode from '../types/ExpressKitErrorCode';
|
|
22
25
|
|
|
23
26
|
// Stored copy of dce-mango log collection
|
|
24
|
-
let _logCollection:
|
|
27
|
+
let _logCollection: Collection<Log>;
|
|
25
28
|
|
|
26
29
|
// Stored copy of dce-mango cross-server credential collection
|
|
27
|
-
let _crossServerCredentialCollection:
|
|
30
|
+
let _crossServerCredentialCollection: Collection<CrossServerCredential>;
|
|
28
31
|
|
|
29
32
|
/*------------------------------------------------------------------------*/
|
|
30
33
|
/* Helpers */
|
|
@@ -78,8 +81,8 @@ const initServer = (
|
|
|
78
81
|
opts: {
|
|
79
82
|
app: express.Application,
|
|
80
83
|
logReviewAdmins?: (number[] | Collection<any>),
|
|
81
|
-
logCollection?: Collection<
|
|
82
|
-
crossServerCredentialCollection?: Collection<
|
|
84
|
+
logCollection?: Collection<Log>,
|
|
85
|
+
crossServerCredentialCollection?: Collection<CrossServerCredential>,
|
|
83
86
|
},
|
|
84
87
|
) => {
|
|
85
88
|
_logCollection = opts.logCollection;
|
|
@@ -229,28 +232,28 @@ const initServer = (
|
|
|
229
232
|
);
|
|
230
233
|
|
|
231
234
|
/**
|
|
232
|
-
* Get
|
|
233
|
-
* @author Gabe Abrams
|
|
234
|
-
* @param
|
|
235
|
-
* @param
|
|
236
|
-
* @returns {Log[]} list of logs
|
|
235
|
+
* Get filtered logs based on provided filters
|
|
236
|
+
* @author Gabe Abrams, Yuen Ler Chow
|
|
237
|
+
* @param pageNumber the page number to get
|
|
238
|
+
* @param filters the filters to apply to the logs
|
|
239
|
+
* @returns {Log[]} list of logs that match the filters
|
|
237
240
|
*/
|
|
238
241
|
opts.app.get(
|
|
239
|
-
|
|
242
|
+
LOG_REVIEW_GET_LOGS_ROUTE,
|
|
240
243
|
genRouteHandler({
|
|
241
244
|
paramTypes: {
|
|
242
|
-
year: ParamType.Int,
|
|
243
|
-
month: ParamType.Int,
|
|
244
245
|
pageNumber: ParamType.Int,
|
|
246
|
+
filters: ParamType.JSON,
|
|
247
|
+
countDocuments: ParamType.Boolean,
|
|
245
248
|
},
|
|
246
249
|
handler: async ({ params }) => {
|
|
247
|
-
//
|
|
250
|
+
// Destructure params
|
|
248
251
|
const {
|
|
249
|
-
year,
|
|
250
|
-
month,
|
|
251
252
|
pageNumber,
|
|
252
253
|
userId,
|
|
253
254
|
isAdmin,
|
|
255
|
+
filters,
|
|
256
|
+
countDocuments,
|
|
254
257
|
} = params;
|
|
255
258
|
|
|
256
259
|
// Validate user
|
|
@@ -262,14 +265,12 @@ const initServer = (
|
|
|
262
265
|
);
|
|
263
266
|
}
|
|
264
267
|
|
|
265
|
-
//
|
|
266
|
-
const response = await
|
|
267
|
-
query: {
|
|
268
|
-
year,
|
|
269
|
-
month,
|
|
270
|
-
},
|
|
271
|
-
perPage: 1000,
|
|
268
|
+
// Get logs
|
|
269
|
+
const response = await getLogReviewerLogs({
|
|
272
270
|
pageNumber,
|
|
271
|
+
filters,
|
|
272
|
+
countDocuments,
|
|
273
|
+
logCollection: _logCollection,
|
|
273
274
|
});
|
|
274
275
|
|
|
275
276
|
// Return response
|
package/genSalt.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// All chars for randomizer
|
|
2
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
3
|
-
|
|
4
|
-
// Generate a random salt
|
|
5
|
-
let salt = '';
|
|
6
|
-
for (let i = 0; i < 32; i++) {
|
|
7
|
-
salt += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
8
|
-
}
|
|
9
|
-
salt = Buffer.from(salt).toString('base64');
|
|
10
|
-
|
|
11
|
-
// Generates 32 byte salt
|
|
12
|
-
console.log('New *receiving* server salt:')
|
|
13
|
-
|
|
14
|
-
Buffer.from("Hello World").toString('base64')
|
|
15
|
-
console.log(salt);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import ROUTE_PATH_PREFIX from './ROUTE_PATH_PREFIX';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Route for checking the status of the current user's
|
|
5
|
-
* access to log review
|
|
6
|
-
* @author Gabe Abrams
|
|
7
|
-
*/
|
|
8
|
-
const LOG_REVIEW_STATUS_ROUTE = `${ROUTE_PATH_PREFIX}/logs/access_allowed`;
|
|
9
|
-
|
|
10
|
-
export default LOG_REVIEW_STATUS_ROUTE;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* An error with a code
|
|
3
|
-
* @author Gabe Abrams
|
|
4
|
-
*/
|
|
5
|
-
class ErrorWithCode extends Error {
|
|
6
|
-
code: string;
|
|
7
|
-
|
|
8
|
-
constructor(message: string, code: string) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.name = 'ErrorWithCode';
|
|
11
|
-
this.code = code;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default ErrorWithCode;
|