- permission trace correctly uses language variables now

- updated documentation for the auth class
- use cache for "SELECT forum_name FROM phpbb_forums WHERE forum_id = X" queries everywhere and not only in functions_display
- updated the permission trace to include information about global settings overwriting local ones
- take global permissions into account for local permission results on the view permission pages for users
- only allow to change the post author with m_chgposter


git-svn-id: file:///svn/phpbb/trunk@6009 89ea8834-ac86-4346-8a33-228a782c2dd0
This commit is contained in:
Nils Adermann 2006-06-04 16:30:58 +00:00
parent f3499d1251
commit 5c181bc528
9 changed files with 197 additions and 65 deletions

View file

@ -2,17 +2,19 @@
<div style="background-color: #fff; padding: 10px; margin-top: 10px;" class="permissions">
<h3>Trace for: {PERMISSION_USERNAME} / {PERMISSION}</h3>
<!-- IF U_BACK --><a href="{U_BACK}" style="float: right">&laquo; {L_BACK}</a><!-- ENDIF -->
<h3>{L_TRACE_FOR}: {PERMISSION_USERNAME} / <!-- IF FORUM_NAME -->{FORUM_NAME} / <!-- ENDIF -->{PERMISSION} </h3>
<br />
<table cellspacing="1" class="type1">
<thead>
<tr>
<th>Who</th>
<th style="width: 50px;">Setting</th>
<th style="width: 50px;">Total</th>
<th>Information</th>
<th>{L_TRACE_WHO}</th>
<th style="width: 50px;">{L_ACL_SETTING}</th>
<th style="width: 50px;">{L_TRACE_TOTAL}</th>
<th>{L_INFORMATION}</th>
</tr>
</thead>
<tbody>

View file

