1<?php 2/** 3 * @copyright Copyright (c) 2016, ownCloud, Inc. 4 * 5 * @author Arthur Schiwon <blizzz@arthur-schiwon.de> 6 * @author Bart Visscher <bartv@thisnet.nl> 7 * @author Christoph Wurst <christoph@winzerhof-wurst.at> 8 * @author Joas Schilling <coding@schilljs.com> 9 * @author Lukas Reschke <lukas@statuscode.ch> 10 * @author Morris Jobke <hey@morrisjobke.de> 11 * @author Robin Appelman <robin@icewind.nl> 12 * @author Robin McCorkell <robin@mccorkell.me.uk> 13 * 14 * @license AGPL-3.0 15 * 16 * This code is free software: you can redistribute it and/or modify 17 * it under the terms of the GNU Affero General Public License, version 3, 18 * as published by the Free Software Foundation. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU Affero General Public License for more details. 24 * 25 * You should have received a copy of the GNU Affero General Public License, version 3, 26 * along with this program. If not, see <http://www.gnu.org/licenses/> 27 * 28 */ 29namespace OCA\User_LDAP\Jobs; 30 31use OC\BackgroundJob\TimedJob; 32use OCA\User_LDAP\Group_Proxy; 33use OCP\EventDispatcher\IEventDispatcher; 34use OCP\Group\Events\UserAddedEvent; 35use OCP\Group\Events\UserRemovedEvent; 36use OCP\IDBConnection; 37use OCP\IGroupManager; 38use OCP\IUser; 39use OCP\IUserManager; 40use Psr\Log\LoggerInterface; 41 42class UpdateGroups extends TimedJob { 43 private $groupsFromDB; 44 45 /** @var Group_Proxy */ 46 private $groupBackend; 47 /** @var IEventDispatcher */ 48 private $dispatcher; 49 /** @var IGroupManager */ 50 private $groupManager; 51 /** @var IUserManager */ 52 private $userManager; 53 /** @var LoggerInterface */ 54 private $logger; 55 /** @var IDBConnection */ 56 private $dbc; 57 58 public function __construct( 59 Group_Proxy $groupBackend, 60 IEventDispatcher $dispatcher, 61 IGroupManager $groupManager, 62 IUserManager $userManager, 63 LoggerInterface $logger, 64 IDBConnection $dbc 65 ) { 66 $this->interval = $this->getRefreshInterval(); 67 $this->groupBackend = $groupBackend; 68 $this->dispatcher = $dispatcher; 69 $this->groupManager = $groupManager; 70 $this->userManager = $userManager; 71 $this->logger = $logger; 72 $this->dbc = $dbc; 73 } 74 75 /** 76 * @return int 77 */ 78 private function getRefreshInterval() { 79 //defaults to every hour 80 return \OC::$server->getConfig()->getAppValue('user_ldap', 'bgjRefreshInterval', 3600); 81 } 82 83 /** 84 * @param mixed $argument 85 */ 86 public function run($argument) { 87 $this->updateGroups(); 88 } 89 90 public function updateGroups() { 91 $this->logger->debug( 92 'Run background job "updateGroups"', 93 ['app' => 'user_ldap'] 94 ); 95 96 $knownGroups = array_keys($this->getKnownGroups()); 97 $actualGroups = $this->groupBackend->getGroups(); 98 99 if (empty($actualGroups) && empty($knownGroups)) { 100 $this->logger->info( 101 'bgJ "updateGroups" – groups do not seem to be configured properly, aborting.', 102 ['app' => 'user_ldap'] 103 ); 104 return; 105 } 106 107 $this->handleKnownGroups(array_intersect($actualGroups, $knownGroups)); 108 $this->handleCreatedGroups(array_diff($actualGroups, $knownGroups)); 109 $this->handleRemovedGroups(array_diff($knownGroups, $actualGroups)); 110 111 $this->logger->debug( 112 'bgJ "updateGroups" – Finished.', 113 ['app' => 'user_ldap'] 114 ); 115 } 116 117 /** 118 * @return array 119 */ 120 private function getKnownGroups() { 121 if (is_array($this->groupsFromDB)) { 122 $this->groupsFromDB; 123 } 124 $qb = $this->dbc->getQueryBuilder(); 125 $qb->select(['owncloudname', 'owncloudusers']) 126 ->from('ldap_group_members'); 127 128 $qResult = $qb->execute(); 129 $result = $qResult->fetchAll(); 130 $qResult->closeCursor(); 131 132 $this->groupsFromDB = []; 133 foreach ($result as $dataset) { 134 $this->groupsFromDB[$dataset['owncloudname']] = $dataset; 135 } 136 137 return $this->groupsFromDB; 138 } 139 140 private function handleKnownGroups(array $groups) { 141 $this->logger->debug( 142 'bgJ "updateGroups" – Dealing with known Groups.', 143 ['app' => 'user_ldap'] 144 ); 145 $qb = $this->dbc->getQueryBuilder(); 146 $qb->update('ldap_group_members') 147 ->set('owncloudusers', $qb->createParameter('members')) 148 ->where($qb->expr()->eq('owncloudname', $qb->createParameter('groupId'))); 149 150 if (!is_array($this->groupsFromDB)) { 151 $this->getKnownGroups(); 152 } 153 foreach ($groups as $group) { 154 $knownUsers = unserialize($this->groupsFromDB[$group]['owncloudusers']); 155 $actualUsers = $this->groupBackend->usersInGroup($group); 156 $hasChanged = false; 157 158 $groupObject = $this->groupManager->get($group); 159 foreach (array_diff($knownUsers, $actualUsers) as $removedUser) { 160 $userObject = $this->userManager->get($removedUser); 161 if ($userObject instanceof IUser) { 162 $this->dispatcher->dispatchTyped(new UserRemovedEvent($groupObject, $userObject)); 163 } 164 $this->logger->info( 165 'bgJ "updateGroups" – {user} removed from {group}', 166 [ 167 'app' => 'user_ldap', 168 'user' => $removedUser, 169 'group' => $group 170 ] 171 ); 172 $hasChanged = true; 173 } 174 foreach (array_diff($actualUsers, $knownUsers) as $addedUser) { 175 $userObject = $this->userManager->get($addedUser); 176 if ($userObject instanceof IUser) { 177 $this->dispatcher->dispatchTyped(new UserAddedEvent($groupObject, $userObject)); 178 } 179 $this->logger->info( 180 'bgJ "updateGroups" – {user} added to {group}', 181 [ 182 'app' => 'user_ldap', 183 'user' => $addedUser, 184 'group' => $group 185 ] 186 ); 187 $hasChanged = true; 188 } 189 if ($hasChanged) { 190 $qb->setParameters([ 191 'members' => serialize($actualUsers), 192 'groupId' => $group 193 ]); 194 $qb->execute(); 195 } 196 } 197 $this->logger->debug( 198 'bgJ "updateGroups" – FINISHED dealing with known Groups.', 199 ['app' => 'user_ldap'] 200 ); 201 } 202 203 /** 204 * @param string[] $createdGroups 205 */ 206 private function handleCreatedGroups($createdGroups) { 207 $this->logger->debug( 208 'bgJ "updateGroups" – dealing with created Groups.', 209 ['app' => 'user_ldap'] 210 ); 211 212 $query = $this->dbc->getQueryBuilder(); 213 $query->insert('ldap_group_members') 214 ->setValue('owncloudname', $query->createParameter('owncloudname')) 215 ->setValue('owncloudusers', $query->createParameter('owncloudusers')); 216 foreach ($createdGroups as $createdGroup) { 217 $this->logger->info( 218 'bgJ "updateGroups" – new group "' . $createdGroup . '" found.', 219 ['app' => 'user_ldap'] 220 ); 221 $users = serialize($this->groupBackend->usersInGroup($createdGroup)); 222 223 $query->setParameter('owncloudname', $createdGroup) 224 ->setParameter('owncloudusers', $users); 225 $query->execute(); 226 } 227 $this->logger->debug( 228 'bgJ "updateGroups" – FINISHED dealing with created Groups.', 229 ['app' => 'user_ldap'] 230 ); 231 } 232 233 /** 234 * @param string[] $removedGroups 235 */ 236 private function handleRemovedGroups($removedGroups) { 237 $this->logger->debug( 238 'bgJ "updateGroups" – dealing with removed groups.', 239 ['app' => 'user_ldap'] 240 ); 241 242 $query = $this->dbc->getQueryBuilder(); 243 $query->delete('ldap_group_members') 244 ->where($query->expr()->eq('owncloudname', $query->createParameter('owncloudname'))); 245 246 foreach ($removedGroups as $removedGroup) { 247 $this->logger->info( 248 'bgJ "updateGroups" – group "' . $removedGroup . '" was removed.', 249 ['app' => 'user_ldap'] 250 ); 251 $query->setParameter('owncloudname', $removedGroup); 252 $query->execute(); 253 } 254 $this->logger->debug( 255 'bgJ "updateGroups" – FINISHED dealing with removed groups.', 256 ['app' => 'user_ldap'] 257 ); 258 } 259} 260