CleanUp.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Morris Jobke <hey@morrisjobke.de>
  9. * @author Roeland Jago Douma <roeland@famdouma.nl>
  10. *
  11. * @license AGPL-3.0
  12. *
  13. * This code is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Affero General Public License, version 3,
  15. * as published by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License, version 3,
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>
  24. *
  25. */
  26. namespace OCA\User_LDAP\Jobs;
  27. use OCP\AppFramework\Utility\ITimeFactory;
  28. use OCP\BackgroundJob\TimedJob;
  29. use OCA\User_LDAP\Helper;
  30. use OCA\User_LDAP\Mapping\UserMapping;
  31. use OCA\User_LDAP\User\DeletedUsersIndex;
  32. use OCA\User_LDAP\User_LDAP;
  33. use OCA\User_LDAP\User_Proxy;
  34. /**
  35. * Class CleanUp
  36. *
  37. * a Background job to clean up deleted users
  38. *
  39. * @package OCA\User_LDAP\Jobs;
  40. */
  41. class CleanUp extends TimedJob {
  42. /** @var ?int $limit amount of users that should be checked per run */
  43. protected $limit;
  44. /** @var int $defaultIntervalMin default interval in minutes */
  45. protected $defaultIntervalMin = 51;
  46. /** @var User_LDAP|User_Proxy $userBackend */
  47. protected $userBackend;
  48. /** @var \OCP\IConfig $ocConfig */
  49. protected $ocConfig;
  50. /** @var \OCP\IDBConnection $db */
  51. protected $db;
  52. /** @var Helper $ldapHelper */
  53. protected $ldapHelper;
  54. /** @var UserMapping */
  55. protected $mapping;
  56. /** @var DeletedUsersIndex */
  57. protected $dui;
  58. public function __construct(
  59. ITimeFactory $timeFactory,
  60. User_Proxy $userBackend,
  61. DeletedUsersIndex $dui
  62. ) {
  63. parent::__construct($timeFactory);
  64. $minutes = \OC::$server->getConfig()->getSystemValue(
  65. 'ldapUserCleanupInterval', (string)$this->defaultIntervalMin);
  66. $this->setInterval((int)$minutes * 60);
  67. $this->userBackend = $userBackend;
  68. $this->dui = $dui;
  69. }
  70. /**
  71. * assigns the instances passed to run() to the class properties
  72. * @param array $arguments
  73. */
  74. public function setArguments($arguments): void {
  75. //Dependency Injection is not possible, because the constructor will
  76. //only get values that are serialized to JSON. I.e. whatever we would
  77. //pass in app.php we do add here, except something else is passed e.g.
  78. //in tests.
  79. if (isset($arguments['helper'])) {
  80. $this->ldapHelper = $arguments['helper'];
  81. } else {
  82. $this->ldapHelper = new Helper(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection());
  83. }
  84. if (isset($arguments['ocConfig'])) {
  85. $this->ocConfig = $arguments['ocConfig'];
  86. } else {
  87. $this->ocConfig = \OC::$server->getConfig();
  88. }
  89. if (isset($arguments['userBackend'])) {
  90. $this->userBackend = $arguments['userBackend'];
  91. }
  92. if (isset($arguments['db'])) {
  93. $this->db = $arguments['db'];
  94. } else {
  95. $this->db = \OC::$server->getDatabaseConnection();
  96. }
  97. if (isset($arguments['mapping'])) {
  98. $this->mapping = $arguments['mapping'];
  99. } else {
  100. $this->mapping = \OCP\Server::get(UserMapping::class);
  101. }
  102. if (isset($arguments['deletedUsersIndex'])) {
  103. $this->dui = $arguments['deletedUsersIndex'];
  104. }
  105. }
  106. /**
  107. * makes the background job do its work
  108. * @param array $argument
  109. */
  110. public function run($argument): void {
  111. $this->setArguments($argument);
  112. if (!$this->isCleanUpAllowed()) {
  113. return;
  114. }
  115. $users = $this->mapping->getList($this->getOffset(), $this->getChunkSize());
  116. $resetOffset = $this->isOffsetResetNecessary(count($users));
  117. $this->checkUsers($users);
  118. $this->setOffset($resetOffset);
  119. }
  120. /**
  121. * checks whether next run should start at 0 again
  122. */
  123. public function isOffsetResetNecessary(int $resultCount): bool {
  124. return $resultCount < $this->getChunkSize();
  125. }
  126. /**
  127. * checks whether cleaning up LDAP users is allowed
  128. */
  129. public function isCleanUpAllowed(): bool {
  130. try {
  131. if ($this->ldapHelper->haveDisabledConfigurations()) {
  132. return false;
  133. }
  134. } catch (\Exception $e) {
  135. return false;
  136. }
  137. return $this->isCleanUpEnabled();
  138. }
  139. /**
  140. * checks whether clean up is enabled by configuration
  141. */
  142. private function isCleanUpEnabled(): bool {
  143. return (bool)$this->ocConfig->getSystemValue(
  144. 'ldapUserCleanupInterval', (string)$this->defaultIntervalMin);
  145. }
  146. /**
  147. * checks users whether they are still existing
  148. * @param array $users result from getMappedUsers()
  149. */
  150. private function checkUsers(array $users): void {
  151. foreach ($users as $user) {
  152. $this->checkUser($user);
  153. }
  154. }
  155. /**
  156. * checks whether a user is still existing in LDAP
  157. * @param string[] $user
  158. */
  159. private function checkUser(array $user): void {
  160. if ($this->userBackend->userExistsOnLDAP($user['name'])) {
  161. //still available, all good
  162. return;
  163. }
  164. $this->dui->markUser($user['name']);
  165. }
  166. /**
  167. * gets the offset to fetch users from the mappings table
  168. */
  169. private function getOffset(): int {
  170. return (int)$this->ocConfig->getAppValue('user_ldap', 'cleanUpJobOffset', '0');
  171. }
  172. /**
  173. * sets the new offset for the next run
  174. * @param bool $reset whether the offset should be set to 0
  175. */
  176. public function setOffset(bool $reset = false): void {
  177. $newOffset = $reset ? 0 :
  178. $this->getOffset() + $this->getChunkSize();
  179. $this->ocConfig->setAppValue('user_ldap', 'cleanUpJobOffset', (string)$newOffset);
  180. }
  181. /**
  182. * returns the chunk size (limit in DB speak)
  183. */
  184. public function getChunkSize(): int {
  185. if ($this->limit === null) {
  186. $this->limit = (int)$this->ocConfig->getAppValue('user_ldap', 'cleanUpJobChunkSize', '50');
  187. }
  188. return $this->limit;
  189. }
  190. }