@ -1,21 +1,20 @@
<html>
<head>
<link rel="stylesheet" href="../templates/subSilver/subSilver.css" type="text/css" />
<link rel="stylesheet" href="../styles/subSilver/theme/stylesheet.css" type="text/css" />
<style type="text/css">
<!--
p,ul,td {font-size:10pt;}
h2 {font-size:15pt;font-weight:bold;color:red}
h3 {font-size:12pt;color:blue}
p {font-size:125%;}
pre {font-size:125%;line-height:150%;}
h2 {font-size:175%;color:red;padding-top:4px;}
h3 {font-size:150%;color:blue;padding-top:4px;}
p {padding-top:4px;padding-bottom:4px;}
//-->
</style>
</head>
<body bgcolor="#E5E5E5" text="#000000" link="#006699" vlink="#006699">
<table width="100%" border="0" cellspacing="0" cellpadding="10" align="center">
<tr>
<td class="bodyline"><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<body>
<a name="top"></a>
<div id="wrapcentre">
<h1>Using the <i><u>auth</u></i> class</h1>
@ -29,25 +28,29 @@ h3 {font-size:12pt;color:blue}
<pre>$auth = new auth();</pre>
<p>Once an instance of the object has been created you are free to call the various methods it contains. Please note that should you wish to use the <i><u>auth_admin</u></i> methods you will need to instantiate this seperately but in the same way.</p>
<p>Once an instance of the class has been created you are free to call the various methods it contains. Please note that should you wish to use the <i><u>auth_admin</u></i> methods you will need to instantiate this seperately but in the same way.</p>
<h3><i>acl</i></h3>
<p>The <i>acl</i> method is the initialisation routine for all the acl functions. If you intend calling any acl method you must first call this. The method takes as its one and only required parameter a hash of userdata. This hash must contain at least the following information; user_id, user_permissions and user_founder. It is called in the following way:
<p>The <i>acl</i> method is the initialisation routine for all the acl functions. If you intend calling any acl method you must first call this. The method takes as its one and only required parameter an associative array containing user information as stored in the database. This array must contain at least the following information; user_id, user_permissions and user_type. It is called in the following way:
<pre>$auth->acl(<i>userdata</i>);</pre>
<p>Where userdata is the hash containing the aforementioned data.</p>
<p>Where userdata is the array containing the aforementioned data.</p>
<h3><i>acl_get</i></h3>
<p>This method is the primary way of determining what a user can and cannot do for a given option in, optionally, a given forum. The method should be called in the following way:</p>
<p>This method is the primary way of determining what a user can and cannot do for a given option globally or in a given forum. The method should be called in the following way:</p>
<pre>$result = $auth->acl_get(<i>option</i>[, <i>forum</i>]);</pre>
<p>Where option is a string representing the required option, e.g. 'f_list', 'm_edit', 'a_adduser', etc. The optional forum term is the integer forum_id.</p>
<p>Where option is a string representing the required option, e.g. 'f_list', 'm_edit', 'a_adduser', etc. By adding a ! in front of the option, e.g. '!f_list' the result of this method will be negated. The optional forum term is the integer forum_id.</p>
<pThe method returns a positive integer when the user is allowed to carry out the option and a zero if denied.</p>
<p>The method returns a positive integer when the user is allowed to carry out the option and a zero if denied or the other way around if the option is prefixed with an exclamation mark.</p>
<p>If you specify a forum and there is also a global setting for the specified option then this method will return a positive integer if one of them evaluates to a positive integer. An example would be the m_approve option which can be set per forum but also globally. If a user has the global option he will automatically have m_approve in every forum.</p>
<p>There are some special options or <i>flags</i> which are used as prefixes for other options, e.g. 'f_' or 'm_'. These flags will automatically be set to a positive integer if the user has one or more permissions with the given prefix. A local setting will result in the flag being set only locally (so it will require a forum id to retrieve). If a user has one or more global permissions with the prefix acl_get will return a positive integer regardless of the forum id.</p>
<h3><i>acl_gets</i></h3>
@ -59,17 +62,41 @@ h3 {font-size:12pt;color:blue}
<p>As with the <i>acl_get</i> method the options are strings representing the required permissions to check. The forum again is an integer representing a given forum_id.</p>
<p>The method will return a positive integer if acl_get for one of the options evaluates to a positive integer (combines permissions with OR).</p>
<h3><i>acl_getf</i></h3>
<p>This method is used to find out in which forums a user is allowed to carry out an operation or to find out in which forums he is not allowed to carry out an operation. The method should be called in the following way:</p>
<pre>$result = $auth->acl_getf(<i>option</i>[, <i>clean</i>])</pre>
<p>Just like in the <i>acl_get</i> method the option is a string specifying the permission which has to be checked (negation using ! is allowed). The second parameter is a boolean. If it is set to false this method returns all forums with either zero or a positive integer. If it is set to true only those forums with a positive integer as the result will be returned.</p>
<p>The method returns an associative array of the form:</p>
<pre>array(<i>forum_id1</i> => array(<i>option</i> => <i>integer</i>), <i>forum_id2</i> => ...)</pre>
<p>Where option is the option passed to the method and integer is either zero or a positive integer and the same <i>acl_get(option, forum_id)</i> would return.</p>
<h3><i>acl_getf_global</i></h3>
<p>This method is used to find out whether a user has a permission in at least one forum or globally. This method is similar to checking whether <i>acl_getf(option, true)</i> returned one or more forums but it's faster. It should be called in the following way:</p>
<pre>$result = acl_getf_global(<i>option</i>)</pre>
<p>As with the previous methods option is a string specifying the permission which has to be checked.</p>
<p>This method returns either zero or a positive integer.</p>
<h3><i>acl_cache</i></h3>
<p>This should be considered a private method and not be called externally. It handles the generation of the user_permissions data from the basic user and group authorisation data. When necessary this method is called automatically by <i>acl</i>.</p>
<h3><i>login</i></h3>
<p></p>
<h2>Admin related functions</h2>
<p>A number of additional methods are available related to <i><u>auth</u></i>. These handle more basic functions such as adding user and group permissions, new options and clearing the user cache. These methods are contained within a seperate class, <i><u>auth_admin</u></i>. This can be found in the functions_admin source.</p>
<p>A number of additional methods are available related to <i><u>auth</u></i>. These handle more basic functions such as adding user and group permissions, new options and clearing the user cache. These methods are contained within a seperate class, <i><u>auth_admin</u></i>. This can be found in includes/acp/auth.php.</p>
<p>To use any methods this class contains it first needs to be instantiated seperately from <i><u>auth</u></i>. This is achieved in the same way as <i><u>auth</u></i>:</p>
@ -77,12 +104,7 @@ h3 {font-size:12pt;color:blue}
<p>This instance gives you access to both the methods of this specific class and that of <i><u>auth</u></i>.</p>
</td>
</tr>
</table></td>
</tr>
</table>
</div>
</body>
</html>

View file

