Fix password protected rooms in chat backend

Before, any user was able to send and receive messages to and from
public password protected rooms, even if they were not invited and they
had not joined it; guests were not able to send, but were able to
receive nevertheless. Now, only invited users or users/guests that have
joined a public password protected room can send and receive messages to
and from it.

As a side effect that change affects too to regular public rooms (not
password protected), but the new behaviour makes more sense than the old
one anyway.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Daniel Calviño Sánchez 2017-10-20 03:37:13 +02:00
Родитель 943a85d869
Коммит ce9155289b
4 изменённых файлов: 424 добавлений и 51 удалений

Просмотреть файл

@ -24,6 +24,7 @@
namespace OCA\Spreed\Controller;
use OCA\Spreed\Chat\ChatManager;
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\RoomNotFoundException;
use OCA\Spreed\Manager;
use OCP\AppFramework\Http;
@ -75,6 +76,39 @@ class ChatController extends OCSController {
$this->chatManager = $chatManager;
}
/**
* Returns the Room for the current user.
*
* If the user is currently not joined to a room then the room with the
* given token is returned (provided that the current user is a participant
* of that room).
*
* @param string $token the token for the Room.
* @return \OCA\Spreed\Room|null the Room, or null if none was found.
*/
private function getRoom($token) {
try {
$room = $this->manager->getRoomForSession($this->userId, $this->session->get('spreed-session'));
} catch (RoomNotFoundException $exception) {
if ($this->userId === null) {
return null;
}
// For logged in users we search for rooms where they are real
// participants.
try {
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
$room->getParticipant($this->userId);
} catch (RoomNotFoundException $exception) {
return null;
} catch (ParticipantNotFoundException $exception) {
return null;
}
}
return $room;
}
/**
* @PublicPage
*
@ -90,9 +124,8 @@ class ChatController extends OCSController {
* found".
*/
public function sendMessage($token, $message) {
try {
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
} catch (RoomNotFoundException $exception) {
$room = $this->getRoom($token);
if ($room === null) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
@ -154,9 +187,8 @@ class ChatController extends OCSController {
* 'message'.
*/
public function receiveMessages($token, $offset = 0, $notOlderThanTimestamp = 0, $timeout = 30) {
try {
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
} catch (RoomNotFoundException $exception) {
$room = $this->getRoom($token);
if ($room === null) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}

Просмотреть файл

@ -0,0 +1,100 @@
Feature: chat/password
Background:
Given user "participant1" exists
Given user "participant2" exists
Given user "participant3" exists
Scenario: owner can send and receive chat messages to and from public password protected room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
When user "participant1" sends message "Message 1" to room "public password protected room" with 201
Then user "participant1" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | users | participant1 | participant1-displayname | Message 1 |
Scenario: invited user can send and receive chat messages to and from public password protected room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
And user "participant1" adds "participant2" to room "public password protected room" with 200
When user "participant2" sends message "Message 1" to room "public password protected room" with 201
Then user "participant2" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | users | participant2 | participant2-displayname | Message 1 |
Scenario: not invited but joined with password user can send and receive chat messages to and from public password protected room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
And user "participant3" joins call "public password protected room" with 200
| password | foobar |
When user "participant3" sends message "Message 1" to room "public password protected room" with 201
Then user "participant3" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | users | participant3 | participant3-displayname | Message 1 |
Scenario: not invited user can not send nor receive chat messages to and from public password protected room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
When user "participant3" sends message "Message 1" to room "public password protected room" with 404
And user "participant1" sends message "Message 2" to room "public password protected room" with 201
Then user "participant3" sees the following messages in room "public password protected room" with 404
Scenario: joined with password guest can send and receive chat messages to and from public password protected room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
And user "guest" joins call "public password protected room" with 200
| password | foobar |
When user "guest" sends message "Message 1" to room "public password protected room" with 201
Then user "guest" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | guests | guest | | Message 1 |
Scenario: not joined guest can not send nor receive chat messages to and from public password protected room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
When user "guest" sends message "Message 1" to room "public password protected room" with 404
And user "participant1" sends message "Message 2" to room "public password protected room" with 201
Then user "guest" sees the following messages in room "public password protected room" with 404
Scenario: everyone in a public password protected room can receive messages from everyone in that room
Given user "participant1" creates room "public password protected room"
| roomType | 3 |
And user "participant1" sets password "foobar" for room "public password protected room" with 200
And user "participant1" adds "participant2" to room "public password protected room" with 200
And user "participant3" joins call "public password protected room" with 200
| password | foobar |
And user "guest" joins call "public password protected room" with 200
| password | foobar |
When user "participant1" sends message "Message 1" to room "public password protected room" with 201
And user "participant2" sends message "Message 2" to room "public password protected room" with 201
And user "participant3" sends message "Message 3" to room "public password protected room" with 201
And user "guest" sends message "Message 4" to room "public password protected room" with 201
Then user "participant1" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | guests | guest | | Message 4 |
| public password protected room | users | participant3 | participant3-displayname | Message 3 |
| public password protected room | users | participant2 | participant2-displayname | Message 2 |
| public password protected room | users | participant1 | participant1-displayname | Message 1 |
And user "participant2" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | guests | guest | | Message 4 |
| public password protected room | users | participant3 | participant3-displayname | Message 3 |
| public password protected room | users | participant2 | participant2-displayname | Message 2 |
| public password protected room | users | participant1 | participant1-displayname | Message 1 |
And user "participant3" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | guests | guest | | Message 4 |
| public password protected room | users | participant3 | participant3-displayname | Message 3 |
| public password protected room | users | participant2 | participant2-displayname | Message 2 |
| public password protected room | users | participant1 | participant1-displayname | Message 1 |
And user "guest" sees the following messages in room "public password protected room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public password protected room | guests | guest | | Message 4 |
| public password protected room | users | participant3 | participant3-displayname | Message 3 |
| public password protected room | users | participant2 | participant2-displayname | Message 2 |
| public password protected room | users | participant1 | participant1-displayname | Message 1 |

Просмотреть файл

@ -21,14 +21,22 @@ Feature: chat/public
| room | actorType | actorId | actorDisplayName | message |
| public room | users | participant2 | participant2-displayname | Message 1 |
Scenario: not invited user can send and receive chat messages to and from public room
Scenario: not invited but joined user can send and receive chat messages to and from public room
Given user "participant1" creates room "public room"
| roomType | 3 |
And user "participant3" joins call "public room" with 200
When user "participant3" sends message "Message 1" to room "public room" with 201
Then user "participant3" sees the following messages in room "public room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public room | users | participant3 | participant3-displayname | Message 1 |
Scenario: not invited user can not send nor receive chat messages to and from public room
Given user "participant1" creates room "public room"
| roomType | 3 |
When user "participant3" sends message "Message 1" to room "public room" with 404
And user "participant1" sends message "Message 2" to room "public room" with 201
Then user "participant3" sees the following messages in room "public room" with 404
Scenario: joined guest can send and receive chat messages to and from public room
Given user "participant1" creates room "public room"
| roomType | 3 |
@ -38,14 +46,12 @@ Feature: chat/public
| room | actorType | actorId | actorDisplayName | message |
| public room | guests | guest | | Message 1 |
Scenario: not joined guest can not send messages to public room, but she can receive them
Scenario: not joined guest can not send nor receive chat messages to and from public room
Given user "participant1" creates room "public room"
| roomType | 3 |
When user "guest" sends message "Message 1" to room "public room" with 404
And user "participant1" sends message "Message 2" to room "public room" with 201
Then user "guest" sees the following messages in room "public room" with 200
| room | actorType | actorId | actorDisplayName | message |
| public room | users | participant1 | participant1-displayname | Message 2 |
Then user "guest" sees the following messages in room "public room" with 404
Scenario: everyone in a public room can receive messages from everyone in that room
Given user "participant1" creates room "public room"

Просмотреть файл

@ -25,6 +25,7 @@ namespace OCA\Spreed\Tests\php\Controller;
use OCA\Spreed\Chat\ChatManager;
use OCA\Spreed\Controller\ChatController;
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\RoomNotFoundException;
use OCA\Spreed\Manager;
use OCA\Spreed\Room;
@ -107,18 +108,23 @@ class ChatControllerTest extends \Test\TestCase {
}
public function testSendMessageByUser() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn('testSpreedSession');
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->method('getRoomForSession')
->with($this->userId, 'testSpreedSession')
->willReturn($this->room);
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->session->expects($this->never())
->method('get');
$this->chatManager->expects($this->once())
->method('sendMessage')
->with('1234',
@ -134,24 +140,96 @@ class ChatControllerTest extends \Test\TestCase {
$this->assertEquals($expected, $response);
}
public function testSendMessageByGuest() {
$this->userId = null;
$this->recreateChatController();
public function testSendMessageByUserNotJoinedButInRoom() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->willReturn($this->room);
$this->room->expects($this->once())
->method('getParticipant')
->with($this->userId);
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->chatManager->expects($this->once())
->method('sendMessage')
->with('1234',
'users',
$this->userId,
'testMessage',
$this->newMessageDateTimeConstraint
);
$response = $this->controller->sendMessage('testToken', 'testMessage');
$expected = new DataResponse([], Http::STATUS_CREATED);
$this->assertEquals($expected, $response);
}
public function testSendMessageByUserNotJoinedNorInRoom() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->willReturn($this->room);
$this->room->expects($this->once())
->method('getParticipant')
->with($this->userId)
->will($this->throwException(new ParticipantNotFoundException()));
$this->chatManager->expects($this->never())
->method('sendMessage');
$response = $this->controller->sendMessage('testToken', 'testMessage');
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
$this->assertEquals($expected, $response);
}
public function testSendMessageByGuest() {
$this->userId = null;
$this->recreateChatController();
$this->session->expects($this->any())
->method('get')
->with('spreed-session')
->willReturn('testSpreedSession');
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, 'testSpreedSession')
->willReturn($this->room);
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->chatManager->expects($this->once())
->method('sendMessage')
->with('1234',
@ -171,16 +249,19 @@ class ChatControllerTest extends \Test\TestCase {
$this->userId = null;
$this->recreateChatController();
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->willReturn($this->room);
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->chatManager->expects($this->never())
->method('sendMessage');
@ -191,14 +272,21 @@ class ChatControllerTest extends \Test\TestCase {
}
public function testSendMessageToInvalidRoom() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->will($this->throwException(new RoomNotFoundException()));
$this->session->expects($this->never())
->method('get');
$this->chatManager->expects($this->never())
->method('sendMessage');
@ -209,18 +297,23 @@ class ChatControllerTest extends \Test\TestCase {
}
public function testReceiveMessagesByUser() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn('testSpreedSession');
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->method('getRoomForSession')
->with($this->userId, 'testSpreedSession')
->willReturn($this->room);
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->session->expects($this->never())
->method('get');
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;
@ -255,22 +348,118 @@ class ChatControllerTest extends \Test\TestCase {
$this->assertEquals($expected, $response);
}
public function testReceiveMessagesByUserNotJoinedButInRoom() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->willReturn($this->room);
$this->room->expects($this->once())
->method('getParticipant')
->with($this->userId);
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;
$this->chatManager->expects($this->once())
->method('receiveMessages')
->with('1234', $timeout, $offset, new \DateTime('@' . $timestamp))
->willReturn([
$this->newComment(111, 'users', 'testUser', new \DateTime('@' . 1000000016), 'testMessage4'),
$this->newComment(110, 'users', 'testUnknownUser', new \DateTime('@' . 1000000015), 'testMessage3'),
$this->newComment(109, 'guests', 'testSpreedSession', new \DateTime('@' . 1000000008), 'testMessage2'),
$this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000004), 'testMessage1')
]);
$testUser = $this->createMock(IUser::class);
$testUser->expects($this->exactly(2))
->method('getDisplayName')
->willReturn('Test User');
$this->userManager->expects($this->exactly(3))
->method('get')
->withConsecutive(['testUser'], ['testUnknownUser'], ['testUser'])
->willReturn($testUser, null, $testUser);
$response = $this->controller->receiveMessages('testToken', $offset, $timestamp, $timeout);
$expected = new DataResponse([
['id'=>111, 'token'=>'testToken', 'actorType'=>'users', 'actorId'=>'testUser', 'actorDisplayName'=>'Test User', 'timestamp'=>1000000016, 'message'=>'testMessage4'],
['id'=>110, 'token'=>'testToken', 'actorType'=>'users', 'actorId'=>'testUnknownUser', 'actorDisplayName'=>null, 'timestamp'=>1000000015, 'message'=>'testMessage3'],
['id'=>109, 'token'=>'testToken', 'actorType'=>'guests', 'actorId'=>'testSpreedSession', 'actorDisplayName'=>null, 'timestamp'=>1000000008, 'message'=>'testMessage2'],
['id'=>108, 'token'=>'testToken', 'actorType'=>'users', 'actorId'=>'testUser', 'actorDisplayName'=>'Test User', 'timestamp'=>1000000004, 'message'=>'testMessage1']
], Http::STATUS_OK);
$this->assertEquals($expected, $response);
}
public function testReceiveMessagesByUserNotJoinedNorInRoom() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->willReturn($this->room);
$this->room->expects($this->once())
->method('getParticipant')
->with($this->userId)
->will($this->throwException(new ParticipantNotFoundException()));
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;
$this->chatManager->expects($this->never())
->method('receiveMessages');
$response = $this->controller->receiveMessages('testToken', $offset, $timestamp, $timeout);
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
$this->assertEquals($expected, $response);
}
public function testReceiveMessagesByGuest() {
$this->userId = null;
$this->recreateChatController();
$this->session->expects($this->any())
->method('get')
->with('spreed-session')
->willReturn('testSpreedSession');
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->method('getRoomForSession')
->with($this->userId, 'testSpreedSession')
->willReturn($this->room);
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->session->expects($this->never())
->method('get');
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;
@ -305,19 +494,53 @@ class ChatControllerTest extends \Test\TestCase {
$this->assertEquals($expected, $response);
}
public function testReceiveMessagesTimeoutExpired() {
public function testReceiveMessagesByGuestNotJoined() {
$this->userId = null;
$this->recreateChatController();
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;
$this->chatManager->expects($this->never())
->method('receiveMessages');
$response = $this->controller->receiveMessages('testToken', $offset, $timestamp, $timeout);
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
$this->assertEquals($expected, $response);
}
public function testReceiveMessagesTimeoutExpired() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn('testSpreedSession');
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, 'testSpreedSession')
->willReturn($this->room);
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->session->expects($this->never())
->method('get');
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;
@ -333,18 +556,23 @@ class ChatControllerTest extends \Test\TestCase {
}
public function testReceiveMessagesTimeoutTooLarge() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn('testSpreedSession');
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->method('getRoomForSession')
->with($this->userId, 'testSpreedSession')
->willReturn($this->room);
$this->manager->expects($this->never())
->method('getRoomForParticipantByToken');
$this->room->expects($this->once())
->method('getId')
->willReturn(1234);
$this->session->expects($this->never())
->method('get');
$timeout = 100000;
$maximumTimeout = 60;
$offset = 23;
@ -361,14 +589,21 @@ class ChatControllerTest extends \Test\TestCase {
}
public function testReceiveMessagesFromInvalidRoom() {
$this->session->expects($this->once())
->method('get')
->with('spreed-session')
->willReturn(null);
$this->manager->expects($this->once())
->method('getRoomForSession')
->with($this->userId, null)
->will($this->throwException(new RoomNotFoundException()));
$this->manager->expects($this->once())
->method('getRoomForParticipantByToken')
->with('testToken', $this->userId)
->will($this->throwException(new RoomNotFoundException()));
$this->session->expects($this->never())
->method('get');
$timeout = 42;
$offset = 23;
$timestamp = 1000000000;