payservedb 6.5.4 → 6.5.5

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/index.js CHANGED
@@ -204,6 +204,8 @@ const models = {
204
204
  MasterWorkplan: require("./src/models/master_workplan"),
205
205
  MasterWorkplanChild: require("./src/models/master_workplan_child"),
206
206
  DutyRosterChecklist: require("./src/models/dutyRosterChecklist"),
207
+ AuditTrail: require("./src/models/auditTrail"),
208
+ // auditTrial
207
209
  };
208
210
 
209
211
  // Function to get models dynamically from a specific database connection
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payservedb",
3
- "version": "6.5.4",
3
+ "version": "6.5.5",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -0,0 +1,320 @@
1
+ const mongoose = require("mongoose");
2
+
3
+ // User details sub-schema (from JWT token)
4
+ const userDetailsSchema = new mongoose.Schema(
5
+ {
6
+ userId: {
7
+ type: String,
8
+ required: true,
9
+ },
10
+ email: {
11
+ type: String,
12
+ required: true,
13
+ },
14
+ fullName: {
15
+ type: String,
16
+ required: true,
17
+ },
18
+ role: {
19
+ type: String,
20
+ required: true,
21
+ },
22
+ phoneNumber: {
23
+ type: String,
24
+ required: false,
25
+ },
26
+ facilityId: {
27
+ type: String,
28
+ required: false,
29
+ },
30
+ permissions: {
31
+ type: mongoose.Schema.Types.Mixed,
32
+ required: false,
33
+ },
34
+ tokenExpiry: {
35
+ type: Date,
36
+ required: false,
37
+ },
38
+ tokenIssued: {
39
+ type: Date,
40
+ required: false,
41
+ },
42
+ },
43
+ { _id: false }
44
+ );
45
+
46
+ // Main audit trail schema
47
+ const auditTrailSchema = new mongoose.Schema(
48
+ {
49
+ // Basic request information
50
+ timestamp: {
51
+ type: Date,
52
+ required: true,
53
+ default: Date.now,
54
+ },
55
+ method: {
56
+ type: String,
57
+ enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
58
+ required: true,
59
+ },
60
+ url: {
61
+ type: String,
62
+ required: true,
63
+ },
64
+ ip_address: {
65
+ type: String,
66
+ required: true,
67
+ },
68
+ platform: {
69
+ type: String,
70
+ required: true,
71
+ },
72
+
73
+ // Authorization and user information
74
+ is_authorized: {
75
+ type: Boolean,
76
+ required: true,
77
+ default: false,
78
+ },
79
+ user_details: {
80
+ type: userDetailsSchema,
81
+ required: false,
82
+ },
83
+
84
+ // Device and browser information
85
+ browser: {
86
+ type: String,
87
+ required: true,
88
+ default: "unknown",
89
+ },
90
+ operating_system: {
91
+ type: String,
92
+ required: true,
93
+ default: "unknown",
94
+ },
95
+ device_type: {
96
+ type: String,
97
+ enum: ["desktop", "mobile", "tablet", "unknown"],
98
+ required: true,
99
+ default: "unknown",
100
+ },
101
+ user_agent: {
102
+ type: String,
103
+ required: false,
104
+ },
105
+
106
+ // Request data
107
+ request_data: {
108
+ type: mongoose.Schema.Types.Mixed,
109
+ required: false,
110
+ },
111
+ query_params: {
112
+ type: mongoose.Schema.Types.Mixed,
113
+ required: false,
114
+ default: {},
115
+ },
116
+ route_params: {
117
+ type: mongoose.Schema.Types.Mixed,
118
+ required: false,
119
+ default: {},
120
+ },
121
+
122
+ // Activity information
123
+ activity: {
124
+ type: String,
125
+ required: true,
126
+ },
127
+
128
+ // Method-specific data
129
+ previous_data: {
130
+ type: mongoose.Schema.Types.Mixed,
131
+ required: false,
132
+ },
133
+ deleted_data: {
134
+ type: mongoose.Schema.Types.Mixed,
135
+ required: false,
136
+ },
137
+
138
+ // Custom additional data
139
+ custom_data: {
140
+ type: mongoose.Schema.Types.Mixed,
141
+ required: false,
142
+ },
143
+
144
+ // Request tracking
145
+ request_id: {
146
+ type: String,
147
+ required: false,
148
+ },
149
+ },
150
+ {
151
+ timestamps: true,
152
+ }
153
+ );
154
+
155
+ // Pre-save middleware for data validation and cleanup
156
+ auditTrailSchema.pre("save", function (next) {
157
+ // Ensure timestamp is set
158
+ if (!this.timestamp) {
159
+ this.timestamp = new Date();
160
+ }
161
+
162
+ // Validate that authorized requests have user details
163
+ if (this.is_authorized && !this.user_details) {
164
+ console.warn("Authorized request without user details detected");
165
+ }
166
+
167
+ // Ensure query_params and route_params are objects
168
+ if (!this.query_params || typeof this.query_params !== "object") {
169
+ this.query_params = {};
170
+ }
171
+ if (!this.route_params || typeof this.route_params !== "object") {
172
+ this.route_params = {};
173
+ }
174
+
175
+ // Set browser to unknown if not provided
176
+ if (!this.browser) {
177
+ this.browser = "unknown";
178
+ }
179
+
180
+ // Set operating_system to unknown if not provided
181
+ if (!this.operating_system) {
182
+ this.operating_system = "unknown";
183
+ }
184
+
185
+ next();
186
+ });
187
+
188
+ // Static methods for common queries
189
+ auditTrailSchema.statics.findByUser = function (userId, startDate, endDate) {
190
+ const query = { "user_details.userId": userId };
191
+ if (startDate || endDate) {
192
+ query.timestamp = {};
193
+ if (startDate) query.timestamp.$gte = startDate;
194
+ if (endDate) query.timestamp.$lte = endDate;
195
+ }
196
+ return this.find(query).sort({ timestamp: -1 });
197
+ };
198
+
199
+ auditTrailSchema.statics.findByActivity = function (activity, limit = 100) {
200
+ return this.find({ activity: new RegExp(activity, "i") })
201
+ .sort({ timestamp: -1 })
202
+ .limit(limit);
203
+ };
204
+
205
+ auditTrailSchema.statics.findByFacility = function (facilityId, startDate, endDate) {
206
+ const query = { "route_params.facilityId": facilityId };
207
+ if (startDate || endDate) {
208
+ query.timestamp = {};
209
+ if (startDate) query.timestamp.$gte = startDate;
210
+ if (endDate) query.timestamp.$lte = endDate;
211
+ }
212
+ return this.find(query).sort({ timestamp: -1 });
213
+ };
214
+
215
+ auditTrailSchema.statics.findByAsset = function (assetId, startDate, endDate) {
216
+ const query = { "route_params.assetId": assetId };
217
+ if (startDate || endDate) {
218
+ query.timestamp = {};
219
+ if (startDate) query.timestamp.$gte = startDate;
220
+ if (endDate) query.timestamp.$lte = endDate;
221
+ }
222
+ return this.find(query).sort({ timestamp: -1 });
223
+ };
224
+
225
+ auditTrailSchema.statics.findByIP = function (ipAddress, startDate, endDate) {
226
+ const query = { ip_address: ipAddress };
227
+ if (startDate || endDate) {
228
+ query.timestamp = {};
229
+ if (startDate) query.timestamp.$gte = startDate;
230
+ if (endDate) query.timestamp.$lte = endDate;
231
+ }
232
+ return this.find(query).sort({ timestamp: -1 });
233
+ };
234
+
235
+ auditTrailSchema.statics.findByMethod = function (method, startDate, endDate) {
236
+ const query = { method: method.toUpperCase() };
237
+ if (startDate || endDate) {
238
+ query.timestamp = {};
239
+ if (startDate) query.timestamp.$gte = startDate;
240
+ if (endDate) query.timestamp.$lte = endDate;
241
+ }
242
+ return this.find(query).sort({ timestamp: -1 });
243
+ };
244
+
245
+ // Instance methods
246
+ auditTrailSchema.methods.getActivityType = function () {
247
+ if (this.activity.includes("Create")) return "CREATE";
248
+ if (this.activity.includes("Update")) return "UPDATE";
249
+ if (this.activity.includes("Delete")) return "DELETE";
250
+ if (this.activity.includes("Login")) return "AUTH";
251
+ return "OTHER";
252
+ };
253
+
254
+ auditTrailSchema.methods.isSuccessful = function () {
255
+ return this.activity.includes("Success") ||
256
+ (!this.activity.includes("Failed") &&
257
+ !this.activity.includes("Error") &&
258
+ !this.activity.includes("Not Found"));
259
+ };
260
+
261
+ auditTrailSchema.methods.hasDataChanges = function () {
262
+ return !!(this.previous_data || this.deleted_data);
263
+ };
264
+
265
+ // Create indexes for efficient queries
266
+ auditTrailSchema.index({ timestamp: -1 }); // Recent activities first
267
+ auditTrailSchema.index({ "user_details.userId": 1, timestamp: -1 }); // User activity history
268
+ auditTrailSchema.index({ "user_details.email": 1, timestamp: -1 }); // User by email
269
+ auditTrailSchema.index({ ip_address: 1, timestamp: -1 }); // IP-based queries
270
+ auditTrailSchema.index({ method: 1, timestamp: -1 }); // Method-based queries
271
+ auditTrailSchema.index({ activity: 1, timestamp: -1 }); // Activity-based queries
272
+ auditTrailSchema.index({ platform: 1, timestamp: -1 }); // Platform-based queries
273
+ auditTrailSchema.index({ "route_params.facilityId": 1, timestamp: -1 }); // Facility-based queries
274
+ auditTrailSchema.index({ "route_params.assetId": 1, timestamp: -1 }); // Asset-based queries
275
+ auditTrailSchema.index({ is_authorized: 1, timestamp: -1 }); // Authorization status
276
+ auditTrailSchema.index({ device_type: 1, timestamp: -1 }); // Device type queries
277
+ auditTrailSchema.index({ browser: 1, timestamp: -1 }); // Browser-based queries
278
+
279
+ // Compound indexes for common query patterns
280
+ auditTrailSchema.index({ "user_details.userId": 1, activity: 1, timestamp: -1 }); // User + activity
281
+ auditTrailSchema.index({ "route_params.facilityId": 1, method: 1, timestamp: -1 }); // Facility + method
282
+ auditTrailSchema.index({ ip_address: 1, "user_details.userId": 1, timestamp: -1 }); // IP + user correlation
283
+
284
+ // Text search index for searching activities and user details
285
+ auditTrailSchema.index({
286
+ activity: "text",
287
+ "user_details.email": "text",
288
+ "user_details.fullName": "text",
289
+ url: "text",
290
+ });
291
+
292
+ // Activity type constants
293
+ auditTrailSchema.statics.ACTIVITY_TYPES = {
294
+ CREATE: "CREATE",
295
+ UPDATE: "UPDATE",
296
+ DELETE: "DELETE",
297
+ AUTH: "AUTH",
298
+ OTHER: "OTHER",
299
+ };
300
+
301
+ // Method constants
302
+ auditTrailSchema.statics.METHODS = {
303
+ GET: "GET",
304
+ POST: "POST",
305
+ PUT: "PUT",
306
+ PATCH: "PATCH",
307
+ DELETE: "DELETE",
308
+ OPTIONS: "OPTIONS",
309
+ HEAD: "HEAD",
310
+ };
311
+
312
+ // Device type constants
313
+ auditTrailSchema.statics.DEVICE_TYPES = {
314
+ DESKTOP: "desktop",
315
+ MOBILE: "mobile",
316
+ TABLET: "tablet",
317
+ UNKNOWN: "unknown",
318
+ };
319
+
320
+ module.exports = mongoose.model("AuditTrail", auditTrailSchema);