dce-expresskit 4.0.0 → 4.2.0

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.
Files changed (41) hide show
  1. package/lib/constants/LOG_REVIEW_PAGE_SIZE.d.ts +6 -0
  2. package/lib/constants/LOG_REVIEW_PAGE_SIZE.js +9 -0
  3. package/lib/constants/LOG_REVIEW_PAGE_SIZE.js.map +1 -0
  4. package/lib/helpers/dataSigner.js +7 -5
  5. package/lib/helpers/dataSigner.js.map +1 -1
  6. package/lib/helpers/genRouteHandler.js +45 -20
  7. package/lib/helpers/genRouteHandler.js.map +1 -1
  8. package/lib/helpers/getLogReviewerLogs.d.ts +27 -0
  9. package/lib/helpers/getLogReviewerLogs.js +238 -0
  10. package/lib/helpers/getLogReviewerLogs.js.map +1 -0
  11. package/lib/helpers/initExpressKitCollections.d.ts +33 -0
  12. package/lib/helpers/initExpressKitCollections.js +180 -0
  13. package/lib/helpers/initExpressKitCollections.js.map +1 -0
  14. package/lib/helpers/initServer.d.ts +0 -33
  15. package/lib/helpers/initServer.js +31 -75
  16. package/lib/helpers/initServer.js.map +1 -1
  17. package/lib/index.d.ts +2 -3
  18. package/lib/index.js +3 -5
  19. package/lib/index.js.map +1 -1
  20. package/lib/types/ExpressKitErrorCode.d.ts +2 -1
  21. package/lib/types/ExpressKitErrorCode.js +1 -0
  22. package/lib/types/ExpressKitErrorCode.js.map +1 -1
  23. package/lib/types/LogReviewerAdmin.d.ts +10 -0
  24. package/lib/types/LogReviewerAdmin.js +3 -0
  25. package/lib/types/LogReviewerAdmin.js.map +1 -0
  26. package/lib/types/SelectAdmin.d.ts +10 -0
  27. package/lib/types/SelectAdmin.js +3 -0
  28. package/lib/types/SelectAdmin.js.map +1 -0
  29. package/package.json +2 -2
  30. package/src/constants/LOG_REVIEW_PAGE_SIZE.ts +7 -0
  31. package/src/helpers/dataSigner.ts +2 -2
  32. package/src/helpers/genRouteHandler.ts +28 -4
  33. package/src/helpers/getLogReviewerLogs.ts +260 -0
  34. package/src/helpers/initExpressKitCollections.ts +144 -0
  35. package/src/helpers/initServer.ts +43 -84
  36. package/src/index.ts +2 -4
  37. package/src/types/ExpressKitErrorCode.ts +1 -0
  38. package/src/types/LogReviewerAdmin.ts +14 -0
  39. package/src/types/SelectAdmin.ts +14 -0
  40. package/src/helpers/initCrossServerCredentialCollection.ts +0 -19
  41. package/src/helpers/initLogCollection.ts +0 -30
@@ -19,9 +19,7 @@ import {
19
19
  import { getLaunchInfo } from 'caccl/server';
20
20
 
21
21
  // Import caccl functions
22
- import {
23
- internalGetLogCollection,
24
- } from './initServer';
22
+ import initExpressKitCollections, { internalGetLogCollection, internalGetSelectAdminCollection } from './initExpressKitCollections';
25
23
 
26
24
  // Import shared types
27
25
  import ExpressKitErrorCode from '../types/ExpressKitErrorCode';
@@ -563,6 +561,32 @@ const genRouteHandler = (
563
561
  );
564
562
  }
565
563
 
