Item14810: Programmatic calls to Foswiki::Func::saveTopic may fail to update DBCache
Priority: Normal
Current State: New
Released In: n/a
Target Release: n/a
Programmatically calling Foswiki::Func::saveTopic with ignorepermissions option set to create a new topic in a restricted web will fail to update DBCache unless the Foswiki object has been initialized with a default user that has permission to read the web.
I'm sorry that creating a stand alone test case from my code is rather complex, so I hope I can describe what I'm seeing well enough that someone will know how to fix it.
I have a web with view, change and rename permission restricted to a group of users. In the web are a form topic and a template topic with the form attached to it. My perl script creates a new topic in the web by reading the template topic (Foswiki::Func::readTopic) and creating the new topic via Foswiki::Func::saveTopic. In pseudo code:
$Foswiki::cfg{Engine} = 'Foswiki::Engine::CLI';
require Foswiki;
$my wikiSession = Foswiki->new();
my ($meta, $template) = Foswiki::Func::readTopic('Web', 'templateTopic');
# Save the updated topic
Foswiki::Func::saveTopic('Web', 'Topic', $meta, $template, {
ignorepermissions => 1,
forcenewrevision => 1,
author => 'SomeUser'
});
After the call to saveTopic, the new topic exists on disk, but a call to DBQuery that should match the topic will not find it. Rebuilding the cache (
./rest /DBCachePlugin/updateCache
) makes the topic findable.
I've tracked the issue down to a permission error bubbling up through
DBCacheContrib.pm around line 581 from _loadTopic: (site specific information removed)
lib/Foswiki/Contrib/DBCacheContrib.pm line 582.
Foswiki::Contrib::DBCacheContrib::_updateTopic(Foswiki::Plugins::DBCachePlugin::WebDB=HASH(0x451c5d0), "Web", "Topic") called at lib/Foswiki/Contrib/DBCacheContrib.pm line 537
eval {...} called at lib/Foswiki/Contrib/DBCacheContrib.pm line 537
Foswiki::Contrib::DBCacheContrib::loadTopic(Foswiki::Plugins::DBCachePlugin::WebDB=HASH(0x451c5d0), "Web", "Topic") called at lib/Foswiki/Plugins/DBCachePlugin/Core.pm line 94
Foswiki::Plugins::DBCachePlugin::Core::afterSaveHandler(Foswiki::Plugins::DBCachePlugin::Core=HASH(0x4143ba8), "Web", "topic") called at lib/Foswiki/Plugins/DBCachePlugin.pm line 195
Foswiki::Plugins::DBCachePlugin::afterSaveHandler("%META:TOPICINFO{author=\"SomeUser\" comment=\"\" date=\"154756485"..., "Topic", "Web", undef, Foswiki::Meta=HASH(0x40c6520)) called at lib/Foswiki/Plugin.pm line 311
Foswiki::Plugin::invoke(Foswiki::Plugin=HASH(0x28a53c0), "afterSaveHandler", "%META:TOPICINFO{author=\"SomeUser\" comment=\"\" date=\"154756485"..., "Topic", "Web", undef, Foswiki::Meta=HASH(0x40c6520)) called at lib/Foswiki/Plugins.pm line 376
Foswiki::Plugins::dispatch(Foswiki::Plugins=HASH(0x1c41080), "afterSaveHandler", "%META:TOPICINFO{author=\"SomeUser\" comment=\"\" date=\"154756485"..., "Topic", "Web", undef, Foswiki::Meta=HASH(0x40c6520)) called at lib/Foswiki/Meta.pm line 2016
Foswiki::Meta::save(Foswiki::Meta=HASH(0x40c6520), "author", "SomeUser", "forcenewrevision", 1, "ignorepermissions", 1) called at lib/Foswiki/Func.pm line 2115
Foswiki::Func::saveTopic("Web", "Topic", Foswiki::Meta=HASH(0x40b87b0), "..."..., HASH(0x40c6460)) called at save2wiki.pl line xxx
The Foswiki log also shows this message:
| 2019-01-15T10:01:04-05:00 warning | Foswiki::Contrib::DBCacheContrib | DBCache: Cache read failed: AccessControlException: Access to VIEW Web.Form for BaseUserMapping_666 is denied. access denied on web |
The fundamental problem seems to be that the process for updating the cache is sensitive to the permissions of the current user, so although the save operation ignores permissions, the cache update does not and that causes the two states to lose synchronization.
There is a work around: set "AdminUser" as the default when initializing Foswiki (
Foswiki->new('AdminUser')
).
--
PaulMerchantJr - 15 Jan 2019
Which settings have you got for
{DBCachePlugin}
as well as
{DBCacheContrib}
?
--
MichaelDaum - 15 Jan 2019
$Foswiki::cfg{DBCacheContrib}{AlwaysUpdateCache} = 0;
$Foswiki::cfg{DBCacheContrib}{Archivist} = 'Foswiki::Contrib::DBCacheContrib::Archivist::Segmentable';
$Foswiki::cfg{DBCacheContrib}{LoadFileLimit} = '0';
$Foswiki::cfg{DBCachePlugin}{MemoryCache} = 1;
$Foswiki::cfg{DBCachePlugin}{UseUploadHandler} = 0;
$Foswiki::cfg{Plugins}{DBCachePlugin}{Enabled} = 1;
$Foswiki::cfg{Plugins}{DBCachePlugin}{Module} = 'Foswiki::Plugins::DBCachePlugin';
--
PaulMerchantJr - 15 Jan 2019
Actually, any script executing Foswiki from the command line does run as admin user. Home comes this is not the case for you? Further more, how are you able to view the topic when you don't have access rights to it? Or is it an unrelated topic not directly addressed by your call to
saveTopic
?
In any other case, your "work around" is correct: initializing the Foswiki object as admin user. I don't see an action item here otherwise. Please reopen if there is anything else we can do about it.
--
MichaelDaum - 16 Apr 2019
Interesting, my configuration does not appear to have a "DefaultUserName" which may explain the difference. At any rate, the main issue is the inconsistent behavior between the fundamental "Save" code which honors the "ignorepermissions" flag and the
DBCachePlugin which does not even see that flag. I'm not sure "ignore permissions" is even a good concept to include in the "saveTopic" API, particularly if the flag isn't passed on to all the components that might be invoked during a save. It feels like a kludge. Running as user "admin" is an alternative way for a script to ignore the permissions, works uniformly across all the components, and at least to me has a clearer set of implications. When should code running as a non-admin user be able to ignore permissions? My suggestion would be to simplify the API by eliminating the "ignorepermissions" flag, and just rely on the conventional user permissions exclusively. No doubt that'll break something, though, as I see it used in Listy and
MetaComment in my site.
--
PaulMerchantJr - 22 Apr 2019