From 98047e8c1cd8c741f4a3d63b970f7e15fa76c128 Mon Sep 17 00:00:00 2001 From: Ruben Homs Date: Mon, 29 Oct 2018 15:36:16 +0100 Subject: [PATCH] Stop decryption when maintenance mode is enabled, fixes #8311 Signed-off-by: Ruben Homs --- core/Command/Encryption/DecryptAll.php | 9 ++++ core/Command/Encryption/ListModules.php | 18 ++++++- core/Command/Encryption/SetDefaultModule.php | 18 ++++++- core/register_command.php | 4 +- .../Command/Encryption/DecryptAllTest.php | 8 +-- .../Encryption/SetDefaultModuleTest.php | 54 +++++++++++++++++-- 6 files changed, 99 insertions(+), 12 deletions(-) diff --git a/core/Command/Encryption/DecryptAll.php b/core/Command/Encryption/DecryptAll.php index 6ae9019696..2d45689d1b 100644 --- a/core/Command/Encryption/DecryptAll.php +++ b/core/Command/Encryption/DecryptAll.php @@ -132,6 +132,15 @@ class DecryptAll extends Command { return; } + $isMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false); + if ($isMaintenanceModeEnabled) { + $output->writeln("Maintenance mode must be disabled when starting decryption,"); + $output->writeln("in order to load the relevant encryption modules correctly."); + $output->writeln("Your instance will automatically be put to maintenance mode"); + $output->writeln("during the actual decryption of the files."); + return; + } + try { if ($this->encryptionManager->isEnabled() === true) { $output->write('Disable server side encryption... '); diff --git a/core/Command/Encryption/ListModules.php b/core/Command/Encryption/ListModules.php index 82a2e5f50f..2b1402ed5e 100644 --- a/core/Command/Encryption/ListModules.php +++ b/core/Command/Encryption/ListModules.php @@ -24,6 +24,7 @@ namespace OC\Core\Command\Encryption; use OC\Core\Command\Base; use OCP\Encryption\IManager; +use OCP\IConfig; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -31,12 +32,20 @@ class ListModules extends Base { /** @var IManager */ protected $encryptionManager; + /** @var IConfig */ + protected $config; + /** * @param IManager $encryptionManager + * @param IConfig $config */ - public function __construct(IManager $encryptionManager) { + public function __construct( + IManager $encryptionManager, + IConfig $config + ) { parent::__construct(); $this->encryptionManager = $encryptionManager; + $this->config = $config; } protected function configure() { @@ -49,6 +58,13 @@ class ListModules extends Base { } protected function execute(InputInterface $input, OutputInterface $output) { + $isMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false); + if ($isMaintenanceModeEnabled) { + $output->writeln("Maintenance mode must be disabled when listing modules"); + $output->writeln("in order to list the relevant encryption modules correctly."); + return; + } + $encryptionModules = $this->encryptionManager->getEncryptionModules(); $defaultEncryptionModuleId = $this->encryptionManager->getDefaultEncryptionModuleId(); diff --git a/core/Command/Encryption/SetDefaultModule.php b/core/Command/Encryption/SetDefaultModule.php index 1a008c7724..3399bd45b2 100644 --- a/core/Command/Encryption/SetDefaultModule.php +++ b/core/Command/Encryption/SetDefaultModule.php @@ -24,6 +24,7 @@ namespace OC\Core\Command\Encryption; use OCP\Encryption\IManager; +use OCP\IConfig; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -33,12 +34,20 @@ class SetDefaultModule extends Command { /** @var IManager */ protected $encryptionManager; + /** @var IConfig */ + protected $config; + /** * @param IManager $encryptionManager + * @param IConfig $config */ - public function __construct(IManager $encryptionManager) { + public function __construct( + IManager $encryptionManager, + IConfig $config + ) { parent::__construct(); $this->encryptionManager = $encryptionManager; + $this->config = $config; } protected function configure() { @@ -56,6 +65,13 @@ class SetDefaultModule extends Command { } protected function execute(InputInterface $input, OutputInterface $output) { + $isMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false); + if ($isMaintenanceModeEnabled) { + $output->writeln("Maintenance mode must be disabled when setting default module,"); + $output->writeln("in order to load the relevant encryption modules correctly."); + return; + } + $moduleId = $input->getArgument('module'); if ($moduleId === $this->encryptionManager->getDefaultEncryptionModuleId()) { diff --git a/core/register_command.php b/core/register_command.php index 6bd1b1b18a..8690e1d1cb 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -99,8 +99,8 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig())); $application->add(new OC\Core\Command\Encryption\Enable(\OC::$server->getConfig(), \OC::$server->getEncryptionManager())); - $application->add(new OC\Core\Command\Encryption\ListModules(\OC::$server->getEncryptionManager())); - $application->add(new OC\Core\Command\Encryption\SetDefaultModule(\OC::$server->getEncryptionManager())); + $application->add(new OC\Core\Command\Encryption\ListModules(\OC::$server->getEncryptionManager(), \OC::$server->getConfig())); + $application->add(new OC\Core\Command\Encryption\SetDefaultModule(\OC::$server->getEncryptionManager(), \OC::$server->getConfig())); $application->add(new OC\Core\Command\Encryption\Status(\OC::$server->getEncryptionManager())); $application->add(new OC\Core\Command\Encryption\EncryptAll(\OC::$server->getEncryptionManager(), \OC::$server->getAppManager(), \OC::$server->getConfig(), new \Symfony\Component\Console\Helper\QuestionHelper())); $application->add(new OC\Core\Command\Encryption\DecryptAll( diff --git a/tests/Core/Command/Encryption/DecryptAllTest.php b/tests/Core/Command/Encryption/DecryptAllTest.php index c857286406..af97a4b4a7 100644 --- a/tests/Core/Command/Encryption/DecryptAllTest.php +++ b/tests/Core/Command/Encryption/DecryptAllTest.php @@ -148,7 +148,7 @@ class DecryptAllTest extends TestCase { ->willReturn('user1'); if ($encryptionEnabled) { - $this->config->expects($this->at(0)) + $this->config->expects($this->at(1)) ->method('setAppValue') ->with('core', 'encryption_enabled', 'no'); $this->questionHelper->expects($this->once()) @@ -160,7 +160,7 @@ class DecryptAllTest extends TestCase { ->with($this->consoleInput, $this->consoleOutput, 'user1'); } else { $this->decryptAll->expects($this->never())->method('decryptAll'); - $this->config->expects($this->at(1)) + $this->config->expects($this->at(2)) ->method('setAppValue') ->with('core', 'encryption_enabled', 'yes'); } @@ -194,12 +194,12 @@ class DecryptAllTest extends TestCase { $this->questionHelper ); - $this->config->expects($this->at(0)) + $this->config->expects($this->at(1)) ->method('setAppValue') ->with('core', 'encryption_enabled', 'no'); // make sure that we enable encryption again after a exception was thrown - $this->config->expects($this->at(3)) + $this->config->expects($this->at(4)) ->method('setAppValue') ->with('core', 'encryption_enabled', 'yes'); diff --git a/tests/Core/Command/Encryption/SetDefaultModuleTest.php b/tests/Core/Command/Encryption/SetDefaultModuleTest.php index 3f04ba7e79..2dc62d42bf 100644 --- a/tests/Core/Command/Encryption/SetDefaultModuleTest.php +++ b/tests/Core/Command/Encryption/SetDefaultModuleTest.php @@ -24,13 +24,16 @@ namespace Tests\Core\Command\Encryption; use OC\Core\Command\Encryption\SetDefaultModule; use OCP\Encryption\IManager; +use OCP\IConfig; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class SetDefaultModuleTest extends TestCase { - /** @var \PHPUnit_Framework_MockObject_MockObject */ + /** @var \PHPUnit_Framework_MockObject_MockObject|IManager */ protected $manager; + /** @var \PHPUnit_Framework_MockObject_MockObject|IConfig */ + protected $config; /** @var \PHPUnit_Framework_MockObject_MockObject */ protected $consoleInput; /** @var \PHPUnit_Framework_MockObject_MockObject */ @@ -42,14 +45,16 @@ class SetDefaultModuleTest extends TestCase { protected function setUp() { parent::setUp(); - $manager = $this->manager = $this->getMockBuilder(IManager::class) + $this->manager = $this->getMockBuilder(IManager::class) ->disableOriginalConstructor() ->getMock(); + $this->config = $this->getMockBuilder(IConfig::class) + ->getMock(); + $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock(); $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - /** @var \OCP\Encryption\IManager $manager */ - $this->command = new SetDefaultModule($manager); + $this->command = new SetDefaultModule($this->manager, $this->config); } @@ -79,6 +84,12 @@ class SetDefaultModuleTest extends TestCase { $this->manager->expects($this->once()) ->method('getDefaultEncryptionModuleId') ->willReturn($oldModule); + + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('maintenance', false) + ->willReturn(false); + if ($updateModule) { $this->manager->expects($this->once()) ->method('setDefaultEncryptionModule') @@ -92,4 +103,39 @@ class SetDefaultModuleTest extends TestCase { self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); } + + /** + * @dataProvider dataSetDefaultModule + * + * @param string $oldModule + * @param string $newModule + * @param string $updateModule + * @param bool $updateSuccess + * @param string $expectedString + */ + public function testMaintenanceMode($oldModule, $newModule, $updateModule, $updateSuccess, $expectedString) { + $this->consoleInput->expects($this->never()) + ->method('getArgument') + ->with('module') + ->willReturn($newModule); + + $this->manager->expects($this->never()) + ->method('getDefaultEncryptionModuleId') + ->willReturn($oldModule); + + $this->config->expects($this->once()) + ->method('getSystemValue') + ->with('maintenance', false) + ->willReturn(true); + + $this->consoleOutput->expects($this->at(0)) + ->method('writeln') + ->with($this->stringContains('Maintenance mode must be disabled when setting default module,')); + + $this->consoleOutput->expects($this->at(1)) + ->method('writeln') + ->with($this->stringContains('in order to load the relevant encryption modules correctly.')); + + self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]); + } }