Вход Регистрация
Файл: 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 $dbphpbbcacheservice $cachephpbbauthauth $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_TABLEACL_ROLES_DATA_TABLEACL_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_TABLEACL_ROLES_DATA_TABLEACL_USERS_TABLEACL_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) ? $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);
        }
    }
}
Онлайн: 1
Реклама