-
Notifications
You must be signed in to change notification settings - Fork 0
/
audited-collections.js
114 lines (100 loc) · 3.21 KB
/
audited-collections.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
108
109
110
111
112
113
114
// Write your package code here!
AuditLogs = new Mongo.Collection('auditlogs');
AuditLogs.metadataGetters = [];
// registers a function which will get metadata to be logged from a document
// function should take the document as the only argument and should return an
// object who's keys will be stored as metadata.
AuditLogs.registerMetadata = function (fn) {
AuditLogs.metadataGetters.push(fn);
};
AuditLogs.getMetadata = function (doc, context) {
var metadata = {};
_.each(AuditLogs.metadataGetters, function (getter) {
try {
_.extend(metadata, getter.call(context, doc));
} catch (e) {
Meteor.setTimeout(function () {throw e;}, 0);
}
});
return metadata;
};
AuditLogs.logSnapshots = function () {
AuditLogs.registerMetadata(function (doc) {
return {
snapshot: doc
};
});
};
AuditLogs.logFieldNames = function () {
AuditLogs.registerMetadata(function (doc) {
return {
fieldNames: this.fieldNames
};
});
};
AuditLogs.logModifiers = function () {
AuditLogs.registerMetadata(function (doc) {
return {
modifier: this.modifier || doc
};
});
};
// These are fields which application code and user actions should not be
// allowedto modify.
// XXX we should enforce this. We should use a deny method for each of these
// fields, note that collection hooks run before the allow/deny logic.
AuditLogs.reservedFields = ['dateModified', 'dateCreated'];
AuditedCollection = function (name) {
var result = new Mongo.Collection(name);
if (Meteor.isServer) {
result.before.insert(function (userId, doc) {
// Note this silently overwrites any existing dateCreated property
doc.dateCreated = new Date();
});
result.before.update(function (userId, doc, fieldNames, modifier, options) {
modifier.$set = modifier.$set || {};
// Note this silently overwrites any existing dateModified property
modifier.$set.dateModified = new Date();
});
result.after.insert(function (userId, doc) {
var metadata = AuditLogs.getMetadata(doc, {
collectionName: name
, userId: userId
});
metadata.documentId = doc._id;
metadata.userId = userId;
metadata.dateLogged = new Date();
metadata.actionType = 'insert';
metadata.collectionName = name;
AuditLogs.insert(metadata);
});
result.after.update(function (userId, doc, fieldNames, modifier, options) {
var metadata = AuditLogs.getMetadata(doc, {
collectionName: name
, userId: userId
, fieldNames: fieldNames
, modifier: modifier
, options: options
});
metadata.documentId = doc._id;
metadata.userId = userId;
metadata.dateLogged = new Date();
metadata.actionType = 'update';
metadata.collectionName = name;
AuditLogs.insert(metadata);
});
result.after.remove(function (userId, doc) {
var metadata = AuditLogs.getMetadata(doc, {
collectionName: name
, userId: userId
});
metadata.documentId = doc._id;
metadata.userId = userId;
metadata.dateLogged = new Date();
metadata.actionType = 'remove';
metadata.collectionName = name;
AuditLogs.insert(metadata);
});
}
return result;
};