Skip to content

Commit 6601f13

Browse files
committed
Updates to post save permissions updates
Previously, if you did a `find()` with permissions, then did a save on that doc with `{ authLevel: false }`, the resulting document would still have the original permissions and it would not reflect the latest data in the document. This change stores the query options used for the find query in the document at find time. Then, if you take an action that skips authz, the permissions in the doc will be recalculated using those original options.
1 parent 46567b3 commit 6601f13

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

index.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,17 @@ module.exports = (schema, installationOptions) => {
112112
// is to have arguments to the middleware function. If we have arguments, mongoose
113113
// assume we want to use a `next()` function. FML
114114
schema.pre('save', function preSave(next, options) {
115-
// Embed the options into the doc so we have access to them in post save hooks
116-
this[docOptionsSymbol] = options;
115+
// If we don't have options saved in the doc already, put whatever options
116+
// we have now in there. This way there are always options saved in the doc.
117+
if (!this[docOptionsSymbol]) this[docOptionsSymbol] = options;
118+
119+
// If auth is disabled, don't store the options in the doc. This will leave options
120+
// that have been stored when the doc was retrieved (if any).
117121
if (authIsDisabled(options)) { return next(); }
118122

123+
// Okay, we are not disabled, so definitely use these options going forward.
124+
this[docOptionsSymbol] = options;
125+
119126
return save(this, options)
120127
.then(() => next())
121128
.catch(next);
@@ -145,10 +152,26 @@ module.exports = (schema, installationOptions) => {
145152
});
146153
schema.post('find', async function postFind(docs) {
147154
if (authIsDisabled(this.options)) { return; }
155+
156+
// Store the options in the doc in case we do a write operation later on.
157+
// If that write skips authz checks, it'll be able to use these options to
158+
// recalculate permissions.
159+
if (this.options && docs && docs.forEach) {
160+
docs.forEach((doc) => { doc[docOptionsSymbol] = this.options; });
161+
}
162+
148163
await find(this, docs);
149164
});
150165
schema.post('findOne', async function postFindOne(doc) {
151166
if (authIsDisabled(this.options)) { return; }
167+
168+
// Store the options in the doc in case we do a write operation later on.
169+
// If that write skips authz checks, it'll be able to use these options to
170+
// recalculate permissions.
171+
if (this.options && doc) {
172+
doc[docOptionsSymbol] = this.options;
173+
}
174+
152175
await find(this, doc);
153176
});
154177
schema.pre('update', async function preUpdate() {

0 commit comments

Comments
 (0)