[xwiki-devs] How to invalidate security cache?
I have XWiki and a separate app. I need to use my app permissions in XWiki. XWiki uses security cache and asks my app for a particular permission only once. I need to make XWiki aware about permission changes in my app. I have several options: 1. sometimes I invalidate cache in my application. I could call xwiki api to invalidate the whole xwiki cache when I invalidate my app cache. 2. from time to time (say, every minute) make a REST call to my app. My app says if cache was invalidated. If it was I would like to invalidate xwiki cache. My questions are: 1. how to invalidate the whole cache? I implemented CustomSecurityCacheInvalidator, but it seems like I can remove only separate entities there via `remove` call. As I understand I have to call `suspend` and then remove entities from the cache and then call `resume`, right? But SecurityCache has only `get` and `remove` methods for separate entities. 2. should I create a separate `Component` for scheduler which will poll data from my app from time to time? I could start new thread there to ask my app on schedule and Inject CustomSecurityCacheInvalidator. Is it the right approach? My class is here: @Component @Singleton public class CustomSecurityCacheInvalidator extends DefaultSecurityCacheRulesInvalidator { @Inject private SecurityCache securityCache; @Override public void suspend() { System.out.println("suspend!"); super.suspend(); //I can use securityCache here } @Override public void resume() { System.out.println("resume!"); super.resume(); } } -- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com.
Hi Andrey, On Fri, Apr 22, 2016 at 11:34 AM, abtv <[email protected]> wrote:
I have XWiki and a separate app. I need to use my app permissions in XWiki. XWiki uses security cache and asks my app for a particular permission only once. I need to make XWiki aware about permission changes in my app.
I have several options: 1. sometimes I invalidate cache in my application. I could call xwiki api to invalidate the whole xwiki cache when I invalidate my app cache. 2. from time to time (say, every minute) make a REST call to my app. My app says if cache was invalidated. If it was I would like to invalidate xwiki cache.
My questions are: 1. how to invalidate the whole cache? I implemented CustomSecurityCacheInvalidator, but it seems like I can remove only separate entities there via `remove` call. As I understand I have to call `suspend` and then remove entities from the cache and then call `resume`, right? But SecurityCache has only `get` and `remove` methods for separate entities.
No you are wrong, the suspend / resume method that you have to implement will be called by the SecurityCacheLoader to inform your invalidator to suspend his work. This happen each time the cache is affected. When you evict a reference in the cache, you will effectively evict all its dependencies… for example if you evict a space, all the documents in that space are evicted as well, if you evict a user, all access decisions made previously for that user is evicted, if you evict a group, all user of that group (and therefore access decisions for those users) will be evicted. Emptying the cache is equivalent to evicting the main wiki (farm). The reference to the main wiki (farm) is easy to build, just pass a null reference to the security reference factory.
2. should I create a separate `Component` for scheduler which will poll data from my app from time to time? I could start new thread there to ask my app on schedule and Inject CustomSecurityCacheInvalidator. Is it the right approach?
Well, the best would be that your external service trigger your invalidator maybe through a REST service that generate events. If you base your work on events, it is event easier, because you just have to override the SecurityCacheRulesInvalidatorListener, and the suspend>resume aspect will be managed for you. You just have to listen to your own event, that your REST service would generate. To create a REST service in XWiki, this could be as easy as writing a scripted XWiki page for example. Regarding events and listener, you can read: http://extensions.xwiki.org/xwiki/bin/view/Extension/Observation+Module+Loca... Regards,
My class is here:
@Component @Singleton public class CustomSecurityCacheInvalidator extends DefaultSecurityCacheRulesInvalidator {
@Inject private SecurityCache securityCache;
@Override public void suspend() { System.out.println("suspend!"); super.suspend();
//I can use securityCache here }
@Override public void resume() { System.out.println("resume!"); super.resume(); } }
-- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
-- Denis Gervalle SOFTEC sa - CEO
I haven't found SecurityCacheRulesInvalidatorListener class/interface and implemented it in the following (code below). Can I clean cache like this? public class CleanCacheEvent extends AbstractWikiEvent { public CleanCacheEvent(){ super(); } } @Component @Named("SecurityCacheRulesInvalidatorListener") @Singleton public class CustomSecurityCacheRulesInvalidatorListener extends AbstractEventListener { @Inject private SecurityCache securityCache; @Inject private SecurityReferenceFactory securityReferenceFactory; public CustomSecurityCacheRulesInvalidatorListener() { super("SecurityCacheRulesInvalidatorListener", new CleanCacheEvent()); } public void onEvent(Event event, Object source, Object data) { System.out.println("on invalidator listener event"); SecurityReference root = securityReferenceFactory.newEntityReference(null); securityCache.remove(root); System.out.println("cache was cleaned"); } } -- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com.
Hi Andrey, Here it is: https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwik... This is the listener you need to replace, and you need to care about the readWriteLock mechanism in place in the original version. For the rest, your implementation looks ok, but it is harsh to clean the whole cache, and it would be better to be more granular if possible (at least per wiki, per user, per group, per space…, regarding the per group case, be careful of the special case adding a user to a group introduce, since you also need to drop that new user in addition to the group it joins). Regards, On Mon, Apr 25, 2016 at 6:37 PM, abtv <[email protected]> wrote:
I haven't found SecurityCacheRulesInvalidatorListener class/interface and implemented it in the following (code below). Can I clean cache like this?
public class CleanCacheEvent extends AbstractWikiEvent { public CleanCacheEvent(){ super(); } }
@Component @Named("SecurityCacheRulesInvalidatorListener") @Singleton public class CustomSecurityCacheRulesInvalidatorListener extends AbstractEventListener { @Inject private SecurityCache securityCache;
@Inject private SecurityReferenceFactory securityReferenceFactory;
public CustomSecurityCacheRulesInvalidatorListener() { super("SecurityCacheRulesInvalidatorListener", new CleanCacheEvent()); }
public void onEvent(Event event, Object source, Object data) { System.out.println("on invalidator listener event"); SecurityReference root = securityReferenceFactory.newEntityReference(null); securityCache.remove(root); System.out.println("cache was cleaned"); } }
-- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
-- Denis Gervalle SOFTEC sa - CEO
Hi Denis! Did you inserted code example to show how to use ReadWriteLock in place? Or I should override the default class? I just added ReadWriteLock, is it ok? There is my final solution with Listener and it works on my machine: I added the following to components.txt: 0:com.myproject.xwiki.cache.CustomSecurityCacheRulesInvalidatorListener @Component @Named("SecurityCacheRulesInvalidatorListener") @Singleton public class CustomSecurityCacheRulesInvalidatorListener extends AbstractEventListener { @Inject @Named(DefaultSecurityCacheRulesInvalidator.NAME) private ReadWriteLock readWriteLock; @Inject private SecurityCache securityCache; @Inject private SecurityReferenceFactory securityReferenceFactory; public CustomSecurityCacheRulesInvalidatorListener() { super(DefaultSecurityCacheRulesInvalidator.NAME, new CleanCacheEvent()); } public void onEvent(Event event, Object source, Object data) { System.out.println("invalidating xwiki cache"); readWriteLock.writeLock().lock(); try { SecurityReference root = securityReferenceFactory.newEntityReference(null); securityCache.remove(root); } finally { readWriteLock.writeLock().unlock(); } } } -- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com.
Hi Andrey, Looks good to me. Regards, On Wed, Apr 27, 2016 at 5:53 PM, abtv <[email protected]> wrote:
Hi Denis!
Did you inserted code example to show how to use ReadWriteLock in place? Or I should override the default class? I just added ReadWriteLock, is it ok?
There is my final solution with Listener and it works on my machine:
I added the following to components.txt: 0:com.myproject.xwiki.cache.CustomSecurityCacheRulesInvalidatorListener
@Component @Named("SecurityCacheRulesInvalidatorListener") @Singleton public class CustomSecurityCacheRulesInvalidatorListener extends AbstractEventListener { @Inject @Named(DefaultSecurityCacheRulesInvalidator.NAME) private ReadWriteLock readWriteLock; @Inject private SecurityCache securityCache;
@Inject private SecurityReferenceFactory securityReferenceFactory;
public CustomSecurityCacheRulesInvalidatorListener() { super(DefaultSecurityCacheRulesInvalidator.NAME, new CleanCacheEvent()); }
public void onEvent(Event event, Object source, Object data) { System.out.println("invalidating xwiki cache"); readWriteLock.writeLock().lock(); try { SecurityReference root = securityReferenceFactory.newEntityReference(null); securityCache.remove(root); } finally { readWriteLock.writeLock().unlock(); } } }
-- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
-- Denis Gervalle SOFTEC sa - CEO
Great thanks! -- View this message in context: http://xwiki.475771.n2.nabble.com/How-to-invalidate-security-cache-tp7599138... Sent from the XWiki- Dev mailing list archive at Nabble.com.
participants (2)
-
abtv -
Denis Gervalle