You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
7.9 KiB

3 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Daniel Kesselberg <mail@danielkesselberg.de>
  7. * @author Georg Ehrke <oc.list@georgehrke.com>
  8. * @author Joas Schilling <coding@schilljs.com>
  9. * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
  10. * @author Julius Härtl <jus@bitgrid.net>
  11. * @author Lukas Reschke <lukas@statuscode.ch>
  12. * @author Michael Weimann <mail@michael-weimann.eu>
  13. * @author Morris Jobke <hey@morrisjobke.de>
  14. * @author Robin Appelman <robin@icewind.nl>
  15. * @author Roeland Jago Douma <roeland@famdouma.nl>
  16. * @author Thomas Müller <thomas.mueller@tmit.eu>
  17. * @author Vincent Petry <pvince81@owncloud.com>
  18. *
  19. * @license AGPL-3.0
  20. *
  21. * This code is free software: you can redistribute it and/or modify
  22. * it under the terms of the GNU Affero General Public License, version 3,
  23. * as published by the Free Software Foundation.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU Affero General Public License for more details.
  29. *
  30. * You should have received a copy of the GNU Affero General Public License, version 3,
  31. * along with this program. If not, see <http://www.gnu.org/licenses/>
  32. *
  33. */
  34. namespace OC;
  35. use OC\Avatar\AvatarManager;
  36. use OC\Repair\AddCleanupUpdaterBackupsJob;
  37. use OC\Repair\CleanTags;
  38. use OC\Repair\ClearFrontendCaches;
  39. use OC\Repair\ClearGeneratedAvatarCache;
  40. use OC\Repair\Collation;
  41. use OC\Repair\MoveUpdaterStepFile;
  42. use OC\Repair\NC11\FixMountStorages;
  43. use OC\Repair\NC13\AddLogRotateJob;
  44. use OC\Repair\NC14\AddPreviewBackgroundCleanupJob;
  45. use OC\Repair\NC16\AddClenupLoginFlowV2BackgroundJob;
  46. use OC\Repair\NC16\CleanupCardDAVPhotoCache;
  47. use OC\Repair\NC16\ClearCollectionsAccessCache;
  48. use OC\Repair\NC18\ResetGeneratedAvatarFlag;
  49. use OC\Repair\NC20\EncryptionLegacyCipher;
  50. use OC\Repair\NC20\EncryptionMigration;
  51. use OC\Repair\NC20\ShippedDashboardEnable;
  52. use OC\Repair\OldGroupMembershipShares;
  53. use OC\Repair\Owncloud\DropAccountTermsTable;
  54. use OC\Repair\Owncloud\SaveAccountsTableData;
  55. use OC\Repair\RemoveLinkShares;
  56. use OC\Repair\RepairInvalidShares;
  57. use OC\Repair\RepairMimeTypes;
  58. use OC\Repair\SqliteAutoincrement;
  59. use OC\Template\JSCombiner;
  60. use OC\Template\SCSSCacher;
  61. use OCP\AppFramework\QueryException;
  62. use OCP\AppFramework\Utility\ITimeFactory;
  63. use OCP\Collaboration\Resources\IManager;
  64. use OCP\Migration\IOutput;
  65. use OCP\Migration\IRepairStep;
  66. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  67. use Symfony\Component\EventDispatcher\GenericEvent;
  68. class Repair implements IOutput {
  69. /** @var IRepairStep[] */
  70. private $repairSteps;
  71. /** @var EventDispatcherInterface */
  72. private $dispatcher;
  73. /** @var string */
  74. private $currentStep;
  75. /**
  76. * Creates a new repair step runner
  77. *
  78. * @param IRepairStep[] $repairSteps array of RepairStep instances
  79. * @param EventDispatcherInterface $dispatcher
  80. */
  81. public function __construct(array $repairSteps, EventDispatcherInterface $dispatcher) {
  82. $this->repairSteps = $repairSteps;
  83. $this->dispatcher = $dispatcher;
  84. }
  85. /**
  86. * Run a series of repair steps for common problems
  87. */
  88. public function run() {
  89. if (count($this->repairSteps) === 0) {
  90. $this->emit('\OC\Repair', 'info', ['No repair steps available']);
  91. return;
  92. }
  93. // run each repair step
  94. foreach ($this->repairSteps as $step) {
  95. $this->currentStep = $step->getName();
  96. $this->emit('\OC\Repair', 'step', [$this->currentStep]);
  97. $step->run($this);
  98. }
  99. }
  100. /**
  101. * Add repair step
  102. *
  103. * @param IRepairStep|string $repairStep repair step
  104. * @throws \Exception
  105. */
  106. public function addStep($repairStep) {
  107. if (is_string($repairStep)) {
  108. try {
  109. $s = \OC::$server->query($repairStep);
  110. } catch (QueryException $e) {
  111. if (class_exists($repairStep)) {
  112. $s = new $repairStep();
  113. } else {
  114. throw new \Exception("Repair step '$repairStep' is unknown");
  115. }
  116. }
  117. if ($s instanceof IRepairStep) {
  118. $this->repairSteps[] = $s;
  119. } else {
  120. throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
  121. }
  122. } else {
  123. $this->repairSteps[] = $repairStep;
  124. }
  125. }
  126. /**
  127. * Returns the default repair steps to be run on the
  128. * command line or after an upgrade.
  129. *
  130. * @return IRepairStep[]
  131. */
  132. public static function getRepairSteps() {
  133. return [
  134. new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), \OC::$server->getDatabaseConnection(), false),
  135. new RepairMimeTypes(\OC::$server->getConfig()),
  136. new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
  137. new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
  138. new MoveUpdaterStepFile(\OC::$server->getConfig()),
  139. new FixMountStorages(\OC::$server->getDatabaseConnection()),
  140. new AddLogRotateJob(\OC::$server->getJobList()),
  141. new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OC::$server->query(SCSSCacher::class), \OC::$server->query(JSCombiner::class)),
  142. new ClearGeneratedAvatarCache(\OC::$server->getConfig(), \OC::$server->query(AvatarManager::class)),
  143. new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()),
  144. new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()),
  145. new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OC::$server->getAppDataDir('dav-photocache'), \OC::$server->getLogger()),
  146. new AddClenupLoginFlowV2BackgroundJob(\OC::$server->getJobList()),
  147. new RemoveLinkShares(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), \OC::$server->getNotificationManager(), \OC::$server->query(ITimeFactory::class)),
  148. new ClearCollectionsAccessCache(\OC::$server->getConfig(), \OC::$server->query(IManager::class)),
  149. \OC::$server->query(ResetGeneratedAvatarFlag::class),
  150. \OC::$server->query(EncryptionLegacyCipher::class),
  151. \OC::$server->query(EncryptionMigration::class),
  152. \OC::$server->get(ShippedDashboardEnable::class),
  153. ];
  154. }
  155. /**
  156. * Returns expensive repair steps to be run on the
  157. * command line with a special option.
  158. *
  159. * @return IRepairStep[]
  160. */
  161. public static function getExpensiveRepairSteps() {
  162. return [
  163. new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager())
  164. ];
  165. }
  166. /**
  167. * Returns the repair steps to be run before an
  168. * upgrade.
  169. *
  170. * @return IRepairStep[]
  171. */
  172. public static function getBeforeUpgradeRepairSteps() {
  173. $connection = \OC::$server->getDatabaseConnection();
  174. $config = \OC::$server->getConfig();
  175. $steps = [
  176. new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connection, true),
  177. new SqliteAutoincrement($connection),
  178. new SaveAccountsTableData($connection, $config),
  179. new DropAccountTermsTable($connection)
  180. ];
  181. return $steps;
  182. }
  183. /**
  184. * @param string $scope
  185. * @param string $method
  186. * @param array $arguments
  187. */
  188. public function emit($scope, $method, array $arguments = []) {
  189. if (!is_null($this->dispatcher)) {
  190. $this->dispatcher->dispatch("$scope::$method",
  191. new GenericEvent("$scope::$method", $arguments));
  192. }
  193. }
  194. public function info($string) {
  195. // for now just emit as we did in the past
  196. $this->emit('\OC\Repair', 'info', [$string]);
  197. }
  198. /**
  199. * @param string $message
  200. */
  201. public function warning($message) {
  202. // for now just emit as we did in the past
  203. $this->emit('\OC\Repair', 'warning', [$message]);
  204. }
  205. /**
  206. * @param int $max
  207. */
  208. public function startProgress($max = 0) {
  209. // for now just emit as we did in the past
  210. $this->emit('\OC\Repair', 'startProgress', [$max, $this->currentStep]);
  211. }
  212. /**
  213. * @param int $step
  214. * @param string $description
  215. */
  216. public function advance($step = 1, $description = '') {
  217. // for now just emit as we did in the past
  218. $this->emit('\OC\Repair', 'advance', [$step, $description]);
  219. }
  220. /**
  221. * @param int $max
  222. */
  223. public function finishProgress() {
  224. // for now just emit as we did in the past
  225. $this->emit('\OC\Repair', 'finishProgress', []);
  226. }
  227. }