Do cache of settings and permissions

pull/3483/merge
Rodrigo Nascimento 9 years ago
parent c65f526375
commit 3b7b8062d3
No known key found for this signature in database
GPG Key ID: 2C85B3AFE75D23F9
  1. 1
      client/routes/router.coffee
  2. 2
      lib/fileUpload.coffee
  3. 2
      packages/rocketchat-authorization/client/hasPermission.coffee
  4. 5
      packages/rocketchat-authorization/client/lib/ChatPermissions.coffee
  5. 2
      packages/rocketchat-authorization/client/startup.coffee
  6. 32
      packages/rocketchat-authorization/server/publications/permissions.js
  7. 8
      packages/rocketchat-integrations/client/route.coffee
  8. 2
      packages/rocketchat-integrations/client/startup.coffee
  9. 111
      packages/rocketchat-lib/client/lib/cachedCollection.js
  10. 17
      packages/rocketchat-lib/client/lib/settings.coffee
  11. 24
      packages/rocketchat-lib/package.js
  12. 6
      packages/rocketchat-lib/server/models/Settings.coffee
  13. 48
      packages/rocketchat-lib/server/publications/settings.coffee
  14. 2
      packages/rocketchat-ui-master/server/fastRender.js
  15. 33
      packages/rocketchat-ui/lib/RoomManager.coffee
  16. 4
      packages/rocketchat-ui/lib/collections.coffee
  17. 1
      packages/rocketchat-ui/views/app/secretURL.coffee
  18. 2
      server/publications/subscription.coffee

@ -9,7 +9,6 @@ FlowRouter.subscriptions = ->
RoomManager.init()
@register 'userData', Meteor.subscribe('userData')
@register 'activeUsers', Meteor.subscribe('activeUsers')
@register 'admin-settings', Meteor.subscribe('admin-settings')
FlowRouter.route '/',

@ -64,6 +64,6 @@ if UploadFS?
initFileStore()
else
Tracker.autorun (c) ->
if Meteor.userId() and RocketChat.settings.subscription.ready()
if Meteor.userId() and RocketChat.settings.cachedCollection.ready.get()
initFileStore()
c.stop()

@ -29,7 +29,7 @@ hasPermission = (permissions, scope, strategy) ->
unless userId
return false
unless RocketChat.authz.subscription.ready()
unless RocketChat.authz.cachedCollection.ready.get()
return false
permissions = [].concat permissions

@ -1 +1,4 @@
@ChatPermissions = new Meteor.Collection 'rocketchat_permissions'
RocketChat.authz.cachedCollection = new RocketChat.CachedCollection({ name: 'permissions', methodName: 'getPermissions', eventName: 'permissions-changed', eventType: 'onAll' })
@ChatPermissions = RocketChat.authz.cachedCollection.collection
RocketChat.authz.cachedCollection.init()

@ -1,7 +1,5 @@
Meteor.subscribe 'roles'
RocketChat.authz.subscription = Meteor.subscribe 'permissions'
RocketChat.AdminBox.addOption
href: 'admin-permissions'
i18nLabel: 'Permissions'