564
+ // Add Select Admin endpoint security
565
+ if (
566
+ // This is a select admin endpoint
567
+ req.path.startsWith('/api/admin/select')
568
+ ) {
569
+ // Get select admin collection
570
+ const selectAdminCollection = await internalGetSelectAdminCollection();
571
+ const id = output.userId;
572
+
573
+ // Find match if exists in select admin collection
574
+ const [match] = await selectAdminCollection.find({ id });
575
+
576
+ // Check that user exists in select admin collection
577
+ if (!match) {
578
+ // User does not have access
579
+ return handleError(
580
+ res,
581
+ {
582
+ message: 'This action is only allowed for select Canvas admins. Please go back to Canvas, log in as a select admin, and try again.',
583
+ code: ExpressKitErrorCode.NotSelectAdmin,
584
+ status: 401,
585
+ },
586
+ );
587
+ }
588
+ }
589
+
566
590
  /*----------------------------------------*/
567
591
  /* ------------- Log Handler ------------ */
568
592
  /*----------------------------------------*/
@@ -675,7 +699,7 @@ const genRouteHandler = (
675
699
  };
676
700
 
677
701
  // Either print to console or save to db
678
- const logCollection = internalGetLogCollection();
702
+ const logCollection = await internalGetLogCollection();
679
703
  if (logCollection) {
680
704
  // Store to the log collection
681
705
  await logCollection.insert(log);
@@ -0,0 +1,260 @@
1
+ // Import dce-mango
2
+ import { Collection } from 'dce-mango';
3
+
4
+ // Import dce-reactkit
5
+ import {
6
+ DAY_IN_MS,
7
+ Log,
8
+ LogReviewerFilterState,
9
+ LogType
10
+ } from 'dce-reactkit';
11
+
12
+ // Import shared types
13
+ import LOG_REVIEW_PAGE_SIZE from '../constants/LOG_REVIEW_PAGE_SIZE';
14
+
15
+ /**
16
+ * Get logs for the log reviewer interface
17
+ * @author Yuen Ler Chow
18
+ * @param opts object containing all arguments
19
+ * @param opts.pageNumber the page number to retrieve (1-indexed)
20
+ * @param opts.filters filter criteria for logs
21
+ * @param opts.countDocuments if true, count number of documents matching
22
+ * filters and return num pages (not always required because if changing pages,
23
+ * we don't need to recount documents)
24
+ * @param opts.logCollection MongoDB collection containing logs
25
+ * @returns object with logs for the requested page and optionally total number of pages
26
+ */
27
+ const getLogReviewerLogs = async (
28
+ opts: {
29
+ pageNumber: number,
30
+ filters: LogReviewerFilterState,
31
+ countDocuments: boolean,
32
+ logCollection: Collection<Log>,
33
+ },
34
+ ) => {
35
+ // Destructure opts
36
+ const {
37
+ pageNumber,
38
+ filters,
39
+ countDocuments,
40
+ logCollection,
41
+ } = opts;
42
+
43
+
44
+ // Destructure filters
45
+ const {
46
+ dateFilterState,
47
+ contextFilterState,
48
+ tagFilterState,
49
+ actionErrorFilterState,
50
+ advancedFilterState,
51
+ } = filters as LogReviewerFilterState;
52
+
53
+ // Build MongoDB query based on filters
54
+ const query: { [k: string]: any } = {};
55
+
56
+ /* -------------- Date Filter ------------- */
57
+
58
+ // Convert start and end dates from the dateFilterState into timestamps
59
+ const { startDate, endDate } = dateFilterState;
60
+ const startTimestamp = new Date(
61
+ `${startDate.month}/${startDate.day}/${startDate.year}`,
62
+ ).getTime();
63
+ const endTimestamp = (
64
+ (new Date(`${endDate.month}/${endDate.day}/${endDate.year}`)).getTime()
65
+ + DAY_IN_MS
66
+ );
67
+
68
+ // Add a date range condition to the query
69
+ query.timestamp = {
70
+ $gte: startTimestamp,
71
+ $lt: endTimestamp,
72
+ };
73
+
74
+ /* ------------ Context Filter ------------ */
75
+
76
+ // Process context filters to include selected contexts and subcontexts
77
+ const contextConditions: { [k: string]: any }[] = [];
78
+ Object.keys(contextFilterState).forEach((context) => {
79
+ const value = contextFilterState[context];
80
+ if (typeof value === 'boolean') {
81
+ if (value) {
82
+ // The entire context is selected
83
+ contextConditions.push({ context });
84
+ }
85
+ } else {
86
+ // The context has subcontexts
87
+ const subcontexts = Object.keys(value).filter((subcontext) => {
88
+ return value[subcontext];
89
+ });
90
+
91
+ if (subcontexts.length > 0) {
92
+ contextConditions.push({
93
+ context,
94
+ subcontext: { $in: subcontexts },
95
+ });
96
+ }
97
+ }
98
+ });
99
+ if (contextConditions.length > 0) {
100
+ query.$or = contextConditions;
101
+ }
102
+
103
+ /* -------------- Tag Filter -------------- */
104
+
105
+ const selectedTags = Object.keys(tagFilterState).filter((tag) => { return tagFilterState[tag]; });
106
+ if (selectedTags.length > 0) {
107
+ query.tags = { $in: selectedTags };
108
+ }
109
+
110
+ /* --------- Action/Error Filter ---------- */
111
+
112
+ if (actionErrorFilterState.type) {
113
+ query.type = actionErrorFilterState.type;
114
+ }
115
+
116
+ if (actionErrorFilterState.type === LogType.Error) {
117
+ if (actionErrorFilterState.errorMessage) {
118
+ // Add error message to the query.
119
+ // $i is used for case-insensitive search, and $regex is used for partial matching
120
+ query.errorMessage = {
121
+ $regex: actionErrorFilterState.errorMessage,
122
+ $options: 'i',
123
+ };
124
+ }
125
+
126
+ if (actionErrorFilterState.errorCode) {
127
+ query.errorCode = {
128
+ $regex: actionErrorFilterState.errorCode,
129
+ $options: 'i',
130
+ };
131
+ }
132
+ }
133
+
134
+ if (actionErrorFilterState.type === LogType.Action) {
135
+ const selectedTargets = (
136
+ Object.keys(actionErrorFilterState.target)
137
+ .filter((target) => {
138
+ return actionErrorFilterState.target[target];
139
+ })
140
+ );
141
+ const selectedActions = (
142
+ Object.keys(actionErrorFilterState.action)
143
+ .filter((action) => {
144
+ return actionErrorFilterState.action[action];
145
+ })
146
+ );
147
+ if (selectedTargets.length > 0) {
148
+ query.target = { $in: selectedTargets };
149
+ }
150
+ if (selectedActions.length > 0) {
151
+ query.action = { $in: selectedActions };
152
+ }
153
+ }
154
+
155
+ /* ------------ Advanced Filter ----------- */
156
+
157
+ if (advancedFilterState.userFirstName) {
158
+ query.userFirstName = {
159
+ $regex: advancedFilterState.userFirstName,
160
+ $options: 'i',
161
+ };
162
+ }
163
+
164
+ if (advancedFilterState.userLastName) {
165
+ query.userLastName = {
166
+ $regex: advancedFilterState.userLastName,
167
+ $options: 'i',
168
+ };
169
+ }
170
+
171
+ if (advancedFilterState.userEmail) {
172
+ query.userEmail = {
173
+ $regex: advancedFilterState.userEmail,
174
+ $options: 'i',
175
+ };
176
+ }
177
+
178
+ if (advancedFilterState.userId) {
179
+ query.userId = Number.parseInt(advancedFilterState.userId, 10);
180
+ }
181
+
182
+ const roles: {
183
+ isLearner?: boolean,
184
+ isTTM?: boolean,
185
+ isAdmin?: boolean,
186
+ }[] = [];
187
+ if (advancedFilterState.includeLearners) {
188
+ roles.push({ isLearner: true });
189
+ }
190
+ if (advancedFilterState.includeTTMs) {
191
+ roles.push({ isTTM: true });
192
+ }
193
+ if (advancedFilterState.includeAdmins) {
194
+ roles.push({ isAdmin: true });
195
+ }
196
+ // If any roles are selected, add them to the query
197
+ if (roles.length > 0) {
198
+ // The $or operator is used to match any of the roles
199
+ // The $and operator is to ensure that other conditions in the query are met
200
+ query.$and = [{ $or: roles }];
201
+ }
202
+
203
+ if (advancedFilterState.courseId) {
204
+ query.courseId = Number.parseInt(advancedFilterState.courseId, 10);
205
+ }
206
+
207
+ if (advancedFilterState.courseName) {
208
+ query.courseName = {
209
+ $regex: advancedFilterState.courseName,
210
+ $options: 'i',
211
+ };
212
+ }
213
+
214
+ if (advancedFilterState.isMobile !== undefined) {
215
+ query['device.isMobile'] = Boolean(advancedFilterState.isMobile);
216
+ }
217
+
218
+ if (advancedFilterState.source) {
219
+ query.source = advancedFilterState.source;
220
+ }
221
+
222
+ if (advancedFilterState.routePath) {
223
+ query.routePath = {
224
+ $regex: advancedFilterState.routePath,
225
+ $options: 'i',
226
+ };
227
+ }
228
+
229
+ if (advancedFilterState.routeTemplate) {
230
+ query.routeTemplate = {
231
+ $regex: advancedFilterState.routeTemplate,
232
+ $options: 'i',
233
+ };
234
+ }
235
+
236
+ // Query for logs
237
+ const response = await logCollection.findPaged({
238
+ query,
239
+ perPage: LOG_REVIEW_PAGE_SIZE,
240
+ pageNumber,
241
+ sortDescending: true,
242
+ });
243
+
244
+ // Count documents if requested
245
+ if (countDocuments) {
246
+ const numPages = Math.ceil(
247
+ await logCollection.count(query)
248
+ / LOG_REVIEW_PAGE_SIZE
249
+ );
250
+ return {
251
+ ...response,
252
+ numPages,
253
+ };
254
+ }
255
+
256
+ // Return response
257
+ return response;
258
+ };
259
+
260
+ export default getLogReviewerLogs;
@@ -0,0 +1,144 @@
1
+ // Import dce-mango
2
+ import { Collection as MangoCollection } from 'dce-mango';
3
+
4
+ // Import dce-reactkit
5
+ import { Log } from 'dce-reactkit';
6
+
7
+ // Import shared types
8
+ import CrossServerCredential from '../types/CrossServerCredential';
9
+ import SelectAdmin from '../types/SelectAdmin';
10
+ import LogReviewerAdmin from '../types/LogReviewerAdmin';
11
+
12
+ /*------------------------------------------------------------------------*/
13
+ /* ------------------------- Collection Storage ------------------------- */
14
+ /*------------------------------------------------------------------------*/
15
+
16
+ // Variables to store collections
17
+ let logCollection: MangoCollection<Log>;
18
+ let crossServerCredentialCollection: MangoCollection<CrossServerCredential>;
19
+ let selectAdminCollection: MangoCollection<SelectAdmin>;
20
+ let logReviewerAdminCollection: MangoCollection<LogReviewerAdmin>;
21
+
22
+ // Promise that resolves when all collections are initialized
23
+ let collectionsInitializedResolve: (v?: unknown) => void;
24
+ let collectionsInitializedReject: (error: Error) => void;
25
+ const collectionsInitialized = new Promise((resolve, reject) => {
26
+ collectionsInitializedResolve = resolve;
27
+ collectionsInitializedReject = reject;
28
+ });
29
+
30
+ /*------------------------------------------------------------------------*/
31
+ /* ------------------------- Collection Getters ------------------------- */
32
+ /*------------------------------------------------------------------------*/
33
+
34
+ /**
35
+ * Get the log collection after initialization
36
+ * @author Gardenia Liu
37
+ */
38
+ export const internalGetLogCollection = async () => {
39
+ // Wait for collections to be initialized
40
+ await collectionsInitialized;
41
+
42
+ // Return the log collection
43
+ return logCollection;
44
+ };
45
+
46
+ /**
47
+ * Get the cross server credential collection after initialization
48
+ * @author Gardenia Liu
49
+ */
50
+ export const internalGetCrossServerCredentialCollection = async () => {
51
+ // Wait for collections to be initialized
52
+ await collectionsInitialized;
53
+
54
+ // Return the cross server credential collection
55
+ return crossServerCredentialCollection;
56
+ };
57
+
58
+ /**
59
+ * Get the select admin collection after initialization
60
+ * @author Gardenia Liu
61
+ */
62
+ export const internalGetSelectAdminCollection = async () => {
63
+ // Wait for collections to be initialized
64
+ await collectionsInitialized;
65
+
66
+ // Return the cross server credential collection
67
+ return selectAdminCollection;
68
+ };
69
+
70
+ /**
71
+ * Get the log reviewer admin collection after initialization
72
+ * @author Yuen Ler Chow
73
+ */
74
+ export const internalGetLogReviewerAdminCollection = async () => {
75
+ // Wait for collections to be initialized
76
+ await collectionsInitialized;
77
+
78
+ // Return the log reviewer admin collection
79
+ return logReviewerAdminCollection;
80
+ };
81
+
82
+ /*------------------------------------------------------------------------*/
83
+ /* -------------------------------- Main -------------------------------- */
84
+ /*------------------------------------------------------------------------*/
85
+
86
+ /**
87
+ * Initialize all collections required for expresskit
88
+ * @author Gardenia Liu
89
+ * @author Gabe Abrams
90
+ * @param Collection the Collection class from dce-mango
91
+ */
92
+ const initExpressKitCollections = (Collection: typeof MangoCollection) => {
93
+ try {
94
+ // Create and store log collection
95
+ logCollection = new Collection<Log>(
96
+ 'Log',
97
+ {
98
+ uniqueIndexKey: 'id',
99
+ indexKeys: [
100
+ 'courseId',
101
+ 'context',
102
+ 'subcontext',
103
+ 'tags',
104
+ 'year',
105
+ 'month',
106
+ 'day',
107
+ 'hour',
108
+ 'type',
109
+ ],
110
+ },
111
+ );
112
+
113
+ // Create and store cross server credential collection
114
+ crossServerCredentialCollection = new Collection<CrossServerCredential>(
115
+ 'CrossServerCredential',
116
+ {
117
+ uniqueIndexKey: 'key',
118
+ },
119
+ );
120
+
121
+ // Create and store select admin collection
122
+ selectAdminCollection = new Collection<SelectAdmin>(
123
+ 'SelectAdmin',
124
+ {
125
+ uniqueIndexKey: 'id',
126
+ },
127
+ );
128
+
129
+ // Create and store log reviewer admin collection
130
+ logReviewerAdminCollection = new Collection<LogReviewerAdmin>(
131
+ 'LogReviewerAdmin',
132
+ {
133
+ uniqueIndexKey: 'id',
134
+ },
135
+ );
136
+
137
+ // Finished! Resolve the promise
138
+ collectionsInitializedResolve();
139
+ } catch (err) {
140
+ return collectionsInitializedReject(err as Error);
141
+ }
142
+ };
143
+
144
+ export default initExpressKitCollections;
@@ -6,51 +6,26 @@ 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,
15
- Log,
13
+ LOG_REVIEW_GET_LOGS_ROUTE,
14
+ ErrorWithCode,
16
15
  } from 'dce-reactkit';
