. */ declare(strict_types=1); /** * sysPass * * @author nuxsmin * @link https://syspass.org * @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * * sysPass is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * sysPass 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with sysPass. If not, see . */ namespace SP\Modules\Web\Controllers\Helpers\Account; use SP\Domain\Account\Adapters\AccountSearchItem; use SP\Domain\Account\Dtos\AccountAclDto; use SP\Domain\Account\Models\AccountSearchView; use SP\Domain\Account\Ports\AccountAclService; use SP\Domain\Account\Ports\AccountCacheService; use SP\Domain\Account\Ports\AccountToFavoriteService; use SP\Domain\Account\Ports\AccountToTagRepository; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Bootstrap\UriContextInterface; use SP\Domain\Core\Context\Context; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\QueryException; use SP\Domain\Storage\Ports\FileCacheService; use SP\Infrastructure\Database\QueryResult; use SP\Infrastructure\File\FileException; use function SP\logger; use function SP\processException; /** * Class AccountSearchData */ final class AccountSearchData { private const COLORS = [ '2196F3', '03A9F4', '00BCD4', '009688', '4CAF50', '8BC34A', 'CDDC39', 'FFC107', '795548', '607D8B', '9E9E9E', 'FF5722', 'F44336', 'E91E63', '9C27B0', '673AB7', '3F51B5', ]; private const TEXT_LENGTH_CARDS = 40; private const TEXT_LENGTH_NORMAL = 60; private ?array $accountColor = null; public function __construct( private readonly Context $context, private readonly AccountAclService $accountAclService, private readonly AccountToTagRepository $accountToTagRepository, private readonly AccountToFavoriteService $accountToFavoriteService, private readonly AccountCacheService $accountCacheService, private readonly FileCacheService $fileCache, private readonly ConfigDataInterface $configData, private readonly UriContextInterface $uriContext, ) { $this->loadColors(); } /** * Load colors from cache */ private function loadColors(): void { try { $this->accountColor = $this->fileCache->load(); logger('Loaded accounts color cache'); } catch (FileException $e) { processException($e); } } /** * @param QueryResult $queryResult * * @return QueryResult * @throws ConstraintException * @throws QueryException */ public function buildFrom(QueryResult $queryResult): QueryResult { $maxTextLength = $this->configData->isResultsAsCards() ? self::TEXT_LENGTH_CARDS : self::TEXT_LENGTH_NORMAL; $userPreferencesData = $this->context->getUserData()->preferences; $accountLinkEnabled = (null !== $userPreferencesData && $userPreferencesData->isAccountLink()) || $this->configData->isAccountLink(); $favorites = $this->accountToFavoriteService->getForUserId($this->context->getUserData()->id); return $queryResult->mutateWithCallback( function (AccountSearchView $accountSearchView) use ( $maxTextLength, $accountLinkEnabled, $favorites ): AccountSearchItem { $cache = $this->accountCacheService->getCacheForAccount( $accountSearchView->getId(), strtotime($accountSearchView->getDateEdit()) ); // Obtener la ACL de la cuenta $accountAcl = $this->accountAclService->getAcl( AclActionsInterface::ACCOUNT_SEARCH, AccountAclDto::makeFromAccountSearch( $accountSearchView, $cache->getUsers(), $cache->getUserGroups() ) ); $tags = $this->accountToTagRepository ->getTagsByAccountId($accountSearchView->getId()) ->getDataAsArray(); $users = !$accountSearchView->getIsPrivate() ? $cache->getUsers() : null; $userGroups = !$accountSearchView->getIsPrivate() ? $cache->getUserGroups() : null; return new AccountSearchItem( $accountSearchView, $accountAcl, $this->configData, $this->uriContext, $tags, $maxTextLength, isset($favorites[$accountSearchView->getId()]), $users, $userGroups, $this->pickAccountColor($accountSearchView->getClientId()), $accountLinkEnabled ); } ); } private function pickAccountColor(int $id): string { if ($this->accountColor !== null && isset($this->accountColor[$id])) { return $this->accountColor[$id]; } // Se asigna el color de forma aleatoria a cada id $this->accountColor[$id] = '#' . self::COLORS[array_rand(self::COLORS)]; try { $this->fileCache->save($this->accountColor); logger('Saved accounts color cache'); return $this->accountColor[$id]; } catch (FileException $e) { processException($e); return ''; } } }