. */ namespace SP\Modules\Web\Controllers\Account; use Defuse\Crypto\Exception\EnvironmentIsBrokenException; use SP\Core\Application; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Core\UI\ThemeIcons; use SP\Domain\Account\Dtos\AccountViewDto; use SP\Domain\Account\Ports\AccountService; use SP\Domain\Account\Ports\PublicLinkService; use SP\Domain\Common\Adapters\Serde; use SP\Domain\Common\Attributes\Action; use SP\Domain\Common\Dtos\ActionResponse; use SP\Domain\Common\Enums\ResponseType; use SP\Domain\Common\Models\Simple; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Crypt\VaultInterface; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\CryptException; use SP\Domain\Core\Exceptions\QueryException; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Http\Providers\Uri; use SP\Domain\Image\Ports\ImageService; use SP\Infrastructure\Common\Repositories\NoSuchItemException; use SP\Modules\Web\Util\ErrorUtil; use SP\Mvc\Controller\WebControllerHelper; use function SP\__; use function SP\__u; /** * Class ViewLinkController */ final class ViewLinkController extends AccountControllerBase { private readonly ThemeIcons $icons; public function __construct( Application $application, WebControllerHelper $webControllerHelper, private readonly AccountService $accountService, private readonly PublicLinkService $publicLinkService, private readonly ImageService $imageUtil ) { parent::__construct($application, $webControllerHelper); $this->icons = $this->theme->getIcons(); } /** * View public link action * * @param string $hash Link's hash * @return ActionResponse * @throws EnvironmentIsBrokenException * @throws ConstraintException * @throws CryptException * @throws QueryException * @throws SPException * @throws NoSuchItemException */ #[Action(ResponseType::PLAIN_TEXT)] public function viewLinkAction(string $hash): ActionResponse { $this->layoutHelper->getPublicLayout('account-link', 'account'); $publicLink = $this->publicLinkService->getByHash($hash); if (time() < $publicLink->getDateExpire() && $publicLink->getCountViews() < $publicLink->getMaxCountViews() ) { $this->publicLinkService->addLinkView($publicLink); $this->accountService->incrementViewCounter($publicLink->getItemId()); $this->accountService->incrementDecryptCounter($publicLink->getItemId()); $vault = Serde::deserialize($publicLink->getData(), VaultInterface::class); $accountViewDto = AccountViewDto::fromModel( Serde::deserialize( $vault->getData( $this->publicLinkService->getPublicLinkKey($publicLink->getHash())->getKey() ), Simple::class ) ); $this->view->assign( 'title', [ 'class' => 'titleNormal', 'name' => __('Account Details'), 'icon' => $this->icons->view()->getIcon(), ] ); $this->view->assign('isView', true); $useImage = $this->configData->isPublinksImageEnabled() || $this->configData->isAccountPassToImage(); $this->view->assign('useImage', $useImage); if ($useImage) { $this->view->assign( 'accountPassImage', $this->imageUtil->convertText($accountViewDto->pass) ); } else { $this->view->assign( 'copyPassRoute', $this->acl->getRouteFor(AclActionsInterface::ACCOUNT_VIEW_PASS) ); } $this->view->assign('accountData', $accountViewDto); $clientAddress = $this->configData->isDemoEnabled() ? '***' : $this->request->getClientAddress(true); $baseUrl = ($this->configData->getApplicationUrl() ?: $this->uriContext->getWebUri()) . $this->uriContext->getSubUri(); $deepLink = new Uri($baseUrl); $deepLink->addParam( 'r', sprintf( "%s/%s", $this->acl->getRouteFor(AclActionsInterface::ACCOUNT_VIEW), $accountViewDto->getId() ) ); $this->eventDispatcher->notify( 'show.account.link', new Event( $this, EventMessage::build(__u('Link viewed')) ->addDetail(__u('Account'), $accountViewDto->getName()) ->addDetail(__u('Client'), $accountViewDto->getClientName()) ->addDetail(__u('Agent'), $this->request->getHeader('User-Agent')) ->addDetail(__u('HTTPS'), $this->request->isHttps() ? __u('ON') : __u('OFF')) ->addDetail(__u('IP'), $clientAddress) ->addDetail( __u('Link'), $deepLink->getUriSigned($this->configData->getPasswordSalt()) ) ->addExtra('userId', $publicLink->getUserId()) ->addExtra('notify', $publicLink->isNotify()) ) ); } else { ErrorUtil::showErrorInView( $this->view, ErrorUtil::ERR_PAGE_NO_PERMISSION, true, 'account-link' ); } return ActionResponse::ok($this->render()); } }