mirror of
				https://github.com/Icinga/icingaweb2.git
				synced 2025-10-24 17:04:04 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			304 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
 | |
| 
 | |
| namespace Icinga\Authentication\UserGroup;
 | |
| 
 | |
| use Icinga\Data\Filter\Filter;
 | |
| use Icinga\Exception\NotFoundError;
 | |
| use Icinga\Repository\DbRepository;
 | |
| use Icinga\Repository\RepositoryQuery;
 | |
| use Icinga\User;
 | |
| 
 | |
| class DbUserGroupBackend extends DbRepository implements UserGroupBackendInterface
 | |
| {
 | |
|     /**
 | |
|      * The query columns being provided
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $queryColumns = array(
 | |
|         'group' => array(
 | |
|             'group_id'      => 'g.id',
 | |
|             'group'         => 'g.name COLLATE utf8_general_ci',
 | |
|             'group_name'    => 'g.name',
 | |
|             'parent'        => 'g.parent',
 | |
|             'created_at'    => 'UNIX_TIMESTAMP(g.ctime)',
 | |
|             'last_modified' => 'UNIX_TIMESTAMP(g.mtime)'
 | |
|         ),
 | |
|         'group_membership' => array(
 | |
|             'group_id'      => 'gm.group_id',
 | |
|             'user'          => 'gm.username COLLATE utf8_general_ci',
 | |
|             'user_name'     => 'gm.username',
 | |
|             'created_at'    => 'UNIX_TIMESTAMP(gm.ctime)',
 | |
|             'last_modified' => 'UNIX_TIMESTAMP(gm.mtime)'
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     /**
 | |
|      * The table aliases being applied
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $tableAliases = array(
 | |
|         'group'             => 'g',
 | |
|         'group_membership'  => 'gm'
 | |
|     );
 | |
| 
 | |
|     /**
 | |
|      * The statement columns being provided
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $statementColumns = array(
 | |
|         'group' => array(
 | |
|             'group_id'      => 'id',
 | |
|             'group_name'    => 'name',
 | |
|             'parent'        => 'parent',
 | |
|             'created_at'    => 'ctime',
 | |
|             'last_modified' => 'mtime'
 | |
|         ),
 | |
|         'group_membership' => array(
 | |
|             'group_id'      => 'group_id',
 | |
|             'group_name'    => 'group_id',
 | |
|             'user_name'     => 'username',
 | |
|             'created_at'    => 'ctime',
 | |
|             'last_modified' => 'mtime'
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     /**
 | |
|      * The columns which are not permitted to be queried
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $blacklistedQueryColumns = array('group', 'user');
 | |
| 
 | |
|     /**
 | |
|      * The search columns being provided
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $searchColumns = array('group', 'user');
 | |
| 
 | |
|     /**
 | |
|      * The value conversion rules to apply on a query or statement
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $conversionRules = array(
 | |
|         'group'             => array(
 | |
|             'parent'        => 'group_id'
 | |
|         ),
 | |
|         'group_membership'  => array(
 | |
|             'group_name'    => 'group_id'
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     /**
 | |
|      * Initialize this database user group backend
 | |
|      */
 | |
|     protected function init()
 | |
|     {
 | |
|         if (! $this->ds->getTablePrefix()) {
 | |
|             $this->ds->setTablePrefix('icingaweb_');
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initialize this repository's filter columns
 | |
|      *
 | |
|      * @return  array
 | |
|      */
 | |
|     protected function initializeFilterColumns()
 | |
|     {
 | |
|         $userLabel = t('Username') . ' ' . t('(Case insensitive)');
 | |
|         $groupLabel = t('User Group') . ' ' . t('(Case insensitive)');
 | |
|         return array(
 | |
|             $userLabel          => 'user',
 | |
|             t('Username')       => 'user_name',
 | |
|             $groupLabel         => 'group',
 | |
|             t('User Group')     => 'group_name',
 | |
|             t('Parent')         => 'parent',
 | |
|             t('Created At')     => 'created_at',
 | |
|             t('Last Modified')  => 'last_modified'
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Insert a table row with the given data
 | |
|      *
 | |
|      * @param   string  $table
 | |
|      * @param   array   $bind
 | |
|      */
 | |
|     public function insert($table, array $bind)
 | |
|     {
 | |
|         $bind['created_at'] = date('Y-m-d H:i:s');
 | |
|         parent::insert($table, $bind);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Update table rows with the given data, optionally limited by using a filter
 | |
|      *
 | |
|      * @param   string  $table
 | |
|      * @param   array   $bind
 | |
|      * @param   Filter  $filter
 | |
|      */
 | |
|     public function update($table, array $bind, Filter $filter = null)
 | |
|     {
 | |
|         $bind['last_modified'] = date('Y-m-d H:i:s');
 | |
|         parent::update($table, $bind, $filter);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Delete table rows, optionally limited by using a filter
 | |
|      *
 | |
|      * @param   string  $table
 | |
|      * @param   Filter  $filter
 | |
|      */
 | |
|     public function delete($table, Filter $filter = null)
 | |
|     {
 | |
|         if ($table === 'group') {
 | |
|             parent::delete('group_membership', $filter);
 | |
|             $idQuery = $this->select(array('group_id'));
 | |
|             if ($filter !== null) {
 | |
|                 $idQuery->applyFilter($filter);
 | |
|             }
 | |
| 
 | |
|             $this->update('group', array('parent' => null), Filter::where('parent', $idQuery->fetchColumn()));
 | |
|         }
 | |
| 
 | |
|         parent::delete($table, $filter);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the groups the given user is a member of
 | |
|      *
 | |
|      * @param   User    $user
 | |
|      *
 | |
|      * @return  array
 | |
|      */
 | |
|     public function getMemberships(User $user)
 | |
|     {
 | |
|         $groupQuery = $this->ds
 | |
|             ->select()
 | |
|             ->from(
 | |
|                 array('g' => $this->prependTablePrefix('group')),
 | |
|                 array(
 | |
|                     'group_name'    => 'g.name',
 | |
|                     'parent_name'   => 'gg.name'
 | |
|                 )
 | |
|             )->joinLeft(
 | |
|                 array('gg' => $this->prependTablePrefix('group')),
 | |
|                 'g.parent = gg.id',
 | |
|                 array()
 | |
|             );
 | |
| 
 | |
|         $groups = array();
 | |
|         foreach ($groupQuery as $group) {
 | |
|             $groups[$group->group_name] = $group->parent_name;
 | |
|         }
 | |
| 
 | |
|         $membershipQuery = $this
 | |
|             ->select()
 | |
|             ->from('group_membership', array('group_name'))
 | |
|             ->where('user_name', $user->getUsername());
 | |
| 
 | |
|         $memberships = array();
 | |
|         foreach ($membershipQuery as $membership) {
 | |
|             $memberships[] = $membership->group_name;
 | |
|             $parent = $groups[$membership->group_name];
 | |
|             while ($parent !== null) {
 | |
|                 $memberships[] = $parent;
 | |
|                 // Usually a parent is an existing group, but since we do not have a constraint on our table..
 | |
|                 $parent = isset($groups[$parent]) ? $groups[$parent] : null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $memberships;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the name of the backend that is providing the given user
 | |
|      *
 | |
|      * @param   string  $username   Currently unused
 | |
|      *
 | |
|      * @return  null|string     The name of the backend or null in case this information is not available
 | |
|      */
 | |
|     public function getUserBackendName($username)
 | |
|     {
 | |
|         return null; // TODO(10373): Store this to the database when inserting and fetch it here
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Join group into group_membership
 | |
|      *
 | |
|      * @param   RepositoryQuery     $query
 | |
|      */
 | |
|     protected function joinGroup(RepositoryQuery $query)
 | |
|     {
 | |
|         $query->getQuery()->join(
 | |
|             $this->requireTable('group'),
 | |
|             'gm.group_id = g.id',
 | |
|             array()
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Join group_membership into group
 | |
|      *
 | |
|      * @param   RepositoryQuery     $query
 | |
|      */
 | |
|     protected function joinGroupMembership(RepositoryQuery $query)
 | |
|     {
 | |
|         $query->getQuery()->joinLeft(
 | |
|             $this->requireTable('group_membership'),
 | |
|             'g.id = gm.group_id',
 | |
|             array()
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Fetch and return the corresponding id for the given group's name
 | |
|      *
 | |
|      * @param   string|array    $groupName
 | |
|      *
 | |
|      * @return  int
 | |
|      *
 | |
|      * @throws  NotFoundError
 | |
|      */
 | |
|     protected function persistGroupId($groupName)
 | |
|     {
 | |
|         if (! $groupName || empty($groupName) || is_numeric($groupName)) {
 | |
|             return $groupName;
 | |
|         }
 | |
| 
 | |
|         if (is_array($groupName)) {
 | |
|             if (is_numeric($groupName[0])) {
 | |
|                 return $groupName; // In case the array contains mixed types...
 | |
|             }
 | |
| 
 | |
|             $groupIds = $this->ds
 | |
|                 ->select()
 | |
|                 ->from($this->prependTablePrefix('group'), array('id'))
 | |
|                 ->where('name', $groupName)
 | |
|                 ->fetchColumn();
 | |
|             if (empty($groupIds)) {
 | |
|                 throw new NotFoundError('No groups found matching one of: %s', implode(', ', $groupName));
 | |
|             }
 | |
| 
 | |
|             return $groupIds;
 | |
|         }
 | |
| 
 | |
|         $groupId = $this->ds
 | |
|             ->select()
 | |
|             ->from($this->prependTablePrefix('group'), array('id'))
 | |
|             ->where('name', $groupName)
 | |
|             ->fetchOne();
 | |
|         if ($groupId === false) {
 | |
|             throw new NotFoundError('Group "%s" does not exist', $groupName);
 | |
|         }
 | |
| 
 | |
|         return $groupId;
 | |
|     }
 | |
| }
 |