Вход Регистрация
Файл: phpbb/db/migration/tool/permission.php
Строк: 410
<?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 phpbbdbmigrationtool;

/**
* Migration permission management tool
*/
class permission implements phpbbdbmigrationtooltool_interface
{
    
/** @var phpbbauthauth */
    
protected $auth;

    
/** @var phpbbcacheservice */
    
protected $cache;

    
/** @var phpbbdbdriverdriver_interface */
    
protected $db;

    
/** @var string */
    
protected $phpbb_root_path;

    
/** @var string */
    
protected $php_ext;

    
/**
    * Constructor
    *
    * @param phpbbdbdriverdriver_interface $db
    * @param phpbbcacheservice $cache
    * @param phpbbauthauth $auth
    * @param string $phpbb_root_path
    * @param string $php_ext
    */
    
public function __construct(phpbbdbdriverdriver_interface $db, phpbbcacheservice $cache, phpbbauthauth $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 phpbbdbmigrationexception
    */
    
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 
phpbbdbmigrationexception('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 phpbbdbmigrationexception
    */
    
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 
phpbbdbmigrationexception('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 
phpbbdbmigrationexception('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
                        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_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 phpbbdbmigrationexception
    */
    
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 
phpbbdbmigrationexception('ROLE_NOT_EXIST', $name);
                }

                
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
                    WHERE ' 
. $this->db->sql_in_set('auth_option_id', $to_remove);
                
$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 
phpbbdbmigrationexception('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;
        }

        if (
$call)
        {
            return 
call_user_func_array(array(&$this, $call), $arguments);
        }
    }
}
Онлайн: 3
Реклама