The attached php files contain code changes that extends the permission granularity of 'Public' pages to 'Semi-public' and 'Private' pages. These files are being posted for those who want to test out the concept of a wiki capable of more flexible restrictions. Hopefully, it will help determine what could be changed in the current UI to make a complex restriction UI easy and/or intuitive to work with.
These files do not create or use functions, features, or methods that were not already available through the Deki API. The only significant change is that a grant's role will be saved according to the role associated with a user or group instead of being set to a default value ($wgDefaultRestrictRole). I've tested it on my dev box, believe it is running without major issues, and that using it will not damage the wiki.
Disclaimer: This code is functional and safe to the best of my knowledge, however, it is not an official modification and you are ultimately responsible for dealing with the result of any changes to your wiki. This code was written for experimental purposes, and I do not recommend it for a 'live' wiki.
Simple example case that demonstrates the new functionality (hopefully, it makes sense):
Group info:
| Group | Role | Members |
| Group1 | Viewer | User1, User2 |
| Group2 | Contributor | User2 |
Case 1: Private page, grant list = Group1
| User | Role |
| User1 | Viewer |
| User2 | Viewer |
Case 2: Private page, grant list = Group1, Group2
| User | Role |
| User1 | Viewer |
| User2 | Contributor |
Simply extract the php files to your '<deki>/web/includes' directory. You may want to rename the original files before hand:
Change notes:
The original version used DreamUserManagement.php and DreamGroupManagement.php to call wfResetRestrictions. However, that approach resulted in the grants being rewritten for every single group or user update. I moved the call to AdminGroups.php and AdminUsers.php so that the wiki is only updated once. This was neccessary mostly because of the poor speed design of wfResetRestrictions. Sorry, but I still haven't made an attempt to increase the reset's overall speed yet. The original version of wfResetRestrictions would post a 'Permissions updated' for every page that was touched. The new version is modified to only report a single time once the update is finished.
The method has been redesigned slightly. The main difference is that triggering a full grant reset is manually done on the Authentication sub-page of deki-cp.
Extract the following files to your wiki directory. Renaming/archiving the original files is recommended:
Change notes:
This version puts grant resets in the hands of the admin now. Simply navigate to the Authentication page of the control panel, and there should be a sub-section that triggers a grant reset. All of the logic for the reset is contained in the updated authentication.php file. I attempted to minimize the amount of API calls to improve speed (it gathers all of the needed data using MySQL). Unfortunately, it turns out that most of the time sink is within the API call to update the page grants. Pages which require a grant update take an average of about 10 times longer to process than ones which don't (each API call ranged from ~40ms to over 200ms on my dev PC). Fortunately, if a page requires no updates, the API call only takes a few ms (ranged from 4ms to 8ms for me).
Grant information, including the role value of each grant, is stored as part of each page's data. This allows for very complex and varied permissions throughout the wiki. Until the new code is executed, all existing grants in your wiki will have the default value assigned by the normal method. The modified code looks up the role associated with each user or group that is being given a grant and saves that specific role; the default variable is not used at all.
There are only two events that will trigger the new code:
Triggering a grant reset is the way to push a grant update to many pages automatically. The 8.05.2b code only touches pages off the main branch, but the 8.08 version touches the grants of any currently existing page with restriction data (deleted pages will not be updated). It is much quicker than opening and saving each set of page grants manually. Unfortunately, this function is a very ugly, brute force answer to the issue of getting the wiki grants updated. It may take a significant amount of time for large wikis. My test setup took about 30 seconds for 300 pages and 3+ grants per page in 8.08 with every page being updated. It runs considerably quicker if a page doesn't need to be updated, taking about 3 seconds if all 300 pages are up to date.
Note: the performance hit is primarily due to MySQL settings. Setting MySQL to use log file caching will improve the time for the grant reset and many other database commits... however, it kills ACID compliance and isn't recommended for sites with critical data.
# If set to 1, InnoDB will flush (fsync) the transaction logs to the # disk at each commit, which offers full ACID behavior. If you are # willing to compromise this safety, and you are running small # transactions, you may set this to 0 or 2 to reduce disk I/O to the # logs. Value 0 means that the log is only written to the log file and # the log file flushed to disk approximately once per second. Value 2 # means the log is written to the log file at each commit, but the log # file is only flushed to disk approximately once per second. innodb_flush_log_at_trx_commit=1
It is possible to use the modified code to undo the grant changes to your wiki. Returning your wiki to a state of default grant roles requires editing the new php code. The original role assignment code is still present, but simply commented out. Follow these steps to return the wiki to a normal state:
$grants = array();
$groups = array_unique($groups);
$users = array_unique($users);
//foreach ($users as $userId)
//{
// $grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'user' => array('@id' => $userId));
//}
//foreach ($groups as $groupId)
//{
// $grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'group' => array('@id' => $groupId));
//}
foreach ($users as $userId)
{
$role = new DreamUserManagement();
$grants[] = array('permissions' => array('role' => $role->getById($userId)->GetRole()->GetName()), 'user' => array('@id' => $userId));
}
foreach ($groups as $groupId)
{
$role = new DreamGroupManagement();
$grants[] = array('permissions' => array('role' => $role->getById($groupId)->GetRole()->GetName()), 'group' => array('@id' => $groupId));
}
$grants = array();
$groups = array_unique($groups);
$users = array_unique($users);
foreach ($users as $userId)
{
$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'user' => array('@id' => $userId));
}
foreach ($groups as $groupId)
{
$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'group' => array('@id' => $groupId));
}
//foreach ($users as $userId)
//{
// $role = new DreamUserManagement();
// $grants[] = array('permissions' => array('role' => $role->getById($userId)->GetRole()->GetName()), 'user' => array('@id' => $userId));
//}
//foreach ($groups as $groupId)
//{
// $role = new DreamGroupManagement();
// $grants[] = array('permissions' => array('role' => $role->getById($groupId)->GetRole()->GetName()), 'group' => array('@id' => $groupId));
//}
//foreach ($users as $userId)
//{
// $grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'user' => array('@id' => $userId));
//}
//foreach ($groups as $groupId)
//{
// $grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'group' => array('@id' => $groupId));
//}
foreach ($users as $userId)
{
$role = new DreamUserManagement();
$grants[] = array('permissions' => array('role' => $role->getById($userId)->GetRole()->GetName()), 'user' => array('@id' => $userId));
}
foreach ($groups as $groupId)
{
$role = new DreamGroupManagement();
$grants[] = array('permissions' => array('role' => $role->getById($groupId)->GetRole()->GetName()), 'group' => array('@id' => $groupId));
}
foreach ($users as $userId)
{
$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'user' => array('@id' => $userId));
}
foreach ($groups as $groupId)
{
$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'group' => array('@id' => $groupId));
}
//foreach ($users as $userId)
//{
// $role = new DreamUserManagement();
// $grants[] = array('permissions' => array('role' => $role->getById($userId)->GetRole()->GetName()), 'user' => array('@id' => $userId));
//}
//foreach ($groups as $groupId)
//{
// $role = new DreamGroupManagement();
// $grants[] = array('permissions' => array('role' => $role->getById($groupId)->GetRole()->GetName()), 'group' => array('@id' => $groupId));
//}
foreach ($pages[$pid]['grants'] as $grant)
{
if (strncmp($grant, 'g', 1) == 0)
{
$grants[] = array('permissions' => array('role' => $group_roles[substr($grant, 1)]), 'group' => array('@id' => substr($grant, 1)));
//$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'group' => array('@id' => substr($grant, 1)));
}
else
{
$grants[] = array('permissions' => array('role' => $user_roles[substr($grant, 1)]), 'user' => array('@id' => substr($grant, 1)));
//$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'user' => array('@id' => substr($grant, 1)));
}
}
foreach ($pages[$pid]['grants'] as $grant)
{
if (strncmp($grant, 'g', 1) == 0)
{
//$grants[] = array('permissions' => array('role' => $group_roles[substr($grant, 1)]), 'group' => array('@id' => substr($grant, 1)));
$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'group' => array('@id' => substr($grant, 1)));
}
else
{
//$grants[] = array('permissions' => array('role' => $user_roles[substr($grant, 1)]), 'user' => array('@id' => substr($grant, 1)));
$grants[] = array('permissions' => array('role' => $wgDefaultRestrictRole), 'user' => array('@id' => substr($grant, 1)));
}
}
I'm not one of the people responsible for final development and approval of the Deki software. However, I am one of the people who would like to see an improved version of the existing restriction model. The current permission system is up for redesign in the Lyons release. Please share any ideas for improvements on this page.
If you have any questions or problems specifically about this mod, send me a PM and I'll do my best to help.
| File | Size | Date | Attached by | |||
|---|---|---|---|---|---|---|
| restrict_mod.zip Restriction Modifications - 8.05.2b Base | 36.56 kB | 16:05, 15 Aug 2008 | anbrcyp | Actions | ||
| restrict_mod_8_08.zip Mod for 8.08; redesign to trigger from deki-cp. | 27.21 kB | 00:25, 9 Oct 2008 | anbrcyp | Actions | ||
Well, I have read your disclaimer - but this functionality is quite essential for us and the first version of the patch still works fine.
We circumvent this issue with simply not using the "grant reset" function - this is fine as long as the roles of users and groups are not modified (this is no problem for us).