17
16
 
18
17
  // Import shared helpers
19
18
  import genRouteHandler from './genRouteHandler';
19
+ import getLogReviewerLogs from './getLogReviewerLogs';
20
20
 
21
21
  // Import shared types
22
22
  import ExpressKitErrorCode from '../types/ExpressKitErrorCode';
23
- import CrossServerCredential from '../types/CrossServerCredential';
24
-
25
- // Stored copy of dce-mango log collection
26
- let _logCollection: Collection<Log>;
27
-
28
- // Stored copy of dce-mango cross-server credential collection
29
- let _crossServerCredentialCollection: Collection<CrossServerCredential>;
30
23
 
31
- /*------------------------------------------------------------------------*/
32
- /* Helpers */
33
- /*------------------------------------------------------------------------*/
34
-
35
- /**
36
- * Get log collection
37
- * @author Gabe Abrams
38
- * @returns log collection if one was included during launch or null if we don't
39
- * have a log collection (yet)
40
- */
41
- export const internalGetLogCollection = () => {
42
- return _logCollection ?? null;
43
- };
44
-
45
- /**
46
- * Get cross-server credential collection
47
- * @author Gabe Abrams
48
- * @return cross-server credential collection if one was included during launch or null
49
- * if we don't have a cross-server credential collection (yet)
50
- */
51
- export const internalGetCrossServerCredentialCollection = () => {
52
- return _crossServerCredentialCollection ?? null;
53
- };
24
+ // Import shared helpers
25
+ import {
26
+ internalGetLogCollection,
27
+ internalGetLogReviewerAdminCollection,
28
+ } from './initExpressKitCollections';
54
29
 
