diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 317565a2f0..3f391d5197 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -960,6 +960,7 @@ return array( 'OC\\Repair\\AddCleanupUpdaterBackupsJob' => $baseDir . '/lib/private/Repair/AddCleanupUpdaterBackupsJob.php', 'OC\\Repair\\CleanTags' => $baseDir . '/lib/private/Repair/CleanTags.php', 'OC\\Repair\\ClearFrontendCaches' => $baseDir . '/lib/private/Repair/ClearFrontendCaches.php', + 'OC\\Repair\\ClearGeneratedAvatarCache' => $baseDir . '/lib/private/Repair/ClearGeneratedAvatarCache.php', 'OC\\Repair\\Collation' => $baseDir . '/lib/private/Repair/Collation.php', 'OC\\Repair\\MoveUpdaterStepFile' => $baseDir . '/lib/private/Repair/MoveUpdaterStepFile.php', 'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index ab8e5b2126..5b8c5b195e 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -990,6 +990,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\AddCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/lib/private/Repair/AddCleanupUpdaterBackupsJob.php', 'OC\\Repair\\CleanTags' => __DIR__ . '/../../..' . '/lib/private/Repair/CleanTags.php', 'OC\\Repair\\ClearFrontendCaches' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearFrontendCaches.php', + 'OC\\Repair\\ClearGeneratedAvatarCache' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearGeneratedAvatarCache.php', 'OC\\Repair\\Collation' => __DIR__ . '/../../..' . '/lib/private/Repair/Collation.php', 'OC\\Repair\\MoveUpdaterStepFile' => __DIR__ . '/../../..' . '/lib/private/Repair/MoveUpdaterStepFile.php', 'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php', diff --git a/lib/private/Avatar.php b/lib/private/Avatar.php index 97e1c0535a..821ceb7d17 100644 --- a/lib/private/Avatar.php +++ b/lib/private/Avatar.php @@ -86,10 +86,10 @@ class Avatar implements IAvatar { * @param IConfig $config */ public function __construct(ISimpleFolder $folder, - IL10N $l, - $user, - ILogger $logger, - IConfig $config) { + IL10N $l, + $user, + ILogger $logger, + IConfig $config) { $this->folder = $folder; $this->l = $l; $this->user = $user; diff --git a/lib/private/AvatarManager.php b/lib/private/AvatarManager.php index eb45564210..8fd64bc220 100644 --- a/lib/private/AvatarManager.php +++ b/lib/private/AvatarManager.php @@ -104,4 +104,20 @@ class AvatarManager implements IAvatarManager { return new Avatar($folder, $this->l, $user, $this->logger, $this->config); } + + /** + * Clear generated avatars + */ + public function clearCachedAvatars() { + $users = $this->config->getUsersForUserValue('avatar', 'generated', 'true'); + foreach($users as $userId) { + try { + $folder = $this->appData->getFolder($userId); + $folder->delete(); + } catch (NotFoundException $e) { + $this->logger->debug("No cache for the user $userId. Ignoring..."); + } + $this->config->setUserValue($userId, 'avatar', 'generated', 'false'); + } + } } diff --git a/lib/private/Repair.php b/lib/private/Repair.php index 01724fd6a3..da825c9a7a 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -30,13 +30,19 @@ namespace OC; +use OCP\AppFramework\QueryException; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; +use OC\AvatarManager; use OC\Repair\AddCleanupUpdaterBackupsJob; use OC\Repair\CleanTags; +use OC\Repair\ClearGeneratedAvatarCache; use OC\Repair\ClearFrontendCaches; use OC\Repair\Collation; use OC\Repair\MoveUpdaterStepFile; use OC\Repair\NC11\FixMountStorages; use OC\Repair\NC13\AddLogRotateJob; +use OC\Repair\NC13\RepairInvalidPaths; use OC\Repair\NC14\AddPreviewBackgroundCleanupJob; use OC\Repair\NC14\RepairPendingCronJobs; use OC\Repair\NC15\SetVcardDatabaseUID; @@ -44,23 +50,22 @@ use OC\Repair\OldGroupMembershipShares; use OC\Repair\Owncloud\DropAccountTermsTable; use OC\Repair\Owncloud\SaveAccountsTableData; use OC\Repair\RemoveRootShares; -use OC\Repair\NC13\RepairInvalidPaths; -use OC\Repair\SqliteAutoincrement; -use OC\Repair\RepairMimeTypes; use OC\Repair\RepairInvalidShares; +use OC\Repair\RepairMimeTypes; +use OC\Repair\SqliteAutoincrement; use OC\Template\JSCombiner; use OC\Template\SCSSCacher; -use OCP\AppFramework\QueryException; -use OCP\Migration\IOutput; -use OCP\Migration\IRepairStep; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\GenericEvent; -class Repair implements IOutput{ - /* @var IRepairStep[] */ +class Repair implements IOutput { + + /** @var IRepairStep[] */ private $repairSteps; + /** @var EventDispatcher */ private $dispatcher; + /** @var string */ private $currentStep; @@ -72,7 +77,7 @@ class Repair implements IOutput{ */ public function __construct($repairSteps = [], EventDispatcher $dispatcher = null) { $this->repairSteps = $repairSteps; - $this->dispatcher = $dispatcher; + $this->dispatcher = $dispatcher; } /** @@ -81,6 +86,7 @@ class Repair implements IOutput{ public function run() { if (count($this->repairSteps) === 0) { $this->emit('\OC\Repair', 'info', array('No repair steps available')); + return; } // run each repair step @@ -137,10 +143,11 @@ class Repair implements IOutput{ new RepairInvalidPaths(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), new AddLogRotateJob(\OC::$server->getJobList()), new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OC::$server->query(SCSSCacher::class), \OC::$server->query(JSCombiner::class)), + new ClearGeneratedAvatarCache(\OC::$server->getConfig(), \OC::$server->query(AvatarManager::class)), new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()), new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()), new RepairPendingCronJobs(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), - new SetVcardDatabaseUID(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), + new SetVcardDatabaseUID(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()) ]; } @@ -152,7 +159,7 @@ class Repair implements IOutput{ */ public static function getExpensiveRepairSteps() { return [ - new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()), + new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()) ]; } @@ -164,12 +171,12 @@ class Repair implements IOutput{ */ public static function getBeforeUpgradeRepairSteps() { $connection = \OC::$server->getDatabaseConnection(); - $config = \OC::$server->getConfig(); - $steps = [ + $config = \OC::$server->getConfig(); + $steps = [ new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connection, true), new SqliteAutoincrement($connection), new SaveAccountsTableData($connection, $config), - new DropAccountTermsTable($connection), + new DropAccountTermsTable($connection) ]; return $steps; diff --git a/lib/private/Repair/ClearFrontendCaches.php b/lib/private/Repair/ClearFrontendCaches.php index 0a92aa8d20..22add525ad 100644 --- a/lib/private/Repair/ClearFrontendCaches.php +++ b/lib/private/Repair/ClearFrontendCaches.php @@ -23,11 +23,11 @@ namespace OC\Repair; -use OC\Template\JSCombiner; -use OC\Template\SCSSCacher; use OCP\ICacheFactory; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; +use OC\Template\JSCombiner; +use OC\Template\SCSSCacher; class ClearFrontendCaches implements IRepairStep { @@ -44,8 +44,8 @@ class ClearFrontendCaches implements IRepairStep { SCSSCacher $SCSSCacher, JSCombiner $JSCombiner) { $this->cacheFactory = $cacheFactory; - $this->scssCacher = $SCSSCacher; - $this->jsCombiner = $JSCombiner; + $this->scssCacher = $SCSSCacher; + $this->jsCombiner = $JSCombiner; } public function getName() { diff --git a/lib/private/Repair/ClearGeneratedAvatarCache.php b/lib/private/Repair/ClearGeneratedAvatarCache.php new file mode 100644 index 0000000000..631e793de3 --- /dev/null +++ b/lib/private/Repair/ClearGeneratedAvatarCache.php @@ -0,0 +1,72 @@ + + * + * @author John Molakvoæ + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Repair; + +use OC\AvatarManager; +use OCP\IConfig; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; +use OCP\Util; + +class ClearGeneratedAvatarCache implements IRepairStep { + + /** @var AvatarManager */ + protected $avatarManager; + + /** @var IConfig */ + private $config; + + public function __construct(IConfig $config, AvatarManager $avatarManager) { + $this->config = $config; + $this->avatarManager = $avatarManager; + } + + public function getName() { + return 'Clear every generated avatar on major updates'; + } + + /** + * Check if this repair step should run + * + * @return boolean + */ + private function shouldRun() { + $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0.0'); + + // was added to 15.0.0.4 + return version_compare($versionFromBeforeUpdate, '15.0.0.4', '<='); + } + + public function run(IOutput $output) { + if ($this->shouldRun()) { + try { + $this->avatarManager->clearCachedAvatars(); + $output->info('Avatar cache cleared'); + } catch (\Exception $e) { + $output->warning('Unable to clear the avatar cache'); + } + + } + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 938c54b8a1..8ae2cb7652 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -539,7 +539,7 @@ class Server extends ServerContainer implements IServerContainer { }); $this->registerAlias(IValidator::class, Validator::class); - $this->registerService(\OCP\IAvatarManager::class, function (Server $c) { + $this->registerService(AvatarManager::class, function(Server $c) { return new AvatarManager( $c->query(\OC\User\Manager::class), $c->getAppDataDir('avatar'), @@ -548,7 +548,8 @@ class Server extends ServerContainer implements IServerContainer { $c->getConfig() ); }); - $this->registerAlias('AvatarManager', \OCP\IAvatarManager::class); + $this->registerAlias(\OCP\IAvatarManager::class, AvatarManager::class); + $this->registerAlias('AvatarManager', AvatarManager::class); $this->registerAlias(\OCP\Support\CrashReport\IRegistry::class, \OC\Support\CrashReport\Registry::class); diff --git a/lib/public/IAvatarManager.php b/lib/public/IAvatarManager.php index 19e4b93503..4b89173d88 100644 --- a/lib/public/IAvatarManager.php +++ b/lib/public/IAvatarManager.php @@ -44,4 +44,5 @@ interface IAvatarManager { * @since 6.0.0 */ public function getAvatar(string $user) : IAvatar; + } diff --git a/tests/lib/Repair/ClearGeneratedAvatarCacheTest.php b/tests/lib/Repair/ClearGeneratedAvatarCacheTest.php new file mode 100644 index 0000000000..ec107d300d --- /dev/null +++ b/tests/lib/Repair/ClearGeneratedAvatarCacheTest.php @@ -0,0 +1,82 @@ + + * + * @author Julius Härtl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace Test\Repair; + +use OCP\IConfig; +use OCP\Migration\IOutput; +use OC\AvatarManager; +use OC\Repair\ClearGeneratedAvatarCache; + +class ClearGeneratedAvatarCacheTest extends \Test\TestCase { + + /** @var AvatarManager */ + private $avatarManager; + + /** @var IOutput */ + private $outputMock; + + /** @var IConfig */ + private $config; + + /** @var ClearGeneratedAvatarCache */ + protected $repair; + + protected function setUp() { + parent::setUp(); + + $this->outputMock = $this->createMock(IOutput::class); + $this->avatarManager = $this->createMock(AvatarManager::class); + $this->config = $this->createMock(IConfig::class); + + $this->repair = new ClearGeneratedAvatarCache($this->config, $this->avatarManager); + } + + public function shouldRunDataProvider() { + return [ + ['11.0.0.0', true], + ['15.0.0.3', true], + ['13.0.5.2', true], + ['12.0.0.0', true], + ['16.0.0.1', false], + ['15.0.0.2', true], + ['13.0.0.0', true], + ['15.0.0.5', false] + ]; + } + + /** + * @dataProvider shouldRunDataProvider + * + * @param string $from + * @param boolean $expected + */ + public function testShouldRun($from, $expected) { + $this->config->expects($this->any()) + ->method('getSystemValue') + ->with('version', '0.0.0.0') + ->willReturn($from); + + $this->assertEquals($expected, $this->invokePrivate($this->repair, 'shouldRun')); + } +} diff --git a/version.php b/version.php index 235e18bf61..6617a7a539 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(15, 0, 0, 3); +$OC_Version = array(15, 0, 0, 4); // The human readable string $OC_VersionString = '15.0.0 alpha';