Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test remote invite notifications and try to send the accept/decline on invites #7464

Merged
merged 7 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions lib/Chat/Parser/SystemMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use OCA\Talk\Room;
use OCA\Talk\Share\RoomShareProvider;
use OCP\Comments\IComment;
use OCP\Federation\ICloudIdManager;
use OCP\Files\InvalidPathException;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
Expand All @@ -57,6 +58,7 @@ class SystemMessage {
protected RoomShareProvider $shareProvider;
protected PhotoCache $photoCache;
protected IRootFolder $rootFolder;
protected ICloudIdManager $cloudIdManager;
protected IURLGenerator $url;
protected ?IL10N $l = null;

Expand All @@ -80,6 +82,7 @@ public function __construct(IUserManager $userManager,
RoomShareProvider $shareProvider,
PhotoCache $photoCache,
IRootFolder $rootFolder,
ICloudIdManager $cloudIdManager,
IURLGenerator $url) {
$this->userManager = $userManager;
$this->groupManager = $groupManager;
Expand All @@ -88,6 +91,7 @@ public function __construct(IUserManager $userManager,
$this->shareProvider = $shareProvider;
$this->photoCache = $photoCache;
$this->rootFolder = $rootFolder;
$this->cloudIdManager = $cloudIdManager;
$this->url = $url;
}

Expand Down Expand Up @@ -285,6 +289,26 @@ public function parseMessage(Message $chatMessage): void {
$parsedMessage = $this->l->t('An administrator removed {user}');
}
}
} elseif ($message === 'federated_user_added') {
$parsedParameters['federated_user'] = $this->getRemoteUser($parameters['federated_user']);
$parsedMessage = $this->l->t('{actor} invited {user}');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You invited {user}');
} elseif ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator invited {user}');
} elseif ($parsedParameters['federated_user']['id'] === $parsedParameters['actor']['id']) {
$parsedMessage = $this->l->t('{federated_user} accepted the invitation');
}
} elseif ($message === 'federated_user_removed') {
$parsedParameters['federated_user'] = $this->getRemoteUser($parameters['federated_user']);
$parsedMessage = $this->l->t('{actor} removed {federated_user}');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You removed {federated_user}');
} elseif ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator removed {federated_user}');
} elseif ($parsedParameters['federated_user']['id'] === $parsedParameters['actor']['id']) {
$parsedMessage = $this->l->t('{federated_user} declined the invitation');
}
} elseif ($message === 'group_added') {
$parsedParameters['group'] = $this->getGroup($parameters['group']);
$parsedMessage = $this->l->t('{actor} added group {group}');
Expand Down Expand Up @@ -588,6 +612,9 @@ protected function getActor(Room $room, string $actorType, string $actorId): arr
if ($actorType === Attendee::ACTOR_GUESTS) {
return $this->getGuest($room, $actorId);
}
if ($actorType === Attendee::ACTOR_FEDERATED_USERS) {
return $this->getRemoteUser($actorId);
}

return $this->getUser($actorId);
}
Expand Down Expand Up @@ -616,6 +643,17 @@ protected function getUser(string $uid): array {
];
}

protected function getRemoteUser(string $federationId): array {
$cloudId = $this->cloudIdManager->resolveCloudId($federationId);

return [
'type' => 'user',
'id' => $cloudId->getUser(),
'name' => $cloudId->getDisplayId(),
'server' => $cloudId->getRemote(),
];
}

