What are permission masks?
Masks are the effective permissions your user has for the different type of permission as we described already. You have user permissions, moderator permissions both local & global, forum permissions & administrator permissions. So for each of these you have a permission mask which can be viewed in the ACP. For forum permissions & moderator local permissions you need to select the forum you want to check first.
How do I workout permission masks?
From the "PERMISSIONS" tab select from "View administrative permissions", "View user-based permissions", "View global moderation permissions", "View forum moderation permissions" & "View forum-based permissions". If you select either of the last two you will first need to select the forum for which you are trying to view for. When viewing masks you can view for multiple/single user(s) or group(s). Permission for a group are set. However since permissions for a user can come from multiple groups you can trace the permission.
What is tracing a permission?
When viewing the mask of permissions for a user a icon( Image) appears beside each option will show how the option got its value. It will start with the default value and then work through each group the user is a member of and then also the user direct permission at the end. For each group or finally the user permission it looks at the setting and updates the total. Remember a NEVER will wipe out any YES and a YES can not overwrite a NEVER. This is a very handy tool to determine why a user is getting or not getting a permission. The final total is the effective permission for any option.
How do permissions get setup for a page when a user views it?
When a users (remember bots & guests are still users) views a page a session is started with $user->session_begin(); Next you call the following $auth->acl($user->data); this will setup the users permission. This $auth->acl function checks to work out if the user_permission field we mentioned early needs updated. When permissions are updated via the ACP this field is cleared. If you only set a user permission then only that user has it clear otherwise it is cleared for all users. So on next login the acl function has to repopulate it with new permission options for user. It first checks the cache for _acl_options and updates if needed and then rebuilds the users permissions. Else if the cache is OK but the user permissions is empty it rebuilds just the users permissions. If the cache is OK and the user permissions is OK the field is left alone. The field is then turned from a bitstring into an array and it is this array we check against when checking a users permissions.
So what does the acl_options cache contain?
This cache contains an array which has two elements - local & global. Each of these is an array that contains each of the acl options of that type. As with all cache it checks if the cache is within a valid time frame, if the time frame is OK it will setup the array else just return.
So now the page has my users permissions setup how do I check if a user has a single permission option?
You call the $auth->acl_get('u_garage_browse'); and the argument is the option you want to check for If it was specific to a forum (i.e local) then you do it as $auth->acl_get('u_garage_browse', 3); where 3 is the forum id
I have created a forum specific option. How do I find out which forums a user has this set for?
You call the $auth->acl_getf('f_your_permission');
Can I check for more than one option?
Yes. By using $auth->acl_gets(option1[, option2, ..., optionN, forum]);
How do I add a permission on my own for a MOD?
Firstly you need to understand there are two parts to adding a permission.
* Database
* Language
To add to the DB you should always use the native functions. As they handle cache etc..
- Code: Select all
<?php
define('IN_PHPBB', true);
$phpbb_root_path = './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
$user->session_begin();
$auth->acl($user->data);
$user->setup();
include($phpbb_root_path . 'includes/acp/auth.' . $phpEx);
$auth_admin = new auth_admin();
$auth_admin->acl_add_option(array(
'local' => array(),
'global' => array('u_your_mod', 'm_your_mod')
));
?>
- Code: Select all
<?php
if (empty($lang) || !is_array($lang))
{
$lang = array();
}
$lang['permission_cat']['your_mod'] = 'My amazing MOD';
$lang = array_merge($lang, array(
'acl_u_your_mod' => array('lang' => 'Can use amazing MOD', 'cat' => 'your_mod'),
'acl_m_your_mod' => array('lang' => 'Can moderate amazing MOD', 'cat' => 'your_mod'),
));
?>
How do I make my MOD installer setup permission automatically?
By default you can not. As we learnt above when phpBB updates permissions for users/groups/roles it works out the complete permissions and updates as a multi-insert. This approach is just too much for a MOD to try do. Please note this is not standard phpBB. A simple approach is to use functions such as the ones below. The functions check if the user/group/role already has the permission and if so does not insert it, if not it inserts the option and clears the cache. There are three functions provided below, one for user, group, role. Each works in the same way. First is whether you are granting or removing, then you pass a username, group name or role name as the second variable and an array of permissions you want to assign/remove as the third, a four variable sets the ACL_YES|ACL_NO|ACL_NEVER that we also talked about early.
- Code: Select all
<?php
//examples of granting user, group & role
update_user_permissions('grant', $username, array('u_your_mod', 'm_your_mod'));
update_group_permissions('grant',$group_name, array('u_your_mod', 'm_your_mod') );
update_role_permissions('grant',$role_name, array('u_your_mod', 'm_your_mod') );
//examples of removing user, group & role
update_user_permissions('remove', $username, array('u_your_mod', 'm_your_mod'));
update_group_permissions('remove',$group_name, array('u_your_mod', 'm_your_mod') );
update_role_permissions('remove',$role_name, array('u_your_mod', 'm_your_mod') );
?>
User Permission Update
- Code: Select all
<?php
/**
* Update role-specific ACL options. Function can grant or remove options. If option already granted it will NOT be updated.
*
* @param grant|remove $mode defines whether roles are granted to removed
* @param strong $role_name role name to update
* @param mixed $options auth_options to grant (a auth_option has to be specified)
* @param ACL_YES|ACL_NO|ACL_NEVER $auth_setting defines the mode acl_options are getting set with
*
*/
function update_user_permissions($mode = 'grant', $username, $options = array(), $auth_setting = ACL_YES)
{
global $db, $auth, $cache;
//First We Get User ID
$sql = "SELECT u.user_id
FROM " . USERS_TABLE . " u
WHERE username = '$username'";
$result = $db->sql_query($sql);
$user_id = (int) $db->sql_fetchfield('user_id');
$db->sql_freeresult($result);
//Now Lets Get All Current Options For User
$user_options = array();
$sql = "SELECT auth_option_id
FROM " . ACL_USERS_TABLE . "
WHERE user_id = " . (int) $user_id . "
GROUP BY auth_option_id";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$user_options[] = $row;
}
$db->sql_freeresult($result);
//Get Option ID Values For Options Granting Or Removing
$acl_options_ids = array();
$sql = "SELECT auth_option_id
FROM " . ACL_OPTIONS_TABLE . "
WHERE " . $db->sql_in_set('auth_option', $options) . "
GROUP BY auth_option_id";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$acl_options_ids[] = $row;
}
$db->sql_freeresult($result);
//If Granting Permissions
if ($mode == 'grant')
{
//Make Sure We Have Option IDs
if (empty($acl_options_ids))
{
return false;
}
//Build SQL Array For Query
$sql_ary = array();
for ($i = 0, $count = sizeof($acl_options_ids);$i < $count; $i++)
{
//If Option Already Granted To User Then Skip It
if (in_array($acl_options_ids[$i]['auth_option_id'], $user_options))
{
continue;
}
$sql_ary[] = array(
'user_id' => (int) $user_id,
'auth_option_id' => (int) $acl_options_ids[$i]['auth_option_id'],
'auth_setting' => $auth_setting,
);
}
$db->sql_multi_insert(ACL_USERS_TABLE, $sql_ary);
$cache->destroy('acl_options');
$auth->acl_clear_prefetch();
}
//If Removing Permissions
if ($mode == 'remove')
{
//Make Sure We Have Option IDs
if (empty($acl_options_ids))
{
return false;
}
//Process Each Option To Remove
for ($i = 0, $count = sizeof($acl_options_ids);$i < $count; $i++)
{
$sql = "DELETE
FROM " . ACL_USERS_TABLE . "
WHERE auth_option_id = " . $acl_options_ids[$i]['auth_option_id'];
$db->sql_query($sql);
}
$cache->destroy('acl_options');
$auth->acl_clear_prefetch();
}
return;
}
?>
Group Permission Update
- Code: Select all
<?php
/**
* Update group-specific ACL options. Function can grant or remove options. If option already granted it will NOT be updated.
*
* @param grant|remove $mode defines whether roles are granted to removed
* @param string $group_name group name to update
* @param mixed $options auth_options to grant (a auth_option has to be specified)
* @param ACL_YES|ACL_NO|ACL_NEVER $auth_setting defines the mode acl_options are getting set with
*
*/
function update_group_permissions($mode = 'grant', $group_name, $options = array(), $auth_setting = ACL_YES)
{
global $db, $auth, $cache;
//First We Get Role ID
$sql = "SELECT g.role_id
FROM " . GROUPS_TABLE . " g
WHERE group_name = '$group_name'";
$result = $db->sql_query($sql);
$group_id = (int) $db->sql_fetchfield('group_id');
$db->sql_freeresult($result);
//Now Lets Get All Current Options For Role
$group_options = array();
$sql = "SELECT auth_option_id
FROM " . ACL_GROUPS_TABLE . "
WHERE group_id = " . (int) $group_id . "
GROUP BY auth_option_id";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$group_options[] = $row;
}
$db->sql_freeresult($result);
//Get Option ID Values For Options Granting Or Removing
$sql = "SELECT auth_option_id
FROM " . ACL_OPTIONS_TABLE . "
WHERE " . $db->sql_in_set('auth_option', $options) . "
GROUP BY auth_option_id";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$acl_options_ids[] = $row;
}
$db->sql_freeresult($result);
//If Granting Permissions
if ($mode == 'grant')
{
//Make Sure We Have Option IDs
if (empty($acl_options_ids))
{
return false;
}
//Build SQL Array For Query
$sql_ary = array();
for ($i = 0, $count = sizeof($acl_options_ids);$i < $count; $i++)
{
//If Option Already Granted To Role Then Skip It
if (in_array($acl_options_ids[$i]['auth_option_id'], $group_options))
{
continue;
}
$sql_ary[] = array(
'group_id' => (int) $group_id,
'auth_option_id' => (int) $acl_options_ids[$i]['auth_option_id'],
'auth_setting' => $auth_setting,
);
}
$db->sql_multi_insert(ACL_GROUPS_TABLE, $sql_ary);
$cache->destroy('acl_options');
$auth->acl_clear_prefetch();
}
//If Removing Permissions
if ($mode == 'remove')
{
//Make Sure We Have Option IDs
if (empty($acl_options_ids))
{
return false;
}
//Process Each Option To Remove
for ($i = 0, $count = sizeof($acl_options_ids);$i < $count; $i++)
{
$sql = "DELETE
FROM " . ACL_GROUPS_TABLE . "
WHERE auth_option_id = " . $acl_options_ids[$i]['auth_option_id'];
$db->sql_query($sql);
}
$cache->destroy('acl_options');
$auth->acl_clear_prefetch();
}
return;
}
?>
Role Permission Update
- Code: Select all
<?php
/**
* Update role-specific ACL options. Function can grant or remove options. If option already granted it will NOT be updated.
*
* @param grant|remove $mode defines whether roles are granted to removed
* @param strong $role_name role name to update
* @param mixed $options auth_options to grant (a auth_option has to be specified)
* @param ACL_YES|ACL_NO|ACL_NEVER $auth_setting defines the mode acl_options are getting set with
*
*/
function update_role_permissions($mode = 'grant', $role_name, $options = array(), $auth_setting = ACL_YES)
{
global $db, $auth, $cache;
//First We Get Role ID
$sql = "SELECT r.role_id
FROM " . ACL_ROLES_TABLE . " r
WHERE role_name = '$role_name'";
$result = $db->sql_query($sql);
$role_id = (int) $db->sql_fetchfield('role_id');
$db->sql_freeresult($result);
//Now Lets Get All Current Options For Role
$role_options = array();
$sql = "SELECT auth_option_id
FROM " . ACL_ROLES_DATA_TABLE . "
WHERE role_id = " . (int) $role_id . "
GROUP BY auth_option_id";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$role_options[] = $row;
}
$db->sql_freeresult($result);
//Get Option ID Values For Options Granting Or Removing
$acl_options_ids = array();
$sql = "SELECT auth_option_id
FROM " . ACL_OPTIONS_TABLE . "
WHERE " . $db->sql_in_set('auth_option', $options) . "
GROUP BY auth_option_id";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$acl_options_ids[] = $row;
}
$db->sql_freeresult($result);
//If Granting Permissions
if ($mode == 'grant')
{
//Make Sure We Have Option IDs
if (empty($acl_options_ids))
{
return false;
}
//Build SQL Array For Query
$sql_ary = array();
for ($i = 0, $count = sizeof($acl_options_ids);$i < $count; $i++)
{
//If Option Already Granted To Role Then Skip It
if (in_array($acl_options_ids[$i]['auth_option_id'], $role_options))
{
continue;
}
$sql_ary[] = array(
'role_id' => (int) $role_id,
'auth_option_id' => (int) $acl_options_ids[$i]['auth_option_id'],
'auth_setting' => $auth_setting,
);
}
$db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary);
$cache->destroy('acl_options');
$auth->acl_clear_prefetch();
}
//If Removing Permissions
if ($mode == 'remove')
{
//Make Sure We Have Option IDs
if (empty($acl_options_ids))
{
return false;
}
//Process Each Option To Remove
for ($i = 0, $count = sizeof($acl_options_ids);$i < $count; $i++)
{
$sql = "DELETE
FROM " . ACL_ROLES_DATA_TABLE . "
WHERE auth_option_id = " . $acl_options_ids[$i]['auth_option_id'];
$db->sql_query($sql);
}
$cache->destroy('acl_options');
$auth->acl_clear_prefetch();
}
return;
}
?>