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