* @author Christoph Wurst * @author Joas Schilling * @author John Molakvoæ * @author Julius Härtl * @author Lukas Reschke * @author Michael Weimann * @author Morris Jobke * @author Robin Appelman * @author Roeland Jago Douma * @author Thomas Müller * @author Vincent Petry * * @license AGPL-3.0 * * This code is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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, version 3, * along with this program. If not, see * */ namespace OC\Avatar; use OC\KnownUser\KnownUserService; use OC\User\Manager; use OC\User\NoUserException; use OCP\Accounts\IAccountManager; use OCP\Accounts\PropertyDoesNotExistException; use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OCP\Files\StorageNotAvailableException; use OCP\IAvatar; use OCP\IAvatarManager; use OCP\IConfig; use OCP\IL10N; use OCP\IUserSession; use Psr\Log\LoggerInterface; /** * This class implements methods to access Avatar functionality */ class AvatarManager implements IAvatarManager { public function __construct( private IUserSession $userSession, private Manager $userManager, private IAppData $appData, private IL10N $l, private LoggerInterface $logger, private IConfig $config, private IAccountManager $accountManager, private KnownUserService $knownUserService, ) { } /** * return a user specific instance of \OCP\IAvatar * * If the user is disabled a guest avatar will be returned * * @see \OCP\IAvatar * @param string $userId the ownCloud user id * @throws \Exception In case the username is potentially dangerous * @throws NotFoundException In case there is no user folder yet */ public function getAvatar(string $userId): IAvatar { $user = $this->userManager->get($userId); if ($user === null) { throw new \Exception('user does not exist'); } if (!$user->isEnabled()) { return $this->getGuestAvatar($userId); } // sanitize userID - fixes casing issue (needed for the filesystem stuff that is done below) $userId = $user->getUID(); $requestingUser = $this->userSession->getUser(); try { $folder = $this->appData->getFolder($userId); } catch (NotFoundException $e) { $folder = $this->appData->newFolder($userId); } try { $account = $this->accountManager->getAccount($user); $avatarProperties = $account->getProperty(IAccountManager::PROPERTY_AVATAR); $avatarScope = $avatarProperties->getScope(); } catch (PropertyDoesNotExistException $e) { $avatarScope = ''; } switch ($avatarScope) { // v2-private scope hides the avatar from public access and from unknown users case IAccountManager::SCOPE_PRIVATE: if ($requestingUser !== null && $this->knownUserService->isKnownToUser($requestingUser->getUID(), $userId)) { return new UserAvatar($folder, $this->l, $user, $this->logger, $this->config); } break; case IAccountManager::SCOPE_LOCAL: case IAccountManager::SCOPE_FEDERATED: case IAccountManager::SCOPE_PUBLISHED: return new UserAvatar($folder, $this->l, $user, $this->logger, $this->config); default: // use a placeholder avatar which caches the generated images return new PlaceholderAvatar($folder, $user, $this->logger); } return new PlaceholderAvatar($folder, $user, $this->logger); } /** * Clear generated avatars */ public function clearCachedAvatars(): void { $users = $this->config->getUsersForUserValue('avatar', 'generated', 'true'); foreach ($users as $userId) { // This also bumps the avatar version leading to cache invalidation in browsers $this->getAvatar($userId)->remove(); } } public function deleteUserAvatar(string $userId): void { try { $folder = $this->appData->getFolder($userId); $folder->delete(); } catch (NotFoundException $e) { $this->logger->debug("No cache for the user $userId. Ignoring avatar deletion"); } catch (NotPermittedException | StorageNotAvailableException $e) { $this->logger->error("Unable to delete user avatars for $userId. gnoring avatar deletion"); } catch (NoUserException $e) { $this->logger->debug("Account $userId not found. Ignoring avatar deletion"); } $this->config->deleteUserValue($userId, 'avatar', 'generated'); } /** * Returns a GuestAvatar. * * @param string $name The guest name, e.g. "Albert". */ public function getGuestAvatar(string $name): IAvatar { return new GuestAvatar($name, $this->logger); } }