JedWatson/keystone — pull request #490 by JohnnyEstilles (2014-07-25 00:39:27+00:00)
Title: Adding optional audit meta fields to track createdBy/updatedBy user

After reading the comments on #458 I remembered that I had implemented this several months ago, so I decided to share it with you all.

My implementation consists of an optional `audit meta` pattern that can be added to the `List` object (mirroring the existing `standard meta` pattern implementation).

The option is enabled as follows:

List.addPattern('audit meta');

This adds two fields to `List` (`createdBy` and `updatedBy`). I used these names to mirror the `createdOn` and `updatedOn` fields added by the `standard pattern`. Both fields are of type `Relationship` and they both refer to the model defined in the Keystone `user model` option.

This is how I implemented it.

`lib/list.js`

* Added the `standard meta` fields (if they dont' already exists)
* Added `createdBy` and `updatedBy` Relationship fields with `ref` pointing to `keystone.get('user model')`
* Mapped the new `createdBy` and `updatedBy` fields to the existing `createdBy` and `modifiedBy` mappings (I personally would have preferred using the same names as their respective fields, but I decided to use the two existing mappings ... which oddly appear to be unused elsewhere in Keystone).

NOTE: The idea of using the mappings is to give developers the option to implement their own `createdBy` and/or `modifiedBy` fields, while still using the original `standard meta` (if they so desire). Below is a somewhat silly example, but I'm sure it gets the point across.

var List = new keystone.List('Test', {
map: { createdBy: 'userThatCreatedThis', modifiedBy: `userThatModifiedThis' }
});

List.add({
...
userThatCreatedThis: { type: Types.Relationship, ref: 'User', noedit: true },
userThatModifiedThis: { type: Types.Relationship, ref: 'User', noedit: true },
..
});

List.addPattern('standard meta');

`lib/updateHandler.js`

* Checked for an existing `createdBy`mapping, and if one exists I set the corresponding mapped field to `user._id` (which was cached earlier using `req.user` in the `UpdateHandler()` constructor), but only when `item.isNew`.
* Checked for an existing `modifiedBy` mapping, and if one exists I set the corresponding mapped field to `user._id`

That's it! And ... as usual ... feel free to tweak away!