diff --git a/composer.lock b/composer.lock index de55963bc01..172118b9fc5 100644 --- a/composer.lock +++ b/composer.lock @@ -258,12 +258,12 @@ "source": { "type": "git", "url": "https://github.com/nextcloud-deps/ocp.git", - "reference": "a74e96645848edc4c29ed65629543ecec4cfaea1" + "reference": "fa7ed9794598fa62f13cc4a6c4cafd25af4b6c3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/a74e96645848edc4c29ed65629543ecec4cfaea1", - "reference": "a74e96645848edc4c29ed65629543ecec4cfaea1", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/fa7ed9794598fa62f13cc4a6c4cafd25af4b6c3e", + "reference": "fa7ed9794598fa62f13cc4a6c4cafd25af4b6c3e", "shasum": "" }, "require": { @@ -295,7 +295,7 @@ "issues": "https://github.com/nextcloud-deps/ocp/issues", "source": "https://github.com/nextcloud-deps/ocp/tree/master" }, - "time": "2023-10-20T00:31:29+00:00" + "time": "2023-10-24T00:31:30+00:00" }, { "name": "psr/clock", diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 537bd4339cc..de5b348faaf 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -52,6 +52,7 @@ use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\Template\PublicTemplateResponse; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Http\TooManyRequestsResponse; use OCP\AppFramework\Services\IInitialState; use OCP\Collaboration\Reference\RenderReferenceEvent; use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent; @@ -64,9 +65,14 @@ use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; +use OCP\IUserManager; use OCP\IUserSession; +use OCP\L10N\IFactory; use OCP\Notification\IManager as INotificationManager; +use OCP\Profile\IProfileManager; use OCP\Security\Bruteforce\IThrottler; +use OCP\Security\RateLimiting\ILimiter; +use OCP\Security\RateLimiting\IRateLimitExceededException; use Psr\Log\LoggerInterface; #[IgnoreOpenAPI] @@ -95,6 +101,10 @@ public function __construct( Config $talkConfig, IConfig $serverConfig, IGroupManager $groupManager, + protected IUserManager $userManager, + protected IProfileManager $profileManager, + protected ILimiter $limiter, + protected IFactory $l10nFactory, ) { parent::__construct($appName, $request); $this->initialState = $initialState; @@ -148,7 +158,7 @@ public function duplicateSession(): Response { /** * @param string $token * @param string $callUser - * @return TemplateResponse|RedirectResponse + * @return TemplateResponse|RedirectResponse|TooManyRequestsResponse * @throws HintException */ #[NoCSRFRequired] @@ -162,17 +172,66 @@ public function index(string $token = '', string $callUser = ''): Response { return $this->pageHandler($token, $callUser); } + /** + * @throws \InvalidArgumentException + */ + protected function createContactRequestRoom(string $targetUserId): Room { + $user = $this->userManager->get($targetUserId); + if (!$user instanceof IUser) { + throw new \InvalidArgumentException('user'); + } + + if ($this->talkConfig->isNotAllowedToCreateConversations($user)) { + throw new \InvalidArgumentException('config'); + } + + if (!$this->profileManager->isProfileFieldVisible('talk', $user, null)) { + throw new \InvalidArgumentException('profile'); + } + + $l = $this->l10nFactory->get('spreed', $this->l10nFactory->getUserLanguage($user)); + + return $this->roomService->createConversation( + Room::TYPE_PUBLIC, + $l->t('Contact request'), + $user, + ); + } + /** * @param string $token * @param string $callUser * @param string $password - * @return TemplateResponse|RedirectResponse + * @return TemplateResponse|RedirectResponse|TooManyRequestsResponse * @throws HintException */ protected function pageHandler(string $token = '', string $callUser = '', string $password = ''): Response { $bruteForceToken = $token; $user = $this->userSession->getUser(); if (!$user instanceof IUser) { + if ($token === '') { + try { + $this->limiter->registerAnonRequest( + 'create-anonymous-conversation', + 5, // Five conversations + 60 * 60, // Per hour + $this->request->getRemoteAddress(), + ); + } catch (IRateLimitExceededException) { + return new TooManyRequestsResponse(); + } + + try { + $room = $this->createContactRequestRoom($callUser); + } catch (\InvalidArgumentException) { + $response = new TemplateResponse('core', '404-profile', [], TemplateResponse::RENDER_AS_GUEST); + $response->throttle(['action' => 'callUser', 'callUser' => $callUser]); + return $response; + } + + return $this->redirectToConversation($room->getToken()); + } + return $this->guestEnterRoom($token, $password); } diff --git a/lib/Profile/TalkAction.php b/lib/Profile/TalkAction.php index 943aed15b24..c7a6dc8c646 100644 --- a/lib/Profile/TalkAction.php +++ b/lib/Profile/TalkAction.php @@ -63,9 +63,10 @@ public function getDisplayId(): string { public function getTitle(): string { $visitingUser = $this->userSession->getUser(); - if (!$visitingUser || $visitingUser === $this->targetUser) { + if ($visitingUser === $this->targetUser) { return $this->l->t('Open Talk'); } + return $this->l->t('Talk to %s', [$this->targetUser->getDisplayName()]); } @@ -78,17 +79,23 @@ public function getIcon(): string { } public function getTarget(): ?string { - $visitingUser = $this->userSession->getUser(); - if ( - !$visitingUser - || $this->config->isDisabledForUser($this->targetUser) - || $this->config->isDisabledForUser($visitingUser) - ) { + if ($this->config->isDisabledForUser($this->targetUser)) { return null; } + + $visitingUser = $this->userSession->getUser(); if ($visitingUser === $this->targetUser) { return $this->urlGenerator->linkToRouteAbsolute('spreed.Page.index'); } + + if ($visitingUser && $this->config->isDisabledForUser($visitingUser)) { + return null; + } + + if (!$visitingUser && $this->config->isNotAllowedToCreateConversations($this->targetUser)) { + return null; + } + return $this->urlGenerator->linkToRouteAbsolute('spreed.Page.index') . '?callUser=' . $this->targetUser->getUID(); } }