Skip to content

Role cache #3974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions src/LiveQuery/ParseLiveQueryServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand Down