CleanUp.php 4.9 KB

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