mirror of
https://github.com/nextcloud/spreed.git
synced 2025-12-18 05:20:50 +01:00
fix(federation): Allow accessing avatars with pending invites
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
parent
04d51b3514
commit
5907dc435c
6 changed files with 115 additions and 4 deletions
|
|
@ -28,6 +28,7 @@ declare(strict_types=1);
|
|||
namespace OCA\Talk\Controller;
|
||||
|
||||
use OC\AppFramework\Http\Dispatcher;
|
||||
use OCA\Talk\Model\Invitation;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCP\AppFramework\OCSController;
|
||||
|
|
@ -36,6 +37,7 @@ abstract class AEnvironmentAwareController extends OCSController {
|
|||
protected int $apiVersion = 1;
|
||||
protected ?Room $room = null;
|
||||
protected ?Participant $participant = null;
|
||||
protected ?Invitation $invitation = null;
|
||||
|
||||
public function setAPIVersion(int $apiVersion): void {
|
||||
$this->apiVersion = $apiVersion;
|
||||
|
|
@ -61,6 +63,14 @@ abstract class AEnvironmentAwareController extends OCSController {
|
|||
return $this->participant;
|
||||
}
|
||||
|
||||
public function setInvitation(Invitation $invitation): void {
|
||||
$this->invitation = $invitation;
|
||||
}
|
||||
|
||||
public function getInvitation(): ?Invitation {
|
||||
return $this->invitation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Following the logic of {@see Dispatcher::executeController}
|
||||
* @return string Either 'json' or 'xml'
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace OCA\Talk\Controller;
|
|||
|
||||
use InvalidArgumentException;
|
||||
use OCA\Talk\Exceptions\CannotReachRemoteException;
|
||||
use OCA\Talk\Middleware\Attribute\AllowWithoutParticipantWhenPendingInvitation;
|
||||
use OCA\Talk\Middleware\Attribute\FederationSupported;
|
||||
use OCA\Talk\Middleware\Attribute\RequireLoggedInParticipant;
|
||||
use OCA\Talk\Middleware\Attribute\RequireModeratorParticipant;
|
||||
|
|
@ -143,13 +144,14 @@ class AvatarController extends AEnvironmentAwareController {
|
|||
#[FederationSupported]
|
||||
#[PublicPage]
|
||||
#[NoCSRFRequired]
|
||||
#[AllowWithoutParticipantWhenPendingInvitation]
|
||||
#[RequireParticipantOrLoggedInAndListedConversation]
|
||||
public function getAvatar(bool $darkTheme = false): FileDisplayResponse {
|
||||
if ($this->room->getRemoteServer() !== '') {
|
||||
/** @var \OCA\Talk\Federation\Proxy\TalkV1\Controller\AvatarController $proxy */
|
||||
$proxy = \OCP\Server::get(\OCA\Talk\Federation\Proxy\TalkV1\Controller\AvatarController::class);
|
||||
try {
|
||||
return $proxy->getAvatar($this->room, $this->participant, $darkTheme);
|
||||
return $proxy->getAvatar($this->room, $this->participant, $this->invitation, $darkTheme);
|
||||
} catch (CannotReachRemoteException) {
|
||||
// Falling back to a local "globe" avatar for indicating the federation
|
||||
}
|
||||
|
|
@ -172,6 +174,7 @@ class AvatarController extends AEnvironmentAwareController {
|
|||
#[FederationSupported]
|
||||
#[PublicPage]
|
||||
#[NoCSRFRequired]
|
||||
#[AllowWithoutParticipantWhenPendingInvitation]
|
||||
#[RequireParticipantOrLoggedInAndListedConversation]
|
||||
public function getAvatarDark(): FileDisplayResponse {
|
||||
return $this->getAvatar(true);
|
||||
|
|
@ -193,6 +196,7 @@ class AvatarController extends AEnvironmentAwareController {
|
|||
#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
|
||||
#[PublicPage]
|
||||
#[NoCSRFRequired]
|
||||
#[AllowWithoutParticipantWhenPendingInvitation]
|
||||
#[RequireLoggedInParticipant]
|
||||
public function getUserProxyAvatar(int $size, string $cloudId, bool $darkTheme = false): FileDisplayResponse {
|
||||
try {
|
||||
|
|
@ -252,6 +256,7 @@ class AvatarController extends AEnvironmentAwareController {
|
|||
#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
|
||||
#[PublicPage]
|
||||
#[NoCSRFRequired]
|
||||
#[AllowWithoutParticipantWhenPendingInvitation]
|
||||
#[RequireLoggedInParticipant]
|
||||
public function getUserProxyAvatarDark(int $size, string $cloudId): FileDisplayResponse {
|
||||
return $this->getUserProxyAvatar($size, $cloudId, true);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace OCA\Talk\Federation\Proxy\TalkV1\Controller;
|
|||
|
||||
use OCA\Talk\Exceptions\CannotReachRemoteException;
|
||||
use OCA\Talk\Federation\Proxy\TalkV1\ProxyRequest;
|
||||
use OCA\Talk\Model\Invitation;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\ResponseDefinitions;
|
||||
use OCA\Talk\Room;
|
||||
|
|
@ -53,10 +54,14 @@ class AvatarController {
|
|||
*
|
||||
* 200: Room avatar returned
|
||||
*/
|
||||
public function getAvatar(Room $room, Participant $participant, bool $darkTheme): FileDisplayResponse {
|
||||
public function getAvatar(Room $room, ?Participant $participant, ?Invitation $invitation, bool $darkTheme): FileDisplayResponse {
|
||||
if ($participant === null && $invitation === null) {
|
||||
throw new CannotReachRemoteException('Must receive either participant or invitation');
|
||||
}
|
||||
|
||||
$proxy = $this->proxy->get(
|
||||
$participant->getAttendee()->getInvitedCloudId(),
|
||||
$participant->getAttendee()->getAccessToken(),
|
||||
$participant ? $participant->getAttendee()->getInvitedCloudId() : $invitation->getLocalCloudId(),
|
||||
$participant ? $participant->getAttendee()->getAccessToken() : $invitation->getAccessToken(),
|
||||
$room->getRemoteServer() . '/ocs/v2.php/apps/spreed/api/v1/room/' . $room->getRemoteToken() . '/avatar' . ($darkTheme ? '/dark' : ''),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2024 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Middleware\Attribute;
|
||||
|
||||
use Attribute;
|
||||
use OCA\Talk\Middleware\InjectionMiddleware;
|
||||
|
||||
/**
|
||||
* @see InjectionMiddleware::getRoomByInvite()
|
||||
*/
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
class AllowWithoutParticipantWhenPendingInvitation extends RequireRoom {
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ use OCA\Talk\Exceptions\PermissionsException;
|
|||
use OCA\Talk\Exceptions\RoomNotFoundException;
|
||||
use OCA\Talk\Federation\Authenticator;
|
||||
use OCA\Talk\Manager;
|
||||
use OCA\Talk\Middleware\Attribute\AllowWithoutParticipantWhenPendingInvitation;
|
||||
use OCA\Talk\Middleware\Attribute\FederationSupported;
|
||||
use OCA\Talk\Middleware\Attribute\RequireAuthenticatedParticipant;
|
||||
use OCA\Talk\Middleware\Attribute\RequireLoggedInModeratorParticipant;
|
||||
|
|
@ -46,12 +47,14 @@ use OCA\Talk\Middleware\Exceptions\LobbyException;
|
|||
use OCA\Talk\Middleware\Exceptions\NotAModeratorException;
|
||||
use OCA\Talk\Middleware\Exceptions\ReadOnlyException;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Model\InvitationMapper;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCA\Talk\TalkSession;
|
||||
use OCA\Talk\Webinary;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\BruteForceProtection;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
|
|
@ -74,6 +77,7 @@ class InjectionMiddleware extends Middleware {
|
|||
protected ICloudIdManager $cloudIdManager,
|
||||
protected IThrottler $throttler,
|
||||
protected IURLGenerator $url,
|
||||
protected InvitationMapper $invitationMapper,
|
||||
protected Authenticator $federationAuthenticator,
|
||||
protected ?string $userId,
|
||||
) {
|
||||
|
|
@ -98,6 +102,15 @@ class InjectionMiddleware extends Middleware {
|
|||
$apiVersion = $this->request->getParam('apiVersion');
|
||||
$controller->setAPIVersion((int) substr($apiVersion, 1));
|
||||
|
||||
if (!empty($reflectionMethod->getAttributes(AllowWithoutParticipantWhenPendingInvitation::class))) {
|
||||
try {
|
||||
$this->getRoomByInvite($controller);
|
||||
return;
|
||||
} catch (RoomNotFoundException|ParticipantNotFoundException) {
|
||||
// Falling back to bellow checks
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($reflectionMethod->getAttributes(RequireAuthenticatedParticipant::class))) {
|
||||
$this->getLoggedInOrGuest($controller, false, requireFederationWhenNotLoggedIn: true);
|
||||
}
|
||||
|
|
@ -232,6 +245,34 @@ class InjectionMiddleware extends Middleware {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AEnvironmentAwareController $controller
|
||||
* @throws RoomNotFoundException
|
||||
* @throws ParticipantNotFoundException
|
||||
*/
|
||||
protected function getRoomByInvite(AEnvironmentAwareController $controller): void {
|
||||
if ($this->userId === null) {
|
||||
throw new ParticipantNotFoundException('No user available');
|
||||
}
|
||||
|
||||
$room = $controller->getRoom();
|
||||
if (!$room instanceof Room) {
|
||||
$token = $this->request->getParam('token');
|
||||
$room = $this->manager->getRoomByToken($token);
|
||||
$controller->setRoom($room);
|
||||
}
|
||||
|
||||
$participant = $controller->getParticipant();
|
||||
if (!$participant instanceof Participant) {
|
||||
try {
|
||||
$invitation = $this->invitationMapper->getInvitationsForUserByLocalRoom($room, $this->userId);
|
||||
$controller->setInvitation($invitation);
|
||||
} catch (DoesNotExistException $e) {
|
||||
throw new ParticipantNotFoundException('No invite available', $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AEnvironmentAwareController $controller
|
||||
* @throws FederationUnsupportedFeatureException
|
||||
|
|
|
|||
|
|
@ -95,6 +95,20 @@ class InvitationMapper extends QBMapper {
|
|||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function getInvitationsForUserByLocalRoom(Room $room, string $userId): Invitation {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
|
||||
$query->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($query->expr()->eq('user_id', $query->createNamedParameter($userId)))
|
||||
->andWhere($query->expr()->eq('local_room_id', $query->createNamedParameter($room->getId())));
|
||||
|
||||
return $this->findEntity($query);
|
||||
}
|
||||
|
||||
public function countInvitationsForLocalRoom(Room $room): int {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue