Skip to content
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
14 changes: 12 additions & 2 deletions lib/Chat/Parser/SystemMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,25 @@ public function parseMessage(IComment $comment): array {
} else if ($message === 'user_added') {
$parsedParameters['user'] = $this->getUser($parameters['user']);
$parsedMessage = $this->l->t('{actor} added {user}');
if ($currentUserIsActor) {
if ($parsedParameters['user']['id'] === $parsedParameters['actor']['id']) {
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You joined the conversation');
} else {
$parsedMessage = $this->l->t('{actor} joined the conversation');
}
} else if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You added {user}');
} else if ($this->recipient instanceof IUser && $this->recipient->getUID() === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} added you');
}
} else if ($message === 'user_removed') {
$parsedParameters['user'] = $this->getUser($parameters['user']);
if ($parsedParameters['user']['id'] === $parsedParameters['actor']['id']) {
$parsedMessage = $this->l->t('{actor} left the conversation');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You left the conversation');
} else {
$parsedMessage = $this->l->t('{actor} left the conversation');
}
} else {
$parsedMessage = $this->l->t('{actor} removed {user}');
if ($currentUserIsActor) {
Expand Down
2 changes: 1 addition & 1 deletion lib/Chat/SystemMessage/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public function register() {
/** @var Room $room */
$room = $event->getSubject();
foreach ($participants as $participant) {
if ($userId !== $participant['userId']) {
if ($room->getObjectType() === 'file' || $userId !== $participant['userId']) {
$this->sendSystemMessage($room, 'user_added', ['user' => $participant['userId']]);
}
}
Expand Down
13 changes: 11 additions & 2 deletions lib/Controller/FilesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace OCA\Spreed\Controller;

use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\RoomNotFoundException;
use OCA\Spreed\Files\Util;
use OCA\Spreed\Manager;
Expand Down Expand Up @@ -75,8 +76,10 @@ public function __construct(
* If there is no room associated to the given file id a new room is
* created; the new room is a public room associated with a "file" object
* with the given file id. Unlike normal rooms in which the owner is the
* user that created the room these are special rooms without owner or any
* other persistent participant.
* user that created the room these are special rooms without owner
* (although self joined users become persistent participants automatically
* when they join until they explicitly leave or no longer have access to
* the file).
*
* In any case, to create or even get the token of the room, the file must
* be shared and the user must have direct access to that file; an error
Expand All @@ -101,6 +104,12 @@ public function getRoom(string $fileId): DataResponse {
$room = $this->manager->createPublicRoom($node->getName(), 'file', $fileId);
}

try {
$room->getParticipant($this->currentUser);
} catch (ParticipantNotFoundException $e) {
$room->addUsers(['userId' => $this->currentUser]);
}

return new DataResponse([
'token' => $room->getToken()
]);
Expand Down
8 changes: 6 additions & 2 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use OCA\Spreed\Exceptions\InvalidPasswordException;
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\RoomNotFoundException;
use OCA\Spreed\Exceptions\UnauthorizedException;
use OCA\Spreed\GuestManager;
use OCA\Spreed\Manager;
use OCA\Spreed\Participant;
Expand Down Expand Up @@ -1084,14 +1085,17 @@ public function joinRoom(string $token, string $password = ''): DataResponse {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}

$user = $this->userManager->get($this->userId);
try {
if ($this->userId !== null) {
$newSessionId = $room->joinRoom($this->userId, $password, $this->session->getPasswordForRoom($token) === $room->getToken());
if ($user instanceof IUser) {
$newSessionId = $room->joinRoom($user, $password, $this->session->getPasswordForRoom($token) === $room->getToken());
} else {
$newSessionId = $room->joinRoomGuest($password, $this->session->getPasswordForRoom($token) === $room->getToken());
}
} catch (InvalidPasswordException $e) {
return new DataResponse([], Http::STATUS_FORBIDDEN);
} catch (UnauthorizedException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}

$this->session->removePasswordForRoom($token);
Expand Down
27 changes: 27 additions & 0 deletions lib/Exceptions/UnauthorizedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <[email protected]>
*
* @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\Spreed\Exceptions;

class UnauthorizedException extends \Exception {

}
26 changes: 18 additions & 8 deletions lib/Files/Listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace OCA\Spreed\Files;

use OCA\Spreed\Exceptions\UnauthorizedException;
use OCA\Spreed\Room;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
Expand All @@ -35,8 +36,9 @@
* specific shared file, for example, when collaboratively editing it. The room
* is persistent and can be accessed simultaneously by any user with direct
* access (user, group, circle and room share, but not link share, for example)
* to that file. The room has no owner, and there are no persistent participants
* (it is a public room that users join and leave on each session).
* to that file. The room has no owner, although self joined users become
* persistent participants automatically when they join until they explicitly
* leave or no longer have access to the file.
*
* These rooms are associated to a "file" object, and their custom behaviour is
* provided by calling the methods of this class as a response to different room
Expand All @@ -58,14 +60,22 @@ public function register() {
$listener = function(GenericEvent $event) {
/** @var Room $room */
$room = $event->getSubject();
$this->preventUsersWithoutDirectAccessToTheFileFromJoining($room, $event->getArgument('userId'));
try {
$this->preventUsersWithoutDirectAccessToTheFileFromJoining($room, $event->getArgument('userId'));
} catch (UnauthorizedException $e) {
$event->setArgument('cancel', true);
}
};
$this->dispatcher->addListener(Room::class . '::preJoinRoom', $listener);

$listener = function(GenericEvent $event) {
/** @var Room $room */
$room = $event->getSubject();
$this->preventGuestsFromJoining($room);
try {
$this->preventGuestsFromJoining($room);
} catch (UnauthorizedException $e) {
$event->setArgument('cancel', true);
}
};
$this->dispatcher->addListener(Room::class . '::preJoinRoomGuest', $listener);
}
Expand All @@ -82,7 +92,7 @@ public function register() {
*
* @param Room $room
* @param string $userId
* @throws \Exception
* @throws UnauthorizedException
*/
public function preventUsersWithoutDirectAccessToTheFileFromJoining(Room $room, string $userId) {
if ($room->getObjectType() !== 'file') {
Expand All @@ -91,7 +101,7 @@ public function preventUsersWithoutDirectAccessToTheFileFromJoining(Room $room,

$share = $this->util->getAnyDirectShareOfFileAccessibleByUser($room->getObjectId(), $userId);
if (!$share) {
throw new \Exception('User does not have direct access to the file');
throw new UnauthorizedException('User does not have direct access to the file');
}
}

Expand All @@ -101,14 +111,14 @@ public function preventUsersWithoutDirectAccessToTheFileFromJoining(Room $room,
* This method should be called before a guest joins a room.
*
* @param Room $room
* @throws \Exception
* @throws UnauthorizedException
*/
public function preventGuestsFromJoining(Room $room) {
if ($room->getObjectType() !== 'file') {
return;
}

throw new \Exception('Guests are not allowed in rooms for files');
throw new UnauthorizedException('Guests are not allowed in rooms for files');
}

}
32 changes: 23 additions & 9 deletions lib/Room.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

use OCA\Spreed\Exceptions\InvalidPasswordException;
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\UnauthorizedException;
use OCP\Comments\IComment;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
Expand Down Expand Up @@ -596,24 +597,31 @@ public function removeParticipantBySession(Participant $participant) {
}

/**
* @param string $userId
* @param IUser $user
* @param string $password
* @param bool $passedPasswordProtection
* @return string
* @throws InvalidPasswordException
* @throws UnauthorizedException
*/
public function joinRoom($userId, $password, $passedPasswordProtection = false) {
$this->dispatcher->dispatch(self::class . '::preJoinRoom', new GenericEvent($this, [
'userId' => $userId,
public function joinRoom(IUser $user, $password, $passedPasswordProtection = false) {
$event = new GenericEvent($this, [
'userId' => $user->getUID(),
'password' => $password,
'passedPasswordProtection' => $passedPasswordProtection,
]));
]);
$this->dispatcher->dispatch(self::class . '::preJoinRoom', $event);

if ($event->hasArgument('cancel') && $event->getArgument('cancel') === true) {
$this->removeUser($user);
throw new UnauthorizedException('Participant is not allowed to join');
}

$query = $this->db->getQueryBuilder();
$query->update('talk_participants')
->set('session_id', $query->createParameter('session_id'))
->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($user->getUID())));

$sessionId = $this->secureRandom->generate(255);
$query->setParameter('session_id', $sessionId);
Expand All @@ -626,7 +634,7 @@ public function joinRoom($userId, $password, $passedPasswordProtection = false)

// User joining a public room, without being invited
$this->addUsers([
'userId' => $userId,
'userId' => $user->getUID(),
'participantType' => Participant::USER_SELF_JOINED,
'sessionId' => $sessionId,
]);
Expand All @@ -639,7 +647,7 @@ public function joinRoom($userId, $password, $passedPasswordProtection = false)
}

$this->dispatcher->dispatch(self::class . '::postJoinRoom', new GenericEvent($this, [
'userId' => $userId,
'userId' => $user->getUID(),
'password' => $password,
'passedPasswordProtection' => $passedPasswordProtection,
]));
Expand Down Expand Up @@ -692,9 +700,15 @@ public function leaveRoom($userId) {
* @param bool $passedPasswordProtection
* @return string
* @throws InvalidPasswordException
* @throws UnauthorizedException
*/
public function joinRoomGuest($password, $passedPasswordProtection = false) {
$this->dispatcher->dispatch(self::class . '::preJoinRoomGuest', new GenericEvent($this));
$event = new GenericEvent($this);
$this->dispatcher->dispatch(self::class . '::preJoinRoomGuest', $event);

if ($event->hasArgument('cancel') && $event->getArgument('cancel') === true) {
throw new UnauthorizedException('Participant is not allowed to join');
}

if (!$passedPasswordProtection && !$this->verifyPassword($password)['result']) {
throw new InvalidPasswordException();
Expand Down