@ -1,3 +1,31 @@
Meteor.publish('permissions', function() {
return RocketChat.models.Permissions.find({});
Meteor.methods({
getPermissions() {
this.unblock();
return RocketChat.models.Permissions.find().fetch();
}
});
let subscriptionsReady = false;
RocketChat.models.Settings.findNotHidden().observe({
added(record) {
if (subscriptionsReady) {
RocketChat.Notifications.notifyAll('permissions-changed', 'added', record);
}
},
changed(record) {
if (subscriptionsReady) {
RocketChat.Notifications.notifyAll('permissions-changed', 'changed', record);
}
},
removed(record) {
if (subscriptionsReady) {
RocketChat.Notifications.notifyAll('permissions-changed', 'removed', { _id: record._id });
}
}
});
subscriptionsReady = true;

@ -1,5 +1,7 @@
FlowRouter.route '/admin/integrations',
name: 'admin-integrations'
subscriptions: (params, queryParams) ->
this.register 'integrations', Meteor.subscribe('integrations')
action: (params) ->
RocketChat.TabBar.showGroup 'admin-integrations'
BlazeLayout.render 'main',
@ -9,6 +11,8 @@ FlowRouter.route '/admin/integrations',
FlowRouter.route '/admin/integrations/new',
name: 'admin-integrations-new'
subscriptions: (params, queryParams) ->
this.register 'integrations', Meteor.subscribe('integrations')
action: (params) ->
RocketChat.TabBar.showGroup 'admin-integrations'
BlazeLayout.render 'main',
@ -18,6 +22,8 @@ FlowRouter.route '/admin/integrations/new',
FlowRouter.route '/admin/integrations/incoming/:id?',
name: 'admin-integrations-incoming'
subscriptions: (params, queryParams) ->
this.register 'integrations', Meteor.subscribe('integrations')
action: (params) ->
RocketChat.TabBar.showGroup 'admin-integrations'
BlazeLayout.render 'main',
@ -28,6 +34,8 @@ FlowRouter.route '/admin/integrations/incoming/:id?',
FlowRouter.route '/admin/integrations/outgoing/:id?',
name: 'admin-integrations-outgoing'
subscriptions: (params, queryParams) ->
this.register 'integrations', Meteor.subscribe('integrations')
action: (params) ->
RocketChat.TabBar.showGroup 'admin-integrations'
BlazeLayout.render 'main',

@ -1,5 +1,3 @@
Meteor.subscribe 'integrations'
RocketChat.AdminBox.addOption
href: 'admin-integrations'
i18nLabel: 'Integrations'

@ -0,0 +1,111 @@
/* globals localforage */
class CachedCollection {
constructor({
collection,
name,
methodName,
eventName,
eventType = 'onUser',
sync = true,
debug = true
}) {
this.collection = collection || new Meteor.Collection(null);
this.ready = new ReactiveVar(false);
this.name = name;
this.methodName = methodName || name;
this.eventName = eventName || name;
this.eventType = eventType;
this.sync = sync;
this.debug = debug;
}
log(...args) {
if (this.debug === true) {
console.log(...args);
}
}
loadFromCache(callback = () => {}) {
localforage.getItem(this.name, (error, data) => {
if (data && data.records) {
this.log(`CachedCollection ${this.name} => ${data.records.length} records loaded from cache`);
data.records.forEach((item) => {
item.__cache__ = true;
this.collection.insert(item);
});
callback(true);
} else {
callback(false);
}
});
}
loadFromServer(callback = () => {}) {
Meteor.call(this.methodName, (error, data) => {
this.log(`CachedCollection ${this.name} => ${data.length} records loaded from server`);
data.forEach((item) => {
const _id = item._id;
delete item._id;
this.collection.upsert({ _id: _id }, item);
item._id = _id;
});
callback(data);
});
}
loadFromServerAndPopulate(clearCache = false) {
this.loadFromServer((loadedData) => {
if (clearCache === true) {
this.collection.remove({ __cache__: true });
}
this.ready.set(true);
this.saveCache(loadedData);
});
}
saveCache(data) {
localforage.setItem(this.name, {
updatedAt: new Date,
records: data
});
}
setupListener(eventType, eventName) {
RocketChat.Notifications[eventType || this.eventType](eventName || this.eventName, (t, record) => {
if (t === 'removed') {
this.collection.remove(record._id);
} else {
const _id = record._id;
delete record._id;
this.collection.upsert({ _id: _id }, record);
}
});
}
init() {
this.loadFromCache((cacheLoaded) => {
this.ready.set(cacheLoaded);
if (cacheLoaded === false) {
// If there is no cache load data immediately
this.loadFromServerAndPopulate();
} else if (this.sync === true) {
// If there is cache wait for an empty queue to load data again and sync
const interval = Meteor.setInterval(() => {
if (Meteor.connection._outstandingMethodBlocks.length === 0) {
Meteor.clearInterval(interval);
this.loadFromServerAndPopulate(true);
}
}, 500);
}
this.setupListener();
});
}
}
RocketChat.CachedCollection = CachedCollection;

@ -3,9 +3,22 @@
# @namespace RocketChat.settings
###
@Settings = new Meteor.Collection 'rocketchat_settings'
RocketChat.settings.cachedCollection = new RocketChat.CachedCollection({ name: 'public-settings', methodName: 'getPublicSettings', eventName: 'public-settings-changed', eventType: 'onAll' })
@Settings = RocketChat.settings.cachedCollection.collection
RocketChat.settings.subscription = Meteor.subscribe 'settings'
RocketChat.settings.cachedCollection.init()
Tracker.autorun (c) ->
if Meteor.userId()?
c.stop()
RocketChat.settings.cachedCollectionPrivate = new RocketChat.CachedCollection({
collection: RocketChat.settings.cachedCollection.collection,
name: 'private-settings',
methodName: 'getPrivateSettings',
eventName: 'private-settings-changed',
eventType: 'onAll'
})
RocketChat.settings.cachedCollectionPrivate.init()
RocketChat.settings.dict = new ReactiveDict 'settings'

@ -51,10 +51,21 @@ Package.onUse(function(api) {
api.addFiles('lib/Message.coffee');
api.addFiles('lib/MessageTypes.coffee');
api.addFiles('server/lib/RateLimiter.coffee', 'server');
// SERVER FUNCTIONS
api.addFiles('server/functions/checkUsernameAvailability.coffee', 'server');
api.addFiles('server/functions/checkEmailAvailability.js', 'server');
api.addFiles('server/functions/deleteUser.js', 'server');
api.addFiles('server/functions/sendMessage.coffee', 'server');
api.addFiles('server/functions/settings.coffee', 'server');
api.addFiles('server/functions/setUsername.coffee', 'server');
api.addFiles('server/functions/setEmail.js', 'server');
api.addFiles('server/functions/Notifications.coffee', 'server');
// SERVER LIB
api.addFiles('server/lib/defaultBlockedDomainsList.js', 'server');
api.addFiles('server/lib/notifyUsersOnMessage.js', 'server');
api.addFiles('server/lib/RateLimiter.coffee', 'server');
api.addFiles('server/lib/roomTypes.coffee', 'server');
api.addFiles('server/lib/sendEmailOnMessage.js', 'server');
api.addFiles('server/lib/sendNotificationsOnMessage.js', 'server');
@ -73,16 +84,6 @@ Package.onUse(function(api) {
// SERVER PUBLICATIONS
api.addFiles('server/publications/settings.coffee', 'server');
// SERVER FUNCTIONS
api.addFiles('server/functions/checkUsernameAvailability.coffee', 'server');
api.addFiles('server/functions/checkEmailAvailability.js', 'server');
api.addFiles('server/functions/deleteUser.js', 'server');
api.addFiles('server/functions/sendMessage.coffee', 'server');
api.addFiles('server/functions/settings.coffee', 'server');
api.addFiles('server/functions/setUsername.coffee', 'server');
api.addFiles('server/functions/setEmail.js', 'server');
api.addFiles('server/functions/Notifications.coffee', 'server');
// SERVER METHODS
api.addFiles('server/methods/addOAuthService.coffee', 'server');
api.addFiles('server/methods/checkRegistrationSecretURL.coffee', 'server');
@ -115,6 +116,7 @@ Package.onUse(function(api) {
// CLIENT LIB
api.addFiles('client/lib/localforage.min.js', 'client');
api.addFiles('client/lib/cachedCollection.js', 'client');
api.addFiles('client/lib/openRoom.coffee', 'client');
api.addFiles('client/lib/roomExit.coffee', 'client');
api.addFiles('client/lib/settings.coffee', 'client');

@ -51,6 +51,12 @@ RocketChat.models.Settings = new class extends RocketChat.models._Base
return @find filter, { fields: _id: 1, value: 1 }
findNotHiddenPrivate: ->
return @find {
hidden: { $ne: true }
public: { $ne: true }
}
findNotHidden: ->
return @find { hidden: { $ne: true } }

@ -1,12 +1,42 @@
Meteor.publish 'settings', (ids = []) ->
return RocketChat.models.Settings.findNotHiddenPublic(ids)
Meteor.methods
getPublicSettings: ->
this.unblock()
Meteor.publish 'admin-settings', ->
unless @userId
return @ready()
return RocketChat.models.Settings.findNotHiddenPublic().fetch()
if RocketChat.authz.hasPermission( @userId, 'view-privileged-setting')
return RocketChat.models.Settings.findNotHidden()
else
return @ready()
getPrivateSettings: ->
unless Meteor.userId()
return []
this.unblock()
if not RocketChat.authz.hasPermission Meteor.userId(), 'view-privileged-setting'
return []
return RocketChat.models.Settings.findNotHiddenPrivate().fetch()
subscriptionsReady = false
RocketChat.models.Settings.findNotHidden().observe
added: (record) ->
if subscriptionsReady
e = if record.public is true then 'public-settings-changed' else 'private-settings-changed'
RocketChat.Notifications.notifyAll e, 'added', record
changed: (record) ->
if subscriptionsReady
e = if record.public is true then 'public-settings-changed' else 'private-settings-changed'
RocketChat.Notifications.notifyAll e, 'changed', record
removed: (record) ->
if subscriptionsReady
e = if record.public is true then 'public-settings-changed' else 'private-settings-changed'
RocketChat.Notifications.notifyAll e, 'removed', { _id: record._id }
subscriptionsReady = true
RocketChat.Notifications.streamAll.allowRead 'private-settings-changed', ->
if not @userId? then return false
return RocketChat.authz.hasPermission @userId, 'view-privileged-setting'

@ -1,6 +1,6 @@
/* globals FastRender */
FastRender.onAllRoutes(function(/*path*/) {
this.subscribe('settings');
// this.subscribe('settings');
this.subscribe('meteor.loginServiceConfiguration');
});

@ -50,41 +50,16 @@ Tracker.autorun ->
@RoomManager = new class
openedRooms = {}
subscriptionReady = new ReactiveVar
msgStream = new Meteor.Streamer 'room-messages'
onlineUsers = new ReactiveVar {}
Dep = new Tracker.Dependency
init = ->
if subscriptionReady.get()
if CachedChatSubscription.ready.get()
return
localforage.getItem 'subscription', (error, data) ->
if data?.records?
subscriptionReady.set true
for item in data.records
ChatSubscription.insert(item)
Meteor.call 'subscriptions', (error, data) ->
subscriptionReady.set true
for item in data
_id = item._id
delete item._id
ChatSubscription.upsert({_id: _id}, item)
localforage.setItem('subscription', {
updatedAt: new Date
records: ChatSubscription.find().fetch()
})
RocketChat.Notifications.onUser 'subscription-change', (type, record) ->
if type is 'removed'
ChatSubscription.remove(record._id)
else
_id = record._id
delete record._id
ChatSubscription.upsert({_id: _id}, record)
CachedChatSubscription.init()
return
@ -127,7 +102,7 @@ Tracker.autorun ->
if record.ready is true
return
ready = record.sub[0].ready() and subscriptionReady.get()
ready = record.sub[0].ready() and CachedChatSubscription.ready.get() is true
if ready is true
type = typeName.substr(0, 1)
@ -197,7 +172,7 @@ Tracker.autorun ->
if openedRooms[typeName].ready
closeOlderRooms()
if subscriptionReady.get() && Meteor.userId()
if CachedChatSubscription.ready.get() is true && Meteor.userId()
if openedRooms[typeName].active isnt true
openedRooms[typeName].active = true

@ -1,6 +1,8 @@
@ChatMessage = new Meteor.Collection null
@ChatRoom = new Meteor.Collection 'rocketchat_room'
@ChatSubscription = new Meteor.Collection null
@CachedChatSubscription = new RocketChat.CachedCollection({ name: 'subscription', methodName: 'subscriptions', eventName: 'subscription-change' })
@ChatSubscription = CachedChatSubscription.collection
@UserRoles = new Mongo.Collection null
@RoomRoles = new Mongo.Collection null
@UserAndRoom = new Meteor.Collection null

@ -7,7 +7,6 @@ Template.secretURL.helpers
Template.secretURL.onCreated ->
@subscribe 'admin-settings'
@hashIsValid = new ReactiveVar false
@hashReady = new ReactiveVar false

@ -3,6 +3,8 @@ Meteor.methods
unless Meteor.userId()
return []
this.unblock()
options =
fields:
t: 1

Loading…
Cancel
Save