Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
33.33% |
4 / 12 |
CRAP | |
54.66% |
176 / 322 |
permission | |
0.00% |
0 / 1 |
|
33.33% |
4 / 12 |
485.45 | |
54.66% |
176 / 322 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
6 / 6 |
|||
get_name | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
exists | |
100.00% |
1 / 1 |
3 | |
100.00% |
13 / 13 |
|||
add | |
0.00% |
0 / 1 |
19.51 | |
54.35% |
25 / 46 |
|||
remove | |
100.00% |
1 / 1 |
7 | |
100.00% |
29 / 29 |
|||
role_add | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 19 |
|||
role_update | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 12 |
|||
role_remove | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 15 |
|||
permission_set | |
0.00% |
0 / 1 |
18.06 | |
94.44% |
51 / 54 |
|||
anonymous function | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
permission_unset | |
0.00% |
0 / 1 |
90 | |
0.00% |
0 / 54 |
|||
reverse | |
0.00% |
0 / 1 |
38.26 | |
34.38% |
11 / 32 |
<?php | |
/** | |
* | |
* This file is part of the phpBB Forum Software package. | |
* | |
* @copyright (c) phpBB Limited <https://www.phpbb.com> | |
* @license GNU General Public License, version 2 (GPL-2.0) | |
* | |
* For full copyright and license information, please see | |
* the docs/CREDITS.txt file. | |
* | |
*/ | |
namespace phpbb\db\migration\tool; | |
/** | |
* Migration permission management tool | |
*/ | |
class permission implements \phpbb\db\migration\tool\tool_interface | |
{ | |
/** @var \phpbb\auth\auth */ | |
protected $auth; | |
/** @var \phpbb\cache\service */ | |
protected $cache; | |
/** @var \phpbb\db\driver\driver_interface */ | |
protected $db; | |
/** @var string */ | |
protected $phpbb_root_path; | |
/** @var string */ | |
protected $php_ext; | |
/** | |
* Constructor | |
* | |
* @param \phpbb\db\driver\driver_interface $db | |
* @param \phpbb\cache\service $cache | |
* @param \phpbb\auth\auth $auth | |
* @param string $phpbb_root_path | |
* @param string $php_ext | |
*/ | |
public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext) | |
{ | |
$this->db = $db; | |
$this->cache = $cache; | |
$this->auth = $auth; | |
$this->phpbb_root_path = $phpbb_root_path; | |
$this->php_ext = $php_ext; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function get_name() | |
{ | |
return 'permission'; | |
} | |
/** | |
* Permission Exists | |
* | |
* Check if a permission (auth) setting exists | |
* | |
* @param string $auth_option The name of the permission (auth) option | |
* @param bool $global True for checking a global permission setting, | |
* False for a local permission setting | |
* @return bool true if it exists, false if not | |
*/ | |
public function exists($auth_option, $global = true) | |
{ | |
if ($global) | |
{ | |
$type_sql = ' AND is_global = 1'; | |
} | |
else | |
{ | |
$type_sql = ' AND is_local = 1'; | |
} | |
$sql = 'SELECT auth_option_id | |
FROM ' . ACL_OPTIONS_TABLE . " | |
WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'" | |
. $type_sql; | |
$result = $this->db->sql_query($sql); | |
$row = $this->db->sql_fetchrow($result); | |
$this->db->sql_freeresult($result); | |
if ($row) | |
{ | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Permission Add | |
* | |
* Add a permission (auth) option | |
* | |
* @param string $auth_option The name of the permission (auth) option | |
* @param bool $global True for checking a global permission setting, | |
* False for a local permission setting | |
* @param int|false $copy_from If set, contains the id of the permission from which to copy the new one. | |
* @return null | |
*/ | |
public function add($auth_option, $global = true, $copy_from = false) | |
{ | |
if ($this->exists($auth_option, $global)) | |
{ | |
return; | |
} | |
// We've added permissions, so set to true to notify the user. | |
$this->permissions_added = true; | |
if (!class_exists('auth_admin')) | |
{ | |
include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext); | |
} | |
$auth_admin = new \auth_admin(); | |
// We have to add a check to see if the !$global (if global, local, and if local, global) permission already exists. If it does, acl_add_option currently has a bug which would break the ACL system, so we are having a work-around here. | |
if ($this->exists($auth_option, !$global)) | |
{ | |
$sql_ary = array( | |
'is_global' => 1, | |
'is_local' => 1, | |
); | |
$sql = 'UPDATE ' . ACL_OPTIONS_TABLE . ' | |
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . " | |
WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'"; | |
$this->db->sql_query($sql); | |
} | |
else | |
{ | |
if ($global) | |
{ | |
$auth_admin->acl_add_option(array('global' => array($auth_option))); | |
} | |
else | |
{ | |
$auth_admin->acl_add_option(array('local' => array($auth_option))); | |
} | |
} | |
// The permission has been added, now we can copy it if needed | |
if ($copy_from && isset($auth_admin->acl_options['id'][$copy_from])) | |
{ | |
$old_id = $auth_admin->acl_options['id'][$copy_from]; | |
$new_id = $auth_admin->acl_options['id'][$auth_option]; | |
$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE); | |
foreach ($tables as $table) | |
{ | |
$sql = 'SELECT * | |
FROM ' . $table . ' | |
WHERE auth_option_id = ' . $old_id; | |
$result = $this->db->sql_query($sql); | |
$sql_ary = array(); | |
while ($row = $this->db->sql_fetchrow($result)) | |
{ | |
$row['auth_option_id'] = $new_id; | |
$sql_ary[] = $row; | |
} | |
$this->db->sql_freeresult($result); | |
if (!empty($sql_ary)) | |
{ | |
$this->db->sql_multi_insert($table, $sql_ary); | |
} | |
} | |
$auth_admin->acl_clear_prefetch(); | |
} | |
} | |
/** | |
* Permission Remove | |
* | |
* Remove a permission (auth) option | |
* | |
* @param string $auth_option The name of the permission (auth) option | |
* @param bool $global True for checking a global permission setting, | |
* False for a local permission setting | |
* @return null | |
*/ | |
public function remove($auth_option, $global = true) | |
{ | |
if (!$this->exists($auth_option, $global)) | |
{ | |
return; | |
} | |
if ($global) | |
{ | |
$type_sql = ' AND is_global = 1'; | |
} | |
else | |
{ | |
$type_sql = ' AND is_local = 1'; | |
} | |
$sql = 'SELECT auth_option_id, is_global, is_local | |
FROM ' . ACL_OPTIONS_TABLE . " | |
WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'" . | |
$type_sql; | |
$result = $this->db->sql_query($sql); | |
$row = $this->db->sql_fetchrow($result); | |
$this->db->sql_freeresult($result); | |
$id = (int) $row['auth_option_id']; | |
// If it is a local and global permission, do not remove the row! :P | |
if ($row['is_global'] && $row['is_local']) | |
{ | |
$sql = 'UPDATE ' . ACL_OPTIONS_TABLE . ' | |
SET ' . (($global) ? 'is_global = 0' : 'is_local = 0') . ' | |
WHERE auth_option_id = ' . $id; | |
$this->db->sql_query($sql); | |
} | |
else | |
{ | |
// Delete time | |
$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE, ACL_OPTIONS_TABLE); | |
foreach ($tables as $table) | |
{ | |
$this->db->sql_query('DELETE FROM ' . $table . ' | |
WHERE auth_option_id = ' . $id); | |
} | |
} | |
// Purge the auth cache | |
$this->cache->destroy('_acl_options'); | |
$this->auth->acl_clear_prefetch(); | |
} | |
/** | |
* Add a new permission role | |
* | |
* @param string $role_name The new role name | |
* @param string $role_type The type (u_, m_, a_) | |
* @param string $role_description Description of the new role | |
* | |
* @return null | |
*/ | |
public function role_add($role_name, $role_type, $role_description = '') | |
{ | |
$sql = 'SELECT role_id | |
FROM ' . ACL_ROLES_TABLE . " | |
WHERE role_name = '" . $this->db->sql_escape($role_name) . "'"; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('role_id'); | |
if ($role_id) | |
{ | |
return; | |
} | |
$sql = 'SELECT MAX(role_order) AS max_role_order | |
FROM ' . ACL_ROLES_TABLE . " | |
WHERE role_type = '" . $this->db->sql_escape($role_type) . "'"; | |
$this->db->sql_query($sql); | |
$role_order = (int) $this->db->sql_fetchfield('max_role_order'); | |
$role_order = (!$role_order) ? 1 : $role_order + 1; | |
$sql_ary = array( | |
'role_name' => $role_name, | |
'role_description' => $role_description, | |
'role_type' => $role_type, | |
'role_order' => $role_order, | |
); | |
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); | |
$this->db->sql_query($sql); | |
} | |
/** | |
* Update the name on a permission role | |
* | |
* @param string $old_role_name The old role name | |
* @param string $new_role_name The new role name | |
* @return null | |
* @throws \phpbb\db\migration\exception | |
*/ | |
public function role_update($old_role_name, $new_role_name) | |
{ | |
$sql = 'SELECT role_id | |
FROM ' . ACL_ROLES_TABLE . " | |
WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'"; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('role_id'); | |
if (!$role_id) | |
{ | |
throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $old_role_name); | |
} | |
$sql = 'UPDATE ' . ACL_ROLES_TABLE . " | |
SET role_name = '" . $this->db->sql_escape($new_role_name) . "' | |
WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'"; | |
$this->db->sql_query($sql); | |
} | |
/** | |
* Remove a permission role | |
* | |
* @param string $role_name The role name to remove | |
* @return null | |
*/ | |
public function role_remove($role_name) | |
{ | |
$sql = 'SELECT role_id | |
FROM ' . ACL_ROLES_TABLE . " | |
WHERE role_name = '" . $this->db->sql_escape($role_name) . "'"; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('role_id'); | |
if (!$role_id) | |
{ | |
return; | |
} | |
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' | |
WHERE role_id = ' . $role_id; | |
$this->db->sql_query($sql); | |
$sql = 'DELETE FROM ' . ACL_ROLES_TABLE . ' | |
WHERE role_id = ' . $role_id; | |
$this->db->sql_query($sql); | |
$this->auth->acl_clear_prefetch(); | |
} | |
/** | |
* Permission Set | |
* | |
* Allows you to set permissions for a certain group/role | |
* | |
* @param string $name The name of the role/group | |
* @param string|array $auth_option The auth_option or array of | |
* auth_options you would like to set | |
* @param string $type The type (role|group) | |
* @param bool $has_permission True if you want to give them permission, | |
* false if you want to deny them permission | |
* @return null | |
* @throws \phpbb\db\migration\exception | |
*/ | |
public function permission_set($name, $auth_option, $type = 'role', $has_permission = true) | |
{ | |
if (!is_array($auth_option)) | |
{ | |
$auth_option = array($auth_option); | |
} | |
$new_auth = array(); | |
$sql = 'SELECT auth_option_id | |
FROM ' . ACL_OPTIONS_TABLE . ' | |
WHERE ' . $this->db->sql_in_set('auth_option', $auth_option); | |
$result = $this->db->sql_query($sql); | |
while ($row = $this->db->sql_fetchrow($result)) | |
{ | |
$new_auth[] = (int) $row['auth_option_id']; | |
} | |
$this->db->sql_freeresult($result); | |
if (empty($new_auth)) | |
{ | |
return; | |
} | |
$current_auth = array(); | |
$type = (string) $type; // Prevent PHP bug. | |
switch ($type) | |
{ | |
case 'role': | |
$sql = 'SELECT role_id | |
FROM ' . ACL_ROLES_TABLE . " | |
WHERE role_name = '" . $this->db->sql_escape($name) . "'"; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('role_id'); | |
if (!$role_id) | |
{ | |
throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $name); | |
} | |
$sql = 'SELECT auth_option_id, auth_setting | |
FROM ' . ACL_ROLES_DATA_TABLE . ' | |
WHERE role_id = ' . $role_id; | |
$result = $this->db->sql_query($sql); | |
while ($row = $this->db->sql_fetchrow($result)) | |
{ | |
$current_auth[$row['auth_option_id']] = $row['auth_setting']; | |
} | |
$this->db->sql_freeresult($result); | |
break; | |
case 'group': | |
$sql = 'SELECT group_id | |
FROM ' . GROUPS_TABLE . " | |
WHERE group_name = '" . $this->db->sql_escape($name) . "'"; | |
$this->db->sql_query($sql); | |
$group_id = (int) $this->db->sql_fetchfield('group_id'); | |
if (!$group_id) | |
{ | |
throw new \phpbb\db\migration\exception('GROUP_NOT_EXIST', $name); | |
} | |
// If the group has a role set for them we will add the requested permissions to that role. | |
$sql = 'SELECT auth_role_id | |
FROM ' . ACL_GROUPS_TABLE . ' | |
WHERE group_id = ' . $group_id . ' | |
AND auth_role_id <> 0 | |
AND forum_id = 0'; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('auth_role_id'); | |
if ($role_id) | |
{ | |
$sql = 'SELECT role_name, role_type | |
FROM ' . ACL_ROLES_TABLE . ' | |
WHERE role_id = ' . $role_id; | |
$this->db->sql_query($sql); | |
$role_data = $this->db->sql_fetchrow(); | |
$role_name = $role_data['role_name']; | |
$role_type = $role_data['role_type']; | |
// Filter new auth options to match the role type: a_ | f_ | m_ | u_ | |
// Set new auth options to the role only if options matching the role type were found | |
$auth_option = array_filter($auth_option, | |
function ($option) use ($role_type) | |
{ | |
return strpos($option, $role_type) === 0; | |
} | |
); | |
if (count($auth_option)) | |
{ | |
return $this->permission_set($role_name, $auth_option, 'role', $has_permission); | |
} | |
} | |
$sql = 'SELECT auth_option_id, auth_setting | |
FROM ' . ACL_GROUPS_TABLE . ' | |
WHERE group_id = ' . $group_id; | |
$result = $this->db->sql_query($sql); | |
while ($row = $this->db->sql_fetchrow($result)) | |
{ | |
$current_auth[$row['auth_option_id']] = $row['auth_setting']; | |
} | |
$this->db->sql_freeresult($result); | |
break; | |
} | |
$sql_ary = array(); | |
switch ($type) | |
{ | |
case 'role': | |
foreach ($new_auth as $auth_option_id) | |
{ | |
if (!isset($current_auth[$auth_option_id])) | |
{ | |
$sql_ary[] = array( | |
'role_id' => $role_id, | |
'auth_option_id' => $auth_option_id, | |
'auth_setting' => $has_permission, | |
); | |
} | |
} | |
$this->db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary); | |
break; | |
case 'group': | |
foreach ($new_auth as $auth_option_id) | |
{ | |
if (!isset($current_auth[$auth_option_id])) | |
{ | |
$sql_ary[] = array( | |
'group_id' => $group_id, | |
'auth_option_id' => $auth_option_id, | |
'auth_setting' => $has_permission, | |
); | |
} | |
} | |
$this->db->sql_multi_insert(ACL_GROUPS_TABLE, $sql_ary); | |
break; | |
} | |
$this->auth->acl_clear_prefetch(); | |
} | |
/** | |
* Permission Unset | |
* | |
* Allows you to unset (remove) permissions for a certain group/role | |
* | |
* @param string $name The name of the role/group | |
* @param string|array $auth_option The auth_option or array of | |
* auth_options you would like to set | |
* @param string $type The type (role|group) | |
* @return null | |
* @throws \phpbb\db\migration\exception | |
*/ | |
public function permission_unset($name, $auth_option, $type = 'role') | |
{ | |
if (!is_array($auth_option)) | |
{ | |
$auth_option = array($auth_option); | |
} | |
$to_remove = array(); | |
$sql = 'SELECT auth_option_id | |
FROM ' . ACL_OPTIONS_TABLE . ' | |
WHERE ' . $this->db->sql_in_set('auth_option', $auth_option); | |
$result = $this->db->sql_query($sql); | |
while ($row = $this->db->sql_fetchrow($result)) | |
{ | |
$to_remove[] = (int) $row['auth_option_id']; | |
} | |
$this->db->sql_freeresult($result); | |
if (empty($to_remove)) | |
{ | |
return; | |
} | |
$type = (string) $type; // Prevent PHP bug. | |
switch ($type) | |
{ | |
case 'role': | |
$sql = 'SELECT role_id | |
FROM ' . ACL_ROLES_TABLE . " | |
WHERE role_name = '" . $this->db->sql_escape($name) . "'"; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('role_id'); | |
if (!$role_id) | |
{ | |
throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $name); | |
} | |
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' | |
WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove) . ' | |
AND role_id = ' . (int) $role_id; | |
$this->db->sql_query($sql); | |
break; | |
case 'group': | |
$sql = 'SELECT group_id | |
FROM ' . GROUPS_TABLE . " | |
WHERE group_name = '" . $this->db->sql_escape($name) . "'"; | |
$this->db->sql_query($sql); | |
$group_id = (int) $this->db->sql_fetchfield('group_id'); | |
if (!$group_id) | |
{ | |
throw new \phpbb\db\migration\exception('GROUP_NOT_EXIST', $name); | |
} | |
// If the group has a role set for them we will remove the requested permissions from that role. | |
$sql = 'SELECT auth_role_id | |
FROM ' . ACL_GROUPS_TABLE . ' | |
WHERE group_id = ' . $group_id . ' | |
AND auth_role_id <> 0'; | |
$this->db->sql_query($sql); | |
$role_id = (int) $this->db->sql_fetchfield('auth_role_id'); | |
if ($role_id) | |
{ | |
$sql = 'SELECT role_name | |
FROM ' . ACL_ROLES_TABLE . ' | |
WHERE role_id = ' . $role_id; | |
$this->db->sql_query($sql); | |
$role_name = $this->db->sql_fetchfield('role_name'); | |
return $this->permission_unset($role_name, $auth_option, 'role'); | |
} | |
$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' | |
WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove); | |
$this->db->sql_query($sql); | |
break; | |
} | |
$this->auth->acl_clear_prefetch(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function reverse() | |
{ | |
$arguments = func_get_args(); | |
$original_call = array_shift($arguments); | |
$call = false; | |
switch ($original_call) | |
{ | |
case 'add': | |
$call = 'remove'; | |
break; | |
case 'remove': | |
$call = 'add'; | |
break; | |
case 'permission_set': | |
$call = 'permission_unset'; | |
break; | |
case 'permission_unset': | |
$call = 'permission_set'; | |
break; | |
case 'role_add': | |
$call = 'role_remove'; | |
break; | |
case 'role_remove': | |
$call = 'role_add'; | |
break; | |
case 'role_update': | |
// Set to the original value if the current value is what we compared to originally | |
$arguments = array( | |
$arguments[1], | |
$arguments[0], | |
); | |
break; | |
case 'reverse': | |
// Reversing a reverse is just the call itself | |
$call = array_shift($arguments); | |
break; | |
} | |
if ($call) | |
{ | |
return call_user_func_array(array(&$this, $call), $arguments); | |
} | |
} | |
} |