[ Index ]

PHP Cross Reference of phpBB-3.3.2-deutsch

title

Body

[close]

/phpbb/db/migration/tool/ -> permission.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\db\migration\tool;
  15  
  16  /**
  17  * Migration permission management tool
  18  */
  19  class permission implements \phpbb\db\migration\tool\tool_interface
  20  {
  21      /** @var \phpbb\auth\auth */
  22      protected $auth;
  23  
  24      /** @var \phpbb\cache\service */
  25      protected $cache;
  26  
  27      /** @var \phpbb\db\driver\driver_interface */
  28      protected $db;
  29  
  30      /** @var string */
  31      protected $phpbb_root_path;
  32  
  33      /** @var string */
  34      protected $php_ext;
  35  
  36      /**
  37      * Constructor
  38      *
  39      * @param \phpbb\db\driver\driver_interface $db
  40      * @param \phpbb\cache\service $cache
  41      * @param \phpbb\auth\auth $auth
  42      * @param string $phpbb_root_path
  43      * @param string $php_ext
  44      */
  45  	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext)
  46      {
  47          $this->db = $db;
  48          $this->cache = $cache;
  49          $this->auth = $auth;
  50          $this->phpbb_root_path = $phpbb_root_path;
  51          $this->php_ext = $php_ext;
  52      }
  53  
  54      /**
  55      * {@inheritdoc}
  56      */
  57  	public function get_name()
  58      {
  59          return 'permission';
  60      }
  61  
  62      /**
  63      * Permission Exists
  64      *
  65      * Check if a permission (auth) setting exists
  66      *
  67      * @param string $auth_option The name of the permission (auth) option
  68      * @param bool $global True for checking a global permission setting,
  69      *     False for a local permission setting
  70      * @return bool true if it exists, false if not
  71      */
  72  	public function exists($auth_option, $global = true)
  73      {
  74          if ($global)
  75          {
  76              $type_sql = ' AND is_global = 1';
  77          }
  78          else
  79          {
  80              $type_sql = ' AND is_local = 1';
  81          }
  82  
  83          $sql = 'SELECT auth_option_id
  84              FROM ' . ACL_OPTIONS_TABLE . "
  85              WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'"
  86                  . $type_sql;
  87          $result = $this->db->sql_query($sql);
  88  
  89          $row = $this->db->sql_fetchrow($result);
  90          $this->db->sql_freeresult($result);
  91  
  92          if ($row)
  93          {
  94              return true;
  95          }
  96  
  97          return false;
  98      }
  99  
 100      /**
 101      * Permission Add
 102      *
 103      * Add a permission (auth) option
 104      *
 105      * @param string $auth_option The name of the permission (auth) option
 106      * @param bool $global True for checking a global permission setting,
 107      *     False for a local permission setting
 108      * @param int|false $copy_from If set, contains the id of the permission from which to copy the new one.
 109      * @return null
 110      */
 111  	public function add($auth_option, $global = true, $copy_from = false)
 112      {
 113          if ($this->exists($auth_option, $global))
 114          {
 115              return;
 116          }
 117  
 118          // We've added permissions, so set to true to notify the user.
 119          $this->permissions_added = true;
 120  
 121          if (!class_exists('auth_admin'))
 122          {
 123              include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
 124          }
 125          $auth_admin = new \auth_admin();
 126  
 127          // 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.
 128          if ($this->exists($auth_option, !$global))
 129          {
 130              $sql_ary = array(
 131                  'is_global'    => 1,
 132                  'is_local'    => 1,
 133              );
 134              $sql = 'UPDATE ' . ACL_OPTIONS_TABLE . '
 135                  SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . "
 136                  WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'";
 137              $this->db->sql_query($sql);
 138          }
 139          else
 140          {
 141              if ($global)
 142              {
 143                  $auth_admin->acl_add_option(array('global' => array($auth_option)));
 144              }
 145              else
 146              {
 147                  $auth_admin->acl_add_option(array('local' => array($auth_option)));
 148              }
 149          }
 150  
 151          // The permission has been added, now we can copy it if needed
 152          if ($copy_from && isset($auth_admin->acl_options['id'][$copy_from]))
 153          {
 154              $old_id = $auth_admin->acl_options['id'][$copy_from];
 155              $new_id = $auth_admin->acl_options['id'][$auth_option];
 156  
 157              $tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE);
 158  
 159              foreach ($tables as $table)
 160              {
 161                  $sql = 'SELECT *
 162                      FROM ' . $table . '
 163                      WHERE auth_option_id = ' . $old_id;
 164                  $result = $this->db->sql_query($sql);
 165  
 166                  $sql_ary = array();
 167                  while ($row = $this->db->sql_fetchrow($result))
 168                  {
 169                      $row['auth_option_id'] = $new_id;
 170                      $sql_ary[] = $row;
 171                  }
 172                  $this->db->sql_freeresult($result);
 173  
 174                  if (!empty($sql_ary))
 175                  {
 176                      $this->db->sql_multi_insert($table, $sql_ary);
 177                  }
 178              }
 179  
 180              $auth_admin->acl_clear_prefetch();
 181          }
 182      }
 183  
 184      /**
 185      * Permission Remove
 186      *
 187      * Remove a permission (auth) option
 188      *
 189      * @param string $auth_option The name of the permission (auth) option
 190      * @param bool $global True for checking a global permission setting,
 191      *     False for a local permission setting
 192      * @return null
 193      */
 194  	public function remove($auth_option, $global = true)
 195      {
 196          if (!$this->exists($auth_option, $global))
 197          {
 198              return;
 199          }
 200  
 201          if ($global)
 202          {
 203              $type_sql = ' AND is_global = 1';
 204          }
 205          else
 206          {
 207              $type_sql = ' AND is_local = 1';
 208          }
 209          $sql = 'SELECT auth_option_id, is_global, is_local
 210              FROM ' . ACL_OPTIONS_TABLE . "
 211              WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'" .
 212                  $type_sql;
 213          $result = $this->db->sql_query($sql);
 214          $row = $this->db->sql_fetchrow($result);
 215          $this->db->sql_freeresult($result);
 216  
 217          $id = (int) $row['auth_option_id'];
 218  
 219          // If it is a local and global permission, do not remove the row! :P
 220          if ($row['is_global'] && $row['is_local'])
 221          {
 222              $sql = 'UPDATE ' . ACL_OPTIONS_TABLE . '
 223                  SET ' . (($global) ? 'is_global = 0' : 'is_local = 0') . '
 224                  WHERE auth_option_id = ' . $id;
 225              $this->db->sql_query($sql);
 226          }
 227          else
 228          {
 229              // Delete time
 230              $tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE, ACL_OPTIONS_TABLE);
 231              foreach ($tables as $table)
 232              {
 233                  $this->db->sql_query('DELETE FROM ' . $table . '
 234                      WHERE auth_option_id = ' . $id);
 235              }
 236          }
 237  
 238          // Purge the auth cache
 239          $this->cache->destroy('_acl_options');
 240          $this->auth->acl_clear_prefetch();
 241      }
 242  
 243      /**
 244       * Check if a permission role exists
 245       *
 246       * @param string $role_name The role name
 247       *
 248       * @return int The id of the role if it exists, 0 otherwise
 249       */
 250  	public function role_exists($role_name)
 251      {
 252          $sql = 'SELECT role_id
 253              FROM ' . ACL_ROLES_TABLE . "
 254              WHERE role_name = '" . $this->db->sql_escape($role_name) . "'";
 255          $result = $this->db->sql_query($sql);
 256          $role_id = (int) $this->db->sql_fetchfield('role_id');
 257          $this->db->sql_freeresult($result);
 258  
 259          return $role_id;
 260      }
 261  
 262      /**
 263      * Add a new permission role
 264      *
 265      * @param string $role_name The new role name
 266      * @param string $role_type The type (u_, m_, a_)
 267      * @param string $role_description Description of the new role
 268      *
 269      * @return null
 270      */
 271  	public function role_add($role_name, $role_type, $role_description = '')
 272      {
 273          if ($this->role_exists($role_name))
 274          {
 275              return;
 276          }
 277  
 278          $sql = 'SELECT MAX(role_order) AS max_role_order
 279              FROM ' . ACL_ROLES_TABLE . "
 280              WHERE role_type = '" . $this->db->sql_escape($role_type) . "'";
 281          $this->db->sql_query($sql);
 282          $role_order = (int) $this->db->sql_fetchfield('max_role_order');
 283          $role_order = (!$role_order) ? 1 : $role_order + 1;
 284  
 285          $sql_ary = array(
 286              'role_name'            => $role_name,
 287              'role_description'    => $role_description,
 288              'role_type'            => $role_type,
 289              'role_order'        => $role_order,
 290          );
 291  
 292          $sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
 293          $this->db->sql_query($sql);
 294      }
 295  
 296      /**
 297      * Update the name on a permission role
 298      *
 299      * @param string $old_role_name The old role name
 300      * @param string $new_role_name The new role name
 301      * @return null
 302      * @throws \phpbb\db\migration\exception
 303      */
 304  	public function role_update($old_role_name, $new_role_name)
 305      {
 306          if (!$this->role_exists($old_role_name))
 307          {
 308              throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $old_role_name);
 309          }
 310  
 311          $sql = 'UPDATE ' . ACL_ROLES_TABLE . "
 312              SET role_name = '" . $this->db->sql_escape($new_role_name) . "'
 313              WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'";
 314          $this->db->sql_query($sql);
 315      }
 316  
 317      /**
 318      * Remove a permission role
 319      *
 320      * @param string $role_name The role name to remove
 321      * @return null
 322      */
 323  	public function role_remove($role_name)
 324      {
 325          if (!($role_id = $this->role_exists($role_name)))
 326          {
 327              return;
 328          }
 329  
 330          $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
 331              WHERE role_id = ' . $role_id;
 332          $this->db->sql_query($sql);
 333  
 334          $sql = 'DELETE FROM ' . ACL_ROLES_TABLE . '
 335              WHERE role_id = ' . $role_id;
 336          $this->db->sql_query($sql);
 337  
 338          $this->auth->acl_clear_prefetch();
 339      }
 340  
 341      /**
 342      * Permission Set
 343      *
 344      * Allows you to set permissions for a certain group/role
 345      *
 346      * @param string $name The name of the role/group
 347      * @param string|array $auth_option The auth_option or array of
 348      *     auth_options you would like to set
 349      * @param string $type The type (role|group)
 350      * @param bool $has_permission True if you want to give them permission,
 351      *     false if you want to deny them permission
 352      * @return null
 353      * @throws \phpbb\db\migration\exception
 354      */
 355  	public function permission_set($name, $auth_option, $type = 'role', $has_permission = true)
 356      {
 357          if (!is_array($auth_option))
 358          {
 359              $auth_option = array($auth_option);
 360          }
 361  
 362          $new_auth = array();
 363          $sql = 'SELECT auth_option_id
 364              FROM ' . ACL_OPTIONS_TABLE . '
 365              WHERE ' . $this->db->sql_in_set('auth_option', $auth_option);
 366          $result = $this->db->sql_query($sql);
 367          while ($row = $this->db->sql_fetchrow($result))
 368          {
 369              $new_auth[] = (int) $row['auth_option_id'];
 370          }
 371          $this->db->sql_freeresult($result);
 372  
 373          if (empty($new_auth))
 374          {
 375              return;
 376          }
 377  
 378          $current_auth = array();
 379  
 380          $type = (string) $type; // Prevent PHP bug.
 381  
 382          switch ($type)
 383          {
 384              case 'role':
 385                  if (!($role_id = $this->role_exists($name)))
 386                  {
 387                      throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $name);
 388                  }
 389  
 390                  $sql = 'SELECT auth_option_id, auth_setting
 391                      FROM ' . ACL_ROLES_DATA_TABLE . '
 392                      WHERE role_id = ' . $role_id;
 393                  $result = $this->db->sql_query($sql);
 394                  while ($row = $this->db->sql_fetchrow($result))
 395                  {
 396                      $current_auth[$row['auth_option_id']] = $row['auth_setting'];
 397                  }
 398                  $this->db->sql_freeresult($result);
 399              break;
 400  
 401              case 'group':
 402                  $sql = 'SELECT group_id
 403                      FROM ' . GROUPS_TABLE . "
 404                      WHERE group_name = '" . $this->db->sql_escape($name) . "'";
 405                  $this->db->sql_query($sql);
 406                  $group_id = (int) $this->db->sql_fetchfield('group_id');
 407  
 408                  if (!$group_id)
 409                  {
 410                      throw new \phpbb\db\migration\exception('GROUP_NOT_EXIST', $name);
 411                  }
 412  
 413                  // If the group has a role set for them we will add the requested permissions to that role.
 414                  $sql = 'SELECT auth_role_id
 415                      FROM ' . ACL_GROUPS_TABLE . '
 416                      WHERE group_id = ' . $group_id . '
 417                          AND auth_role_id <> 0
 418                          AND forum_id = 0';
 419                  $this->db->sql_query($sql);
 420                  $role_id = (int) $this->db->sql_fetchfield('auth_role_id');
 421                  if ($role_id)
 422                  {
 423                      $sql = 'SELECT role_name, role_type
 424                          FROM ' . ACL_ROLES_TABLE . '
 425                          WHERE role_id = ' . $role_id;
 426                      $this->db->sql_query($sql);
 427                      $role_data = $this->db->sql_fetchrow();
 428                      $role_name = $role_data['role_name'];
 429                      $role_type = $role_data['role_type'];
 430  
 431                      // Filter new auth options to match the role type: a_ | f_ | m_ | u_
 432                      // Set new auth options to the role only if options matching the role type were found
 433                      $auth_option = array_filter($auth_option,
 434                          function ($option) use ($role_type)
 435                          {
 436                              return strpos($option, $role_type) === 0;
 437                          }
 438                      );
 439  
 440                      if (count($auth_option))
 441                      {
 442                          return $this->permission_set($role_name, $auth_option, 'role', $has_permission);
 443                      }
 444                  }
 445  
 446                  $sql = 'SELECT auth_option_id, auth_setting
 447                      FROM ' . ACL_GROUPS_TABLE . '
 448                      WHERE group_id = ' . $group_id;
 449                  $result = $this->db->sql_query($sql);
 450                  while ($row = $this->db->sql_fetchrow($result))
 451                  {
 452                      $current_auth[$row['auth_option_id']] = $row['auth_setting'];
 453                  }
 454                  $this->db->sql_freeresult($result);
 455              break;
 456          }
 457  
 458          $sql_ary = array();
 459          switch ($type)
 460          {
 461              case 'role':
 462                  foreach ($new_auth as $auth_option_id)
 463                  {
 464                      if (!isset($current_auth[$auth_option_id]))
 465                      {
 466                          $sql_ary[] = array(
 467                              'role_id'            => $role_id,
 468                              'auth_option_id'    => $auth_option_id,
 469                              'auth_setting'        => $has_permission,
 470                          );
 471                      }
 472                  }
 473  
 474                  $this->db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary);
 475              break;
 476  
 477              case 'group':
 478                  foreach ($new_auth as $auth_option_id)
 479                  {
 480                      if (!isset($current_auth[$auth_option_id]))
 481                      {
 482                          $sql_ary[] = array(
 483                              'group_id'            => $group_id,
 484                              'auth_option_id'    => $auth_option_id,
 485                              'auth_setting'        => $has_permission,
 486                          );
 487                      }
 488                  }
 489  
 490                  $this->db->sql_multi_insert(ACL_GROUPS_TABLE, $sql_ary);
 491              break;
 492          }
 493  
 494          $this->auth->acl_clear_prefetch();
 495      }
 496  
 497      /**
 498      * Permission Unset
 499      *
 500      * Allows you to unset (remove) permissions for a certain group/role
 501      *
 502      * @param string $name The name of the role/group
 503      * @param string|array $auth_option The auth_option or array of
 504      *     auth_options you would like to set
 505      * @param string $type The type (role|group)
 506      * @return null
 507      * @throws \phpbb\db\migration\exception
 508      */
 509  	public function permission_unset($name, $auth_option, $type = 'role')
 510      {
 511          if (!is_array($auth_option))
 512          {
 513              $auth_option = array($auth_option);
 514          }
 515  
 516          $to_remove = array();
 517          $sql = 'SELECT auth_option_id
 518              FROM ' . ACL_OPTIONS_TABLE . '
 519              WHERE ' . $this->db->sql_in_set('auth_option', $auth_option);
 520          $result = $this->db->sql_query($sql);
 521          while ($row = $this->db->sql_fetchrow($result))
 522          {
 523              $to_remove[] = (int) $row['auth_option_id'];
 524          }
 525          $this->db->sql_freeresult($result);
 526  
 527          if (empty($to_remove))
 528          {
 529              return;
 530          }
 531  
 532          $type = (string) $type; // Prevent PHP bug.
 533  
 534          switch ($type)
 535          {
 536              case 'role':
 537                  if (!($role_id = $this->role_exists($name)))
 538                  {
 539                      throw new \phpbb\db\migration\exception('ROLE_NOT_EXIST', $name);
 540                  }
 541  
 542                  $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
 543                      WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove) . '
 544                          AND role_id = ' . (int) $role_id;
 545                  $this->db->sql_query($sql);
 546              break;
 547  
 548              case 'group':
 549                  $sql = 'SELECT group_id
 550                      FROM ' . GROUPS_TABLE . "
 551                      WHERE group_name = '" . $this->db->sql_escape($name) . "'";
 552                  $this->db->sql_query($sql);
 553                  $group_id = (int) $this->db->sql_fetchfield('group_id');
 554  
 555                  if (!$group_id)
 556                  {
 557                      throw new \phpbb\db\migration\exception('GROUP_NOT_EXIST', $name);
 558                  }
 559  
 560                  // If the group has a role set for them we will remove the requested permissions from that role.
 561                  $sql = 'SELECT auth_role_id
 562                      FROM ' . ACL_GROUPS_TABLE . '
 563                      WHERE group_id = ' . $group_id . '
 564                          AND auth_role_id <> 0';
 565                  $this->db->sql_query($sql);
 566                  $role_id = (int) $this->db->sql_fetchfield('auth_role_id');
 567                  if ($role_id)
 568                  {
 569                      $sql = 'SELECT role_name
 570                          FROM ' . ACL_ROLES_TABLE . '
 571                          WHERE role_id = ' . $role_id;
 572                      $this->db->sql_query($sql);
 573                      $role_name = $this->db->sql_fetchfield('role_name');
 574  
 575                      return $this->permission_unset($role_name, $auth_option, 'role');
 576                  }
 577  
 578                  $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
 579                      WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove);
 580                  $this->db->sql_query($sql);
 581              break;
 582          }
 583  
 584          $this->auth->acl_clear_prefetch();
 585      }
 586  
 587      /**
 588      * {@inheritdoc}
 589      */
 590  	public function reverse()
 591      {
 592          $arguments = func_get_args();
 593          $original_call = array_shift($arguments);
 594  
 595          $call = false;
 596          switch ($original_call)
 597          {
 598              case 'add':
 599                  $call = 'remove';
 600              break;
 601  
 602              case 'remove':
 603                  $call = 'add';
 604              break;
 605  
 606              case 'permission_set':
 607                  $call = 'permission_unset';
 608              break;
 609  
 610              case 'permission_unset':
 611                  $call = 'permission_set';
 612              break;
 613  
 614              case 'role_add':
 615                  $call = 'role_remove';
 616              break;
 617  
 618              case 'role_remove':
 619                  $call = 'role_add';
 620              break;
 621  
 622              case 'role_update':
 623                  // Set to the original value if the current value is what we compared to originally
 624                  $arguments = array(
 625                      $arguments[1],
 626                      $arguments[0],
 627                  );
 628              break;
 629  
 630              case 'reverse':
 631                  // Reversing a reverse is just the call itself
 632                  $call = array_shift($arguments);
 633              break;
 634          }
 635  
 636          if ($call)
 637          {
 638              return call_user_func_array(array(&$this, $call), $arguments);
 639          }
 640      }
 641  }


Generated: Wed Nov 11 20:28:18 2020 Cross-referenced by PHPXref 0.7.1