55
30
  /*------------------------------------------------------------------------*/
56
31
  /* Main */
@@ -62,31 +37,12 @@ export const internalGetCrossServerCredentialCollection = () => {
62
37
  * @param opts object containing all arguments
63
38
  * @param opts.app express app from inside of the postprocessor function that
64
39
  * we will add routes to
65
- * @param opts.getLaunchInfo CACCL LTI's get launch info function
66
- * @param [opts.logCollection] mongo collection from dce-mango to use for
67
- * storing logs. If none is included, logs are written to the console
68
- * @param [opts.logReviewAdmins=all] info on which admins can review
69
- * logs from the client. If not included, all Canvas admins are allowed to
70
- * review logs. If null, no Canvas admins are allowed to review logs.
71
- * If an array of Canvas userIds (numbers), only Canvas admins with those
72
- * userIds are allowed to review logs. If a dce-mango collection, only
73
- * Canvas admins with entries in that collection ({ userId, ...}) are allowed
74
- * to review logs
75
- * @param [opts.crossServerCredentialCollection] mongo collection from dce-mango to use for
76
- * storing cross-server credentials. If none is included, cross-server credentials
77
- * are not supported
78
40
  */
79
41
  const initServer = (
80
42
  opts: {
81
43
  app: express.Application,
82
- logReviewAdmins?: (number[] | Collection<any>),
83
- logCollection?: Collection<Log>,
84
- crossServerCredentialCollection?: Collection<CrossServerCredential>,
85
44
  },
86
45
  ) => {
87
- _logCollection = opts.logCollection;
88
- _crossServerCredentialCollection = opts.crossServerCredentialCollection;
89
-
90
46
  /*----------------------------------------*/
91
47
  /* Logging */
92
48
  /*----------------------------------------*/
@@ -189,22 +145,15 @@ const initServer = (
189
145
  return false;
190
146
  }
191
147
 
192
- // If all admins are allowed, we're done
193
- if (!opts.logReviewAdmins) {
194
- return true;
195
- }
148
+ /* ------- Look Up Credential ------- */
196
149
 
197
- // Do a dynamic check
198
- try {
199
- // Array of userIds
200
- if (Array.isArray(opts.logReviewAdmins)) {
201
- return opts.logReviewAdmins.some((allowedId) => {
202
- return (userId === allowedId);
203
- });
204
- }
150
+ // Get the log reviewer admin collection
151
+ const logReviewerAdminCollection = await internalGetLogReviewerAdminCollection();
205
152
 
206
- // Must be a collection
207
- const matches = await opts.logReviewAdmins.find({ userId });
153
+ // Check if the user is in the log reviewer admin collection
154
+ try {
155
+ // Must be in the collection
156
+ const matches = await logReviewerAdminCollection.find({ id: userId });
208
157
 
209
158
  // Make sure at least one entry matches
210
159
  return matches.length > 0;
@@ -223,36 +172,45 @@ const initServer = (
223
172
  LOG_REVIEW_STATUS_ROUTE,
224
173
  genRouteHandler({
225
174
  handler: async ({ params }) => {
226
- const { userId, isAdmin } = params;
175
+ // Destructure params
176
+ const {
177
+ userId,
178
+ isAdmin,
179
+ } = params;
180
+
181
+ // Check if user can review logs
227
182
  const canReview = await canReviewLogs(userId, isAdmin);
183
+
184
+ // Return result
228
185
  return canReview;
229
186
  },
230
187
  }),
231
188
  );
232
189
 
233
190
  /**
234
- * Get all logs for a certain month
191
+ * Get filtered logs based on provided filters
235
192
  * @author Gabe Abrams
236
- * @param {number} year the year to query (e.g. 2022)
237
- * @param {number} month the month to query (e.g. 1 = January)
238
- * @returns {Log[]} list of logs from the given month
193
+ * @author Yuen Ler Chow
194
+ * @param pageNumber the page number to get
195
+ * @param filters the filters to apply to the logs
196
+ * @returns {Log[]} list of logs that match the filters
239
197
  */
240
198
  opts.app.get(
241
- `${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/:year/months/:month`,
199
+ LOG_REVIEW_GET_LOGS_ROUTE,
242
200
  genRouteHandler({
243
201
  paramTypes: {
244
- year: ParamType.Int,
245
- month: ParamType.Int,
246
202
  pageNumber: ParamType.Int,
203
+ filters: ParamType.JSON,
204
+ countDocuments: ParamType.Boolean,
247
205
  },
248
206
  handler: async ({ params }) => {
249
- // Get user info
207
+ // Destructure params
250
208
  const {
251
- year,
252
- month,
253
209
  pageNumber,
254
210
  userId,
255
211
  isAdmin,
212
+ filters,
213
+ countDocuments,
256
214
  } = params;
257
215
 
258
216
  // Validate user
@@ -264,14 +222,15 @@ const initServer = (
264
222
  );
265
223
  }
266
224
 
267
- // Query for logs
268
- const response = await _logCollection.findPaged({
269
- query: {
270
- year,
271
- month,
272
- },
273
- perPage: 1000,
225
+ // Get log collection
226
+ const logCollection = await internalGetLogCollection();
227
+
228
+ // Get logs
229
+ const response = await getLogReviewerLogs({
274
230
  pageNumber,
231
+ filters,
232
+ countDocuments,
233
+ logCollection,
275
234
  });
276
235
 
277
236
  // Return response
package/src/index.ts CHANGED
@@ -48,14 +48,13 @@ import {
48
48
  } from 'dce-reactkit';
49
49
 
50
50
  // Import helpers
51
- import initCrossServerCredentialCollection from './helpers/initCrossServerCredentialCollection';
52
- import initLogCollection from './helpers/initLogCollection';
53
51
  import initServer from './helpers/initServer';
54
52
  import genRouteHandler from './helpers/genRouteHandler';
55
53
  import handleError from './helpers/handleError';
56
54
  import handleSuccess from './helpers/handleSuccess';
57
55
  import addDBEditorEndpoints from './helpers/addDBEditorEndpoints';
58
56
  import visitEndpointOnAnotherServer from './helpers/visitEndpointOnAnotherServer';
57
+ import initExpressKitCollections from './helpers/initExpressKitCollections';
59
58
 
60
59
  // Import types
61
60
  import CrossServerCredential from './types/CrossServerCredential';
@@ -106,8 +105,7 @@ export {
106
105
  genRouteHandler,
107
106
  handleError,
108
107
  handleSuccess,
109
- initLogCollection,
110
- initCrossServerCredentialCollection,
108
+ initExpressKitCollections,
111
109
  addDBEditorEndpoints,
112
110
  visitEndpointOnAnotherServer,
113
111
  // Types
@@ -32,6 +32,7 @@ enum ExpressKitErrorCode {
32
32
  NoCryptoLib = 'DEK32',
33
33
  InvalidCrossServerCredentialsFormat = 'DEK33',
34
34
  UnknownCrossServerError = 'DEK34',
35
+ NotSelectAdmin = 'DEK35',
35
36
  }
36
37
 
37
38
  export default ExpressKitErrorCode;