@ -86,7 +86,7 @@ class acm
include($this->cache_dir . $entry);
if ($expired)
{
unlink($this->cache_dir . $entry);
@unlink($this->cache_dir . $entry);
}
}
@closedir($dir);
@ -174,7 +174,7 @@ class acm
if (preg_match('#/\*.*?\W' . $regex . '\W.*?\*/#s', $file, $m))
{
unlink($this->cache_dir . $entry);
@unlink($this->cache_dir . $entry);
}
}
@closedir($dir);
@ -271,7 +271,7 @@ class acm
}
else if ($expired)
{
unlink($this->cache_dir . 'sql_' . md5($query) . ".$phpEx");
@unlink($this->cache_dir . 'sql_' . md5($query) . ".$phpEx");
return false;
}

View file

@ -913,21 +913,44 @@ class acp_permissions
{
global $db, $template, $user, $auth;
$sql = 'SELECT user_id, username, user_type
FROM ' . USERS_TABLE . '
WHERE user_id = ' . $user_id;
$result = $db->sql_query($sql);
$user_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($user_id != $user->data['user_id'])
{
$sql = 'SELECT user_id, user_permissions, user_type
FROM ' . USERS_TABLE . '
WHERE user_id = ' . $user_id;
$result = $db->sql_query($sql);
$userdata = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
}
else
{
$userdata = $user->data;
}
if (!$user_row)
if (!$userdata)
{
trigger_error('NO_USERS');
}
$forum_name = false;
if ($forum_id)
{
$sql = 'SELECT forum_name
FROM ' . FORUMS_TABLE . "
WHERE forum_id = $forum_id";
$result = $db->sql_query($sql, 3600);
$forum_name = $db->sql_fetchfield('forum_name', false, $result);
$db->sql_freeresult($result);
}
$back = request_var('back', 0);
$template->assign_vars(array(
'PERMISSION' => $user->lang['acl_' . $permission]['lang'],
'PERMISSION_USERNAME' => $user_row['username'])
'PERMISSION_USERNAME' => $userdata['username'],
'FORUM_NAME' => $forum_name,
'U_BACK' => ($back) ? build_url(array('f', 'back')) . "&amp;f=$back" : '')
);
$template->assign_block_vars('trace', array(
@ -1023,19 +1046,56 @@ class acp_permissions
}
$template->assign_block_vars('trace', array(
'WHO' => $user_row['username'],
'WHO' => $userdata['username'],
'INFORMATION' => $information,
'S_SETTING_UNSET' => ($auth_setting == ACL_UNSET) ? true : false,
'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false,
'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false,
'S_TOTAL_UNSET' => ($total == ACL_UNSET) ? true : false,
'S_TOTAL_UNSET' => false,
'S_TOTAL_YES' => ($total == ACL_YES) ? true : false,
'S_TOTAL_NO' => ($total == ACL_NO) ? true : false)
);
// global permission might overwrite local permission
if (($forum_id != 0) && isset($auth->acl_options['global'][$permission]))
{
if ($user_id != $user->data['user_id'])
{
$auth2 = new auth();
$auth2->acl($userdata);
$auth_setting = $auth2->acl_get($permission);
}
else
{
$auth_setting = $auth->acl_get($permission);
}
if ($auth_setting)
{
$information = ($total == ACL_YES) ? $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_YES'] : $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_NO'];
$total = ACL_YES;
}
else
{
$information = $user->lang['TRACE_USER_GLOBAL_NO_TOTAL_KEPT'];
}
$template->assign_block_vars('trace', array(
'WHO' => sprintf($user->lang['TRACE_GLOBAL_SETTING'], $userdata['username']),
'INFORMATION' => sprintf($information, '<a href="' . $this->u_action . "&amp;u=$user_id&amp;f=0&amp;auth=$permission&amp;back=$forum_id\">", '</a>'),
'S_SETTING_UNSET' => false,
'S_SETTING_YES' => $auth_setting,
'S_SETTING_NO' => !$auth_setting,
'S_TOTAL_UNSET' => false,
'S_TOTAL_YES' => ($total == ACL_YES) ? true : false,
'S_TOTAL_NO' => ($total == ACL_NO) ? true : false)
);
}
// Take founder status into account, overwriting the default values
if ($user_row['user_type'] == USER_FOUNDER && strpos($permission, 'a_') === 0)
if ($userdata['user_type'] == USER_FOUNDER && strpos($permission, 'a_') === 0)
{
$template->assign_block_vars('trace', array(
'WHO' => $user_row['username'],

View file

@ -546,7 +546,7 @@ class acp_users
$sql = 'SELECT forum_name
FROM ' . FORUMS_TABLE . "
WHERE forum_id = $new_forum_id";
$result = $db->sql_query($sql);
$result = $db->sql_query($sql, 3600);
$forum_info = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

View file

@ -85,9 +85,10 @@ class auth_admin extends auth
*/
function get_mask($mode, $user_id = false, $group_id = false, $forum_id = false, $auth_option = false, $scope = false, $acl_fill = ACL_NO)
{
global $db;
global $db, $user;
$hold_ary = array();
$view_user_mask = ($mode == 'view' && $group_id === false) ? true : false;
if ($auth_option === false || $scope === false)
{
@ -96,19 +97,61 @@ class auth_admin extends auth
$acl_user_function = ($mode == 'set') ? 'acl_user_raw_data' : 'acl_raw_data';
if ($forum_id !== false)
if (!$view_user_mask)
{
$hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', $forum_id) : $this->$acl_user_function($user_id, $auth_option . '%', $forum_id);
}
else
{
$hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', ($scope == 'global') ? 0 : false) : $this->$acl_user_function($user_id, $auth_option . '%', ($scope == 'global') ? 0 : false);
if ($forum_id !== false)
{
$hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', $forum_id) : $this->$acl_user_function($user_id, $auth_option . '%', $forum_id);
}
else
{
$hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', ($scope == 'global') ? 0 : false) : $this->$acl_user_function($user_id, $auth_option . '%', ($scope == 'global') ? 0 : false);
}
}
// Make sure hold_ary is filled with every setting (prevents missing forums/users/groups)
$ug_id = ($group_id !== false) ? ((!is_array($group_id)) ? array($group_id) : $group_id) : ((!is_array($user_id)) ? array($user_id) : $user_id);
$forum_ids = ($forum_id !== false) ? ((!is_array($forum_id)) ? array($forum_id) : $forum_id) : (($scope == 'global') ? array(0) : array());
// Only those options we need
$compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array(''));
if ($view_user_mask)
{
$auth2 = null;
$sql = 'SELECT user_id, user_permissions, user_type
FROM ' . USERS_TABLE . '
WHERE user_id IN (' . implode(',', $ug_id) . ')';
$result = $db->sql_query($sql);
while ($userdata = $db->sql_fetchrow($result))
{
if ($user->data['user_id'] != $user_id)
{
$auth2 = new auth();
$auth2->acl($userdata);
}
else
{
global $auth;
$auth2 = &$auth;
}
$hold_ary[$userdata['user_id']] = array();
foreach ($forum_ids as $f_id)
{
$hold_ary[$userdata['user_id']][$f_id] = array();
foreach ($compare_options as $option)
{
$hold_ary[$userdata['user_id']][$f_id][$option] = $auth2->acl_get($option, $f_id);
}
}
}
$db->sql_freeresult($result);
unset($userdata);
unset($auth2);
}
// If forum_ids is false and the scope is local we actually want to have all forums within the array
if ($scope == 'local' && !sizeof($forum_ids))
{
@ -141,9 +184,6 @@ class auth_admin extends auth
// Now, we need to fill the gaps with $acl_fill. ;)
// Only those options we need
$compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array(''));
// Now switch back to keys
if (sizeof($compare_options))
{
@ -422,7 +462,7 @@ class auth_admin extends auth
$title = ($role_description) ? ' title="' . $role_description . '"' : '';
$s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_row['role_name'] . '</option>';
}
if ($s_role_options)
{
$s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . '>' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options;

View file

@ -1721,7 +1721,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr
$sql = 'SELECT forum_name
FROM ' . FORUMS_TABLE . "
WHERE forum_id = $forum_id";
$result = $db->sql_query($sql);
$result = $db->sql_query($sql, 3600);
if ($row = $db->sql_fetchrow($result))
{

View file

@ -74,7 +74,7 @@ function mcp_post_details($id, $mode, $action)
trigger_error($user->lang['NO_USER']);
}
if ($auth->acl_get('m_', $post_info['forum_id']))
if ($auth->acl_get('m_chgposter', $post_info['forum_id']))
{
change_poster($post_info, $row);
}
@ -104,14 +104,14 @@ function mcp_post_details($id, $mode, $action)
'U_APPROVE_ACTION' => "{$phpbb_root_path}mcp.$phpEx$SID&amp;i=queue&amp;p=$post_id",
'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']),
'S_CAN_CHGPOSTER' => $auth->acl_get('m_', $post_info['forum_id']),
'S_CAN_CHGPOSTER' => $auth->acl_get('m_chgposter', $post_info['forum_id']),
'S_CAN_LOCK_POST' => $auth->acl_get('m_lock', $post_info['forum_id']),
'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']),
'S_POST_REPORTED' => ($post_info['post_reported']) ? true : false,
'S_POST_UNAPPROVED' => (!$post_info['post_approved']) ? true : false,
'S_POST_LOCKED' => ($post_info['post_edit_locked']) ? true : false,
'S_USER_NOTES' => ($auth->acl_gets('m_', 'a_')) ? true : false,
'S_USER_NOTES' => true,
'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false,
'U_FIND_MEMBER' => "{$phpbb_root_path}memberlist.$phpEx$SID&amp;mode=searchuser&amp;form=mcp_chgposter&amp;field=username",

View file

@ -159,24 +159,32 @@ $lang = array_merge($lang, array(
'SET_USERS_FORUM_PERMISSIONS' => 'Set users forum permissions',
'TRACE_DEFAULT' => 'By default every permission is UNSET. So the permission can be overwritten by other settings.',
'TRACE_FOR' => 'Trace for',
'TRACE_GLOBAL_SETTING' => '%s (global)',
'TRACE_GROUP_NO_TOTAL_NO' => 'This group\'s permission is set to NO like the total result so the old result is kept.',
'TRACE_GROUP_NO_TOTAL_UNSET' => 'This group\'s permission is set to NO which becomes the new total value because it wasn\'t set yet.',
'TRACE_GROUP_NO_TOTAL_YES' => 'This group\'s permission is set to NO which overwrites the total YES to a NO for this user.',
'TRACE_GROUP_UNSET' => 'The permission is UNSET for this group so the old total value is kept.',
'TRACE_GROUP_YES_TOTAL_NO' => 'This group\'s permission is set to YES but the total NO cannot be overwritten.',
'TRACE_GROUP_YES_TOTAL_UNSET' => 'This group\'s permission is set to YES which becomes the new total value because it wasn\'t set yet.',
'TRACE_GROUP_YES_TOTAL_YES' => 'This group\'s permission is set to YES, and the total permission is already set to YES, so the total result is kept.',
'TRACE_GROUP_YES_TOTAL_YES' => 'This group\'s permission is set to YES and the total permission is already set to YES, so the total result is kept.',
'TRACE_PERMISSION' => 'Trace permission - %s',
'TRACE_SETTING' => 'Trace setting',
'TRACE_USER_GLOBAL_YES_TOTAL_YES' => 'The forum independent user permission evaluates to YES but the total permission is already set to YES, so the the total result is kept. %sTrace global permission%s',
'TRACE_USER_GLOBAL_YES_TOTAL_NO' => 'The forum independent user permission evaluates to YES which overwrites the current local result NO. %sTrace global permission%s',
'TRACE_USER_GLOBAL_NO_TOTAL_KEPT' => 'The forum independent user permission evaluates to NO which doesn\'t influence the local permission. %sTrace global permission%s',
'TRACE_USER_FOUNDER' => 'The user has the founder type set, therefore admin permissions are set to YES by default.',
'TRACE_USER_KEPT' => 'The user permission is UNSET so the old total value is kept.',
'TRACE_USER_NO_TOTAL_NO' => 'The user permission is set to no and the total value is set to no, so nothing is changed.',
'TRACE_USER_NO_TOTAL_UNSET' => 'The user permission is set to no which becomes the total value because it wasn\'t set yet.',
'TRACE_USER_NO_TOTAL_YES' => 'The user permission is set to no and overwrites the previous yes.',
'TRACE_USER_NO_TOTAL_NO' => 'The user permission is set to NO and the total value is set to NO, so nothing is changed.',
'TRACE_USER_NO_TOTAL_UNSET' => 'The user permission is set to NO which becomes the total value because it wasn\'t set yet.',
'TRACE_USER_NO_TOTAL_YES' => 'The user permission is set to NO and overwrites the previous YES.',
'TRACE_USER_UNSET_TOTAL_UNSET' => 'The user permission is UNSET and the total value wasn\'t set yet so it defaults to NO.',
'TRACE_USER_YES_TOTAL_NO' => 'The user permission is set to yes but the total no cannot be overwritten.',
'TRACE_USER_YES_TOTAL_NO' => 'The user permission is set to YES but the total NO cannot be overwritten.',
'TRACE_USER_YES_TOTAL_UNSET' => 'The user permission is set to YES which becomes the total value because it wasn\'t set yet.',
'TRACE_USER_YES_TOTAL_YES' => 'The user permission is set to YES and the total value is set to YES, so nothing is changed.',
'TRACE_WHO' => 'Who',
'TRACE_TOTAL' => 'Total',
'USERS_NOT_ASSIGNED' => 'No user assigned to this role',
'USER_IS_MEMBER_OF_DEFAULT' => 'is a member of the following default groups',