CleanUp.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\User_LDAP\Jobs;
  8. use OCA\User_LDAP\Helper;
  9. use OCA\User_LDAP\Mapping\UserMapping;
  10. use OCA\User_LDAP\User\DeletedUsersIndex;
  11. use OCA\User_LDAP\User_LDAP;
  12. use OCA\User_LDAP\User_Proxy;
  13. use OCP\AppFramework\Utility\ITimeFactory;
  14. use OCP\BackgroundJob\TimedJob;
  15. /**
  16. * Class CleanUp
  17. *
  18. * a Background job to clean up deleted users
  19. *
  20. * @package OCA\User_LDAP\Jobs;
  21. */
  22. class CleanUp extends TimedJob {
  23. /** @var ?int $limit amount of users that should be checked per run */
  24. protected $limit;
  25. /** @var int $defaultIntervalMin default interval in minutes */
  26. protected $defaultIntervalMin = 51;
  27. /** @var User_LDAP|User_Proxy $userBackend */
  28. protected $userBackend;
  29. /** @var \OCP\IConfig $ocConfig */
  30. protected $ocConfig;
  31. /** @var \OCP\IDBConnection $db */
  32. protected $db;
  33. /** @var Helper $ldapHelper */
  34. protected $ldapHelper;
  35. /** @var UserMapping */
  36. protected $mapping;
  37. /** @var DeletedUsersIndex */
  38. protected $dui;
  39. public function __construct(
  40. ITimeFactory $timeFactory,
  41. User_Proxy $userBackend,
  42. DeletedUsersIndex $dui
  43. ) {
  44. parent::__construct($timeFactory);
  45. $minutes = \OC::$server->getConfig()->getSystemValue(
  46. 'ldapUserCleanupInterval', (string)$this->defaultIntervalMin);
  47. $this->setInterval((int)$minutes * 60);
  48. $this->userBackend = $userBackend;
  49. $this->dui = $dui;
  50. }
  51. /**
  52. * assigns the instances passed to run() to the class properties
  53. * @param array $arguments
  54. */
  55. public function setArguments($arguments): void {
  56. //Dependency Injection is not possible, because the constructor will
  57. //only get values that are serialized to JSON. I.e. whatever we would
  58. //pass in app.php we do add here, except something else is passed e.g.
  59. //in tests.
  60. if (isset($arguments['helper'])) {
  61. $this->ldapHelper = $arguments['helper'];
  62. } else {
  63. $this->ldapHelper = new Helper(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection());
  64. }
  65. if (isset($arguments['ocConfig'])) {
  66. $this->ocConfig = $arguments['ocConfig'];
  67. } else {
  68. $this->ocConfig = \OC::$server->getConfig();
  69. }
  70. if (isset($arguments['userBackend'])) {
  71. $this->userBackend = $arguments['userBackend'];
  72. }
  73. if (isset($arguments['db'])) {
  74. $this->db = $arguments['db'];
  75. } else {
  76. $this->db = \OC::$server->getDatabaseConnection();
  77. }
  78. if (isset($arguments['mapping'])) {
  79. $this->mapping = $arguments['mapping'];
  80. } else {
  81. $this->mapping = \OCP\Server::get(UserMapping::class);
  82. }
  83. if (isset($arguments['deletedUsersIndex'])) {
  84. $this->dui = $arguments['deletedUsersIndex'];
  85. }
  86. }
  87. /**
  88. * makes the background job do its work
  89. * @param array $argument
  90. */
  91. public function run($argument): void {
  92. $this->setArguments($argument);
  93. if (!$this->isCleanUpAllowed()) {
  94. return;
  95. }
  96. $users = $this->mapping->getList($this->getOffset(), $this->getChunkSize());
  97. $resetOffset = $this->isOffsetResetNecessary(count($users));
  98. $this->checkUsers($users);
  99. $this->setOffset($resetOffset);
  100. }
  101. /**
  102. * checks whether next run should start at 0 again
  103. */
  104. public function isOffsetResetNecessary(int $resultCount): bool {
  105. return $resultCount < $this->getChunkSize();
  106. }
  107. /**
  108. * checks whether cleaning up LDAP users is allowed
  109. */
  110. public function isCleanUpAllowed(): bool {
  111. try {
  112. if ($this->ldapHelper->haveDisabledConfigurations()) {
  113. return false;
  114. }
  115. } catch (\Exception $e) {
  116. return false;
  117. }
  118. return $this->isCleanUpEnabled();
  119. }
  120. /**
  121. * checks whether clean up is enabled by configuration
  122. */
  123. private function isCleanUpEnabled(): bool {
  124. return (bool)$this->ocConfig->getSystemValue(
  125. 'ldapUserCleanupInterval', (string)$this->defaultIntervalMin);
  126. }
  127. /**
  128. * checks users whether they are still existing
  129. * @param array $users result from getMappedUsers()
  130. */
  131. private function checkUsers(array $users): void {
  132. foreach ($users as $user) {
  133. $this->checkUser($user);
  134. }
  135. }
  136. /**
  137. * checks whether a user is still existing in LDAP
  138. * @param string[] $user
  139. */
  140. private function checkUser(array $user): void {
  141. if ($this->userBackend->userExistsOnLDAP($user['name'])) {
  142. //still available, all good
  143. return;
  144. }
  145. $this->dui->markUser($user['name']);
  146. }
  147. /**
  148. * gets the offset to fetch users from the mappings table
  149. */
  150. private function getOffset(): int {
  151. return (int)$this->ocConfig->getAppValue('user_ldap', 'cleanUpJobOffset', '0');
  152. }
  153. /**
  154. * sets the new offset for the next run
  155. * @param bool $reset whether the offset should be set to 0
  156. */
  157. public function setOffset(bool $reset = false): void {
  158. $newOffset = $reset ? 0 :
  159. $this->getOffset() + $this->getChunkSize();
  160. $this->ocConfig->setAppValue('user_ldap', 'cleanUpJobOffset', (string)$newOffset);
  161. }
  162. /**
  163. * returns the chunk size (limit in DB speak)
  164. */
  165. public function getChunkSize(): int {
  166. if ($this->limit === null) {
  167. $this->limit = (int)$this->ocConfig->getAppValue('user_ldap', 'cleanUpJobChunkSize', '50');
  168. }
  169. return $this->limit;
  170. }
  171. }