diff --git a/src/LiveQuery/ParseLiveQueryServer.js b/src/LiveQuery/ParseLiveQueryServer.js index 545b0d325c..dda6628c15 100644 --- a/src/LiveQuery/ParseLiveQueryServer.js +++ b/src/LiveQuery/ParseLiveQueryServer.js @@ -9,6 +9,10 @@ import { matchesQuery, queryHash } from './QueryTools'; import { ParsePubSub } from './ParsePubSub'; import { SessionTokenCache } from './SessionTokenCache'; import _ from 'lodash'; +import { loadAdapter } from '../Adapters/AdapterLoader'; +import { InMemoryCacheAdapter } from '../Adapters/Cache/InMemoryCacheAdapter'; +import { CacheController } from '../Controllers/CacheController'; +import RedisCacheAdapter from '../Adapters/Cache/RedisCacheAdapter'; class ParseLiveQueryServer { clientId: number; @@ -19,6 +23,7 @@ class ParseLiveQueryServer { keyPairs : any; // The subscriber we use to get object update from publisher subscriber: Object; + cacheController: any; constructor(server: any, config: any) { this.clientId = 0; @@ -45,6 +50,11 @@ class ParseLiveQueryServer { const masterKey = config.masterKey || Parse.masterKey; Parse.initialize(appId, javascriptKey, masterKey); + // Initialize cache + + const cacheControllerAdapter = loadAdapter(config.cacheAdapter, InMemoryCacheAdapter, {appId: appId}); + this.cacheController = new CacheController(cacheControllerAdapter, appId); + // Initialize websocket server this.parseWebSocketServer = new ParseWebSocketServer( server, @@ -362,17 +372,28 @@ class ParseLiveQueryServer { // Then get the user's roles var rolesQuery = new Parse.Query(Parse.Role); rolesQuery.equalTo("users", user); - return rolesQuery.find({useMasterKey:true}); + + // fallback to direct query + if (!this.cacheController) { + return rolesQuery.find({useMasterKey:true}); + } + + // use redis cache + return this.cacheController.role.get(user.id).then((roles) => { + if (roles != null) { + return roles.map(role => role.replace(/^role:/, '')); + } + return rolesQuery.find({useMasterKey:true}).then( roles => { + this.cacheController.role.put(user.id, roles.map(role => 'role:' + role.getName())); + return roles; + }) + }) + }). then((roles) => { // Finally, see if any of the user's roles allow them read access - for (const role of roles) { - if (acl.getRoleReadAccess(role)) { - return resolve(true); - } - } - resolve(false); + return resolve(!!~roles.findIndex(role => acl.getRoleReadAccess(role))); }) .catch((error) => { reject(error);