Skip to content

Commit e98b144

Browse files
committed
Enabling permissions to be updated.
This flow was erroring before. 1) Load document with permissions embedded. 2) write to that object 3) have the permissions get updated with post-write permissions It broke because we were doing a really simple check to make sure we didn't overwrite data. In the case, we want to. So the checks now only error if we haven't already embedded permissions.
1 parent 8c22b34 commit e98b144

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

__tests__/embedPermissions.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ test('Verify that the permissions data cannot be changed', (t) => {
111111
const doc = { _id: 'foobar' };
112112
embedPermissions(t.context.schema, { permissions: true }, ['manager'], doc);
113113

114+
t.throws(
115+
() => { doc.permissions = {}; },
116+
Error,
117+
'The permissions object shouldn\'t be writable overall',
118+
);
119+
114120
t.throws(
115121
() => { doc.permissions.read = []; },
116122
Error,

src/embedPermissions.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,33 @@ const _ = require('lodash');
22
const getAuthorizedFields = require('./getAuthorizedFields');
33
const hasPermission = require('./hasPermission');
44

5+
const embedPermissionsSymbol = Symbol('Embedded Permissions');
6+
57
function embedPermissions(schema, options, authLevels, doc) {
68
if (!schema || !options || !options.permissions || _.isEmpty(doc)) { return; }
79

810
const permsKey = options.permissions === true ? 'permissions' : options.permissions;
911

10-
if (doc[permsKey]) {
11-
// There's already something at the key where we're supposed to inset the permissions
12-
// Throw an exception to help the developer avoid this error.
13-
throw new Error(`Cannot embed permissions into mongoose document at \`${permsKey}\`because the key is already present in the document. Please specify a custom key.`);
12+
if (permsKey in doc) {
13+
if (!doc[embedPermissionsSymbol]) {
14+
// We haven't embedded permissions, but there is already a value at the path where
15+
// we're supposed to insert the permissions. Throw an exception for the developer
16+
// knows that something is wrong.
17+
throw new Error(`Cannot embed permissions into mongoose document at \`${permsKey}\`because the key is already present in the document. Please specify a custom key.`);
18+
}
19+
} else {
20+
Object.defineProperty(doc, permsKey, {
21+
get() { return this[embedPermissionsSymbol]; },
22+
set() { throw new Error('Permissions are not writable'); },
23+
enumerable: true,
24+
});
1425
}
1526

16-
Object.defineProperty(doc, permsKey, {
17-
value: {
18-
read: getAuthorizedFields(schema, authLevels, 'read'),
19-
write: getAuthorizedFields(schema, authLevels, 'write'),
20-
remove: hasPermission(schema, authLevels, 'remove'),
21-
},
22-
writable: false,
23-
enumerable: true,
27+
doc[embedPermissionsSymbol] = Object.freeze({
28+
read: getAuthorizedFields(schema, authLevels, 'read'),
29+
write: getAuthorizedFields(schema, authLevels, 'write'),
30+
remove: hasPermission(schema, authLevels, 'remove'),
2431
});
25-
26-
// Freeze the object so this data can't be altered (even accidentally)
27-
Object.freeze(doc[permsKey]);
2832
}
2933

3034
module.exports = embedPermissions;

0 commit comments

Comments
 (0)