Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

permission.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 18.09 KiB


001  <?php
002  /**
003  *
004  * This file is part of the phpBB Forum Software package.
005  *
006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
007  * @license GNU General Public License, version 2 (GPL-2.0)
008  *
009  * For full copyright and license information, please see
010  * the docs/CREDITS.txt file.
011  *
012  */
013   
014  namespace phpbb\db\migration\tool;
015   
016  /**
017  * Migration permission management tool
018  */
019  class permission implements \phpbb\db\migration\tool\tool_interface
020  {
021      /** @var \phpbb\auth\auth */
022      protected $auth;
023   
024      /** @var \includes\acp\auth\auth_admin */
025      protected $auth_admin;
026   
027      /** @var \phpbb\cache\service */
028      protected $cache;
029   
030      /** @var \phpbb\db\driver\driver_interface */
031      protected $db;
032   
033      /** @var string */
034      protected $phpbb_root_path;
035   
036      /** @var string */
037      protected $php_ext;
038   
039      /**
040      * Constructor
041      *
042      * @param \phpbb\db\driver\driver_interface $db
043      * @param \phpbb\cache\service $cache
044      * @param \phpbb\auth\auth $auth
045      * @param string $phpbb_root_path
046      * @param string $php_ext
047      */
048      public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext)
049      {
050          $this->db = $db;
051          $this->cache = $cache;
052          $this->auth = $auth;
053          $this->phpbb_root_path = $phpbb_root_path;
054          $this->php_ext = $php_ext;
055   
056          if (!class_exists('auth_admin'))
057          {
058              include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
059          }
060          $this->auth_admin = new \auth_admin();
061      }
062   
063      /**
064      * {@inheritdoc}
065      */
066      public function get_name()
067      {
068          return 'permission';
069      }
070   
071      /**
072      * Permission Exists
073      *
074      * Check if a permission (auth) setting exists
075      *
076      * @param string $auth_option The name of the permission (auth) option
077      * @param bool $global True for checking a global permission setting,
078      *     False for a local permission setting
079      * @return bool true if it exists, false if not
080      */
081      public function exists($auth_option, $global = true)
082      {
083          if ($global)
084          {
085              $type_sql = ' AND is_global = 1';
086          }
087          else
088          {
089              $type_sql = ' AND is_local = 1';
090          }
091   
092          $sql = 'SELECT auth_option_id
093              FROM ' . ACL_OPTIONS_TABLE . "
094              WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'"
095                  . $type_sql;
096          $result = $this->db->sql_query($sql);
097   
098          $row = $this->db->sql_fetchrow($result);
099          $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  }
707