protected function getDisplayName(string $uid): string {
$user = $this->userManager->get($uid);
if ($user instanceof IUser) {
Expand Down
7 changes: 7 additions & 0 deletions lib/Chat/SystemMessage/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ protected function attendeesAddedEvent(AttendeesAddedEvent $event): void {
$this->sendSystemMessage($event->getRoom(), 'group_added', ['group' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_CIRCLES) {
$this->sendSystemMessage($event->getRoom(), 'circle_added', ['circle' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_FEDERATED_USERS) {
$this->sendSystemMessage($event->getRoom(), 'federated_user_added', ['federated_user' => $attendee->getActorId()]);
}
}
}
Expand All @@ -380,6 +382,8 @@ protected function attendeesRemovedEvent(AttendeesRemovedEvent $event): void {
$this->sendSystemMessage($event->getRoom(), 'group_removed', ['group' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_CIRCLES) {
$this->sendSystemMessage($event->getRoom(), 'circle_removed', ['circle' => $attendee->getActorId()]);
} elseif ($attendee->getActorType() === Attendee::ACTOR_FEDERATED_USERS) {
$this->sendSystemMessage($event->getRoom(), 'federated_user_removed', ['federated_user' => $attendee->getActorId()]);
}
}
}
Expand All @@ -399,6 +403,9 @@ protected function sendSystemMessage(Room $room, string $message, array $paramet
} elseif ($this->session->exists('talk-overwrite-actor')) {
$actorType = Attendee::ACTOR_USERS;
$actorId = $this->session->get('talk-overwrite-actor');
} elseif ($this->session->exists('talk-overwrite-actor-type')) {
$actorType = $this->session->get('talk-overwrite-actor-type');
$actorId = $this->session->get('talk-overwrite-actor-id');
} else {
$actorType = Attendee::ACTOR_GUESTS;
$sessionId = $this->talkSession->getSessionForRoom($room->getToken());
Expand Down
41 changes: 37 additions & 4 deletions lib/Federation/CloudFederationProviderTalk.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use OCA\FederatedFileSharing\AddressHandler;
use OCA\Talk\AppInfo\Application;
use OCA\Talk\Config;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Manager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\AttendeeMapper;
Expand All @@ -37,18 +38,21 @@
use OCA\Talk\Service\ParticipantService;
use OCP\AppFramework\Http;
use OCP\DB\Exception as DBException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\Exceptions\ActionNotSupportedException;
use OCP\Federation\Exceptions\AuthenticationFailedException;
use OCP\Federation\Exceptions\BadRequestException;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\ICloudFederationProvider;
use OCP\Federation\ICloudFederationShare;
use OCP\HintException;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager as INotificationManager;
use OCP\Share\Exceptions\ShareNotFound;
use Psr\Log\LoggerInterface;

class CloudFederationProviderTalk implements ICloudFederationProvider {
private IUserManager $userManager;
Expand All @@ -68,6 +72,9 @@ class CloudFederationProviderTalk implements ICloudFederationProvider {
private AttendeeMapper $attendeeMapper;

private Manager $manager;
private ISession $session;
private IEventDispatcher $dispatcher;
private LoggerInterface $logger;

public function __construct(
IUserManager $userManager,
Expand All @@ -78,7 +85,10 @@ public function __construct(
IURLGenerator $urlGenerator,
ParticipantService $participantService,
AttendeeMapper $attendeeMapper,
Manager $manager
Manager $manager,
ISession $session,
IEventDispatcher $dispatcher,
LoggerInterface $logger
) {
$this->userManager = $userManager;
$this->addressHandler = $addressHandler;
Expand All @@ -89,6 +99,9 @@ public function __construct(
$this->participantService = $participantService;
$this->attendeeMapper = $attendeeMapper;
$this->manager = $manager;
$this->session = $session;
$this->dispatcher = $dispatcher;
$this->logger = $logger;
}

/**
Expand All @@ -105,15 +118,18 @@ public function getShareType(): string {
*/
public function shareReceived(ICloudFederationShare $share): string {
if (!$this->config->isFederationEnabled()) {
$this->logger->debug('Received a federation invite but federation is disabled');
throw new ProviderCouldNotAddShareException('Server does not support talk federation', '', Http::STATUS_SERVICE_UNAVAILABLE);
}
if (!in_array($share->getShareType(), $this->getSupportedShareTypes(), true)) {
$this->logger->debug('Received a federation invite for invalid share type');
throw new ProviderCouldNotAddShareException('Support for sharing with non-users not implemented yet', '', Http::STATUS_NOT_IMPLEMENTED);
// TODO: Implement group shares
}

$roomType = $share->getProtocol()['roomType'];
if (!is_numeric($roomType) || !in_array((int) $roomType, $this->validSharedRoomTypes(), true)) {
$this->logger->debug('Received a federation invite for invalid room type');
throw new ProviderCouldNotAddShareException('roomType is not a valid number', '', Http::STATUS_BAD_REQUEST);
}

Expand All @@ -139,6 +155,7 @@ public function shareReceived(ICloudFederationShare $share): string {
if ($remote && $shareSecret && $shareWith && $roomToken && $remoteId && is_string($roomName) && $roomName && $owner) {
$shareWith = $this->userManager->get($shareWith);
if ($shareWith === null) {
$this->logger->debug('Received a federation invite for user that could not be found');
throw new ProviderCouldNotAddShareException('User does not exist', '', Http::STATUS_BAD_REQUEST);
}

Expand All @@ -147,6 +164,8 @@ public function shareReceived(ICloudFederationShare $share): string {
$this->notifyAboutNewShare($shareWith, $shareId, $sharedByFederatedId, $sharedBy, $roomName, $roomToken, $remote);
return $shareId;
}

$this->logger->debug('Received a federation invite with missing request data');
throw new ProviderCouldNotAddShareException('required request data not found', '', Http::STATUS_BAD_REQUEST);
}

Expand Down Expand Up @@ -183,7 +202,15 @@ public function notificationReceived($notificationType, $providerId, array $noti
private function shareAccepted(int $id, array $notification): array {
$attendee = $this->getAttendeeAndValidate($id, $notification['sharedSecret']);

// TODO: Add activity for share accepted
$this->session->set('talk-overwrite-actor-type', $attendee->getActorType());
$this->session->set('talk-overwrite-actor-id', $attendee->getActorId());

$room = $this->manager->getRoomById($attendee->getRoomId());
$event = new AttendeesAddedEvent($room, [$attendee]);
$this->dispatcher->dispatchTyped($event);

$this->session->remove('talk-overwrite-actor-type');
$this->session->remove('talk-overwrite-actor-id');

return [];
}
Expand All @@ -196,9 +223,15 @@ private function shareAccepted(int $id, array $notification): array {
private function shareDeclined(int $id, array $notification): array {
$attendee = $this->getAttendeeAndValidate($id, $notification['sharedSecret']);

$this->session->set('talk-overwrite-actor-type', $attendee->getActorType());
$this->session->set('talk-overwrite-actor-id', $attendee->getActorId());

$room = $this->manager->getRoomById($attendee->getRoomId());
$participant = new Participant($room, $attendee, null);
$this->participantService->removeAttendee($room, $participant, Room::PARTICIPANT_LEFT);

$this->session->remove('talk-overwrite-actor-type');
$this->session->remove('talk-overwrite-actor-id');
return [];
}

Expand Down Expand Up @@ -287,12 +320,12 @@ private function notifyAboutNewShare(IUser $shareWith, string $shareId, string $

$declineAction = $notification->createAction();
$declineAction->setLabel('decline')
->setLink($this->urlGenerator->linkToOCSRouteAbsolute('spreed.Federation.rejectShare', ['id' => $shareId]), 'DELETE');
->setLink($this->urlGenerator->linkToOCSRouteAbsolute('spreed.Federation.rejectShare', ['apiVersion' => 'v1', 'id' => $shareId]), 'DELETE');
$notification->addAction($declineAction);

$acceptAction = $notification->createAction();
$acceptAction->setLabel('accept')
->setLink($this->urlGenerator->linkToOCSRouteAbsolute('spreed.Federation.acceptShare', ['id' => $shareId]), 'POST');
->setLink($this->urlGenerator->linkToOCSRouteAbsolute('spreed.Federation.acceptShare', ['apiVersion' => 'v1', 'id' => $shareId]), 'POST');
$notification->addAction($acceptAction);

$this->notificationManager->notify($notification);
Expand Down
18 changes: 11 additions & 7 deletions lib/Notification/Notifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ public function prepare(INotification $notification, string $languageCode): INot
return $this->parseHostedSignalingServer($notification, $l);
}

if ($notification->getObjectType() === 'remote_talk_share') {
return $this->parseRemoteInvitationMessage($notification, $l);
}

try {
$room = $this->getRoom($notification->getObjectId(), $userId);
} catch (RoomNotFoundException $e) {
Expand Down Expand Up @@ -252,10 +256,6 @@ public function prepare(INotification $notification, string $languageCode): INot
return $this->parseChatMessage($notification, $room, $participant, $l);
}

if ($subject === 'remote_talk_share') {
return $this->parseRemoteInvitationMessage($notification, $l);
}

$this->notificationManager->markProcessed($notification);
throw new \InvalidArgumentException('Unknown subject');
}
Expand Down Expand Up @@ -300,11 +300,15 @@ protected function parseRemoteInvitationMessage(INotification $notification, IL1
$placeholders = $replacements = [];
foreach ($rosParameters as $placeholder => $parameter) {
$placeholders[] = '{' . $placeholder .'}';
$replacements[] = $parameter['name'];
if ($parameter['type'] === 'user') {
$replacements[] = '@' . $parameter['name'];
} else {
$replacements[] = $parameter['name'];
}
}

$notification->setParsedMessage(str_replace($placeholders, $replacements, $message));
$notification->setRichMessage($message, $rosParameters);
$notification->setParsedSubject(str_replace($placeholders, $replacements, $message));
$notification->setRichSubject($message, $rosParameters);

return $notification;
}
Expand Down
Loading