On a recent project we were asked to use Coveo for Sitecore. Content on the site is gated and require a user to authenticate, request access. To improve user experience, we built a search driven interface using Coveo. We quickly learned that Coveo uses a security cache to maintain lists of relationships between all the security entities (users and groups) for all the indexed repositories. When a user queries an index CES uses the security cache to quickly determine the user permissions and therefore return only documents the user is allowed to see.
It is a great solution to speed up query response time. However, one major limitation is that the cache needs to be updated to capture changes in permissions and new accounts created.
In our case this meant that the user would have to wait for the next security cache update before they could see and download resources. So we started searching for options
Out of the box Coveo provides two methods to update security cache
- Manual – https://onlinehelp.coveo.com/en/ces/7.0/administrator/refreshing_security_caches.htm
- Scheduled task – https://onlinehelp.coveo.com/en/ces/7.0/administrator/modifying_system_schedules.htm. The default is once a day
Neither of these options, worked for us as there is no ideal cache update frequency we could define and manual was out of question. So we turned to Coveo support and asked if we could do it programmatically. The reply was to run the following VB Script programmatically. (https://answers.coveo.com/questions/4259/how-to-programatically-update-security-cache)
Option Explicit Dim Admin: Set Admin = GetAdmin() Admin.UpdateFileSecurityCache(true) Function GetAdmin() Set GetAdmin = CreateObject("CESAdmin.Admin.7.0") Call GetAdmin.Connect("localhost", "default") Call GetAdmin.Refresh() End Function
So now we had a way to programmatically trigger a cache update. The next step was to ensure we only trigger it when a user is added to a role.
Here is how we did it
- Created a custom database to capture events. We could have used the event queue, but we did not want to lose any data to an external job, such as event queue cleanup etc.
- Created an event handler “UserRolesUpdatedHandler”. The handler simply writes an entry into our custom database.
- Added the handler to “roles:usersAdded” and “roles:usersRemoved” events
- Next we created a scheduled task that runs every two minutes, checks if a user was added or removed from a role. If it finds an entry it triggers cache update
Note: we also had to impersonate a local administrator, as the com object that the VB Script is using would not execute without adequate permissions.
Hope this helps. Leave me a note if you would like to get more details or code for this.