|  | 
|  | 1 | +<?php | 
|  | 2 | + | 
|  | 3 | +declare(strict_types=1); | 
|  | 4 | +/** | 
|  | 5 | + * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl> | 
|  | 6 | + * | 
|  | 7 | + * @license GNU AGPL version 3 or any later version | 
|  | 8 | + * | 
|  | 9 | + * This program is free software: you can redistribute it and/or modify | 
|  | 10 | + * it under the terms of the GNU Affero General Public License as | 
|  | 11 | + * published by the Free Software Foundation, either version 3 of the | 
|  | 12 | + * License, or (at your option) any later version. | 
|  | 13 | + * | 
|  | 14 | + * This program is distributed in the hope that it will be useful, | 
|  | 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 17 | + * GNU Affero General Public License for more details. | 
|  | 18 | + * | 
|  | 19 | + * You should have received a copy of the GNU Affero General Public License | 
|  | 20 | + * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 21 | + * | 
|  | 22 | + */ | 
|  | 23 | + | 
|  | 24 | +namespace OC\Authentication\Listeners; | 
|  | 25 | + | 
|  | 26 | +use OC\Files\Cache\Cache; | 
|  | 27 | +use OCP\EventDispatcher\Event; | 
|  | 28 | +use OCP\EventDispatcher\IEventListener; | 
|  | 29 | +use OCP\Files\Config\IMountProviderCollection; | 
|  | 30 | +use OCP\Files\Storage\IStorage; | 
|  | 31 | +use OCP\User\Events\BeforeUserDeletedEvent; | 
|  | 32 | +use OCP\User\Events\UserDeletedEvent; | 
|  | 33 | + | 
|  | 34 | +class UserDeletedFilesCleanupListener implements IEventListener { | 
|  | 35 | +	/** @var array<string,IStorage> */ | 
|  | 36 | +	private $homeStorageCache = []; | 
|  | 37 | + | 
|  | 38 | +	/** @var IMountProviderCollection */ | 
|  | 39 | +	private $mountProviderCollection; | 
|  | 40 | + | 
|  | 41 | +	public function __construct(IMountProviderCollection $mountProviderCollection) { | 
|  | 42 | +		$this->mountProviderCollection = $mountProviderCollection; | 
|  | 43 | +	} | 
|  | 44 | + | 
|  | 45 | +	public function handle(Event $event): void { | 
|  | 46 | +		// since we can't reliably get the user home storage after the user is deleted | 
|  | 47 | +		// but the user deletion might get canceled during the before event | 
|  | 48 | +		// we only cache the user home storage during the before event and then do the | 
|  | 49 | +		// action deletion during the after event | 
|  | 50 | + | 
|  | 51 | +		if ($event instanceof BeforeUserDeletedEvent) { | 
|  | 52 | +			$userHome = $this->mountProviderCollection->getHomeMountForUser($event->getUser()); | 
|  | 53 | +			$storage = $userHome->getStorage(); | 
|  | 54 | +			if (!$storage) { | 
|  | 55 | +				throw new \Exception("User has no home storage"); | 
|  | 56 | +			} | 
|  | 57 | +			$this->homeStorageCache[$event->getUser()->getUID()] = $storage; | 
|  | 58 | +		} | 
|  | 59 | +		if ($event instanceof UserDeletedEvent) { | 
|  | 60 | +			if (!isset($this->homeStorageCache[$event->getUser()->getUID()])) { | 
|  | 61 | +				throw new \Exception("UserDeletedEvent fired without matching BeforeUserDeletedEvent"); | 
|  | 62 | +			} | 
|  | 63 | +			$storage = $this->homeStorageCache[$event->getUser()->getUID()]; | 
|  | 64 | +			$cache = $storage->getCache(); | 
|  | 65 | +			if ($cache instanceof Cache) { | 
|  | 66 | +				$cache->clear(); | 
|  | 67 | +			} else { | 
|  | 68 | +				throw new \Exception("Home storage has invalid cache"); | 
|  | 69 | +			} | 
|  | 70 | +			$storage->rmdir(''); | 
|  | 71 | +		} | 
|  | 72 | +	} | 
|  | 73 | +} | 
0 commit comments