fix: live query role cache does not clear when a user is added to a role (#8026)

This commit is contained in:
dblythy
2022-06-11 18:21:55 +10:00
committed by GitHub
parent 0cd902b8c2
commit 199dfc1722
6 changed files with 108 additions and 2 deletions

View File

@@ -10,7 +10,13 @@ import { ParsePubSub } from './ParsePubSub';
import SchemaController from '../Controllers/SchemaController';
import _ from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { runLiveQueryEventHandlers, getTrigger, runTrigger, resolveError, toJSONwithObjects } from '../triggers';
import {
runLiveQueryEventHandlers,
getTrigger,
runTrigger,
resolveError,
toJSONwithObjects,
} from '../triggers';
import { getAuthForSessionToken, Auth } from '../Auth';
import { getCacheController } from '../Controllers';
import LRU from 'lru-cache';
@@ -71,6 +77,7 @@ class ParseLiveQueryServer {
this.subscriber = ParsePubSub.createSubscriber(config);
this.subscriber.subscribe(Parse.applicationId + 'afterSave');
this.subscriber.subscribe(Parse.applicationId + 'afterDelete');
this.subscriber.subscribe(Parse.applicationId + 'clearCache');
// Register message handler for subscriber. When publisher get messages, it will publish message
// to the subscribers and the handler will be called.
this.subscriber.on('message', (channel, messageStr) => {
@@ -82,6 +89,10 @@ class ParseLiveQueryServer {
logger.error('unable to parse message', messageStr, e);
return;
}
if (channel === Parse.applicationId + 'clearCache') {
this._clearCachedRoles(message.userId);
return;
}
this._inflateParseObject(message);
if (channel === Parse.applicationId + 'afterSave') {
this._onAfterSave(message);
@@ -468,6 +479,32 @@ class ParseLiveQueryServer {
return matchesQuery(parseObject, subscription.query);
}
async _clearCachedRoles(userId: string) {
try {
const validTokens = await new Parse.Query(Parse.Session)
.equalTo('user', Parse.User.createWithoutData(userId))
.find({ useMasterKey: true });
await Promise.all(
validTokens.map(async token => {
const sessionToken = token.get('sessionToken');
const authPromise = this.authCache.get(sessionToken);
if (!authPromise) {
return;
}
const [auth1, auth2] = await Promise.all([
authPromise,
getAuthForSessionToken({ cacheController: this.cacheController, sessionToken }),
]);
auth1.auth?.clearRoleCache(sessionToken);
auth2.auth?.clearRoleCache(sessionToken);
this.authCache.del(sessionToken);
})
);
} catch (e) {
logger.verbose(`Could not clear role cache. ${e}`);
}
}
getAuthForSessionToken(sessionToken: ?string): Promise<{ auth: ?Auth, userId: ?string }> {
if (!sessionToken) {
return Promise.resolve({});
@@ -574,7 +611,6 @@ class ParseLiveQueryServer {
if (!acl_has_roles) {
return false;
}
const roleNames = await auth.getUserRoles();
// Finally, see if any of the user's roles allow them read access
for (const role of roleNames) {