diff --git a/appinfo/info.xml b/appinfo/info.xml
index e685fa28db..e9f87176e3 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -17,7 +17,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
]]>
- 5.99.2
+ 5.99.3
agpl
Daniel Calviño Sánchez
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 302d7dea4a..63255e4d44 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -146,7 +146,7 @@ return [
'requirements' => ['apiVersion' => 'v1'],
],
[
- 'name' => 'Room#getRoom',
+ 'name' => 'Room#getSingleRoom',
'url' => '/api/{apiVersion}/room/{token}',
'verb' => 'GET',
'requirements' => [
diff --git a/docs/api-v1.md b/docs/api-v1.md
index bf887772d7..ab4794189b 100644
--- a/docs/api-v1.md
+++ b/docs/api-v1.md
@@ -45,6 +45,10 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
* `2` group
* `3` public
+### Read-only states
+* `0` read-write
+* `1` read-only
+
### Participant types
* `1` owner
* `2` moderator
@@ -84,6 +88,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
### 6.0
* `locked-one-to-one-rooms` - One-to-one conversations are now locked to the users. Neither guests nor other participants can be added, so the options to do that should be hidden as well. Also a user can only leave a one-to-one room (not delete). It will be deleted when the other participant left too. If the other participant posts a new chat message or starts a call, the left-participant will be re-added.
+* `read-only-rooms` - Rooms can be in `read-only` mode which means people can not do calls or write chat messages.
## Room management
@@ -137,6 +142,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
`participantType` | int | Permissions level of the current user
`participantInCall` | bool | Flag if the current user is in the call (deprecated, use `participantFlags` instead)
`participantFlags` | int | Flags of the current user (only available with `in-call-flags` capability)
+ `readOnly` | int | Read-only state for the current user (only available with `read-only-rooms` capability)
`count` | int | Number of active users
`numGuests` | int | Number of active guests
`lastPing` | int | Timestamp of the last ping of the current user (should be used for sorting)
diff --git a/lib/Capabilities.php b/lib/Capabilities.php
index 60b6a9f412..f264379455 100644
--- a/lib/Capabilities.php
+++ b/lib/Capabilities.php
@@ -66,6 +66,7 @@ class Capabilities implements IPublicCapability {
'notification-levels',
'invite-groups-and-mails',
'locked-one-to-one-rooms',
+ 'read-only-rooms',
],
],
];
diff --git a/lib/Controller/AEnvironmentAwareController.php b/lib/Controller/AEnvironmentAwareController.php
new file mode 100644
index 0000000000..6a2cda446a
--- /dev/null
+++ b/lib/Controller/AEnvironmentAwareController.php
@@ -0,0 +1,56 @@
+
+ * @copyright Copyright (c) 2016 Joas Schilling
+ *
+ * @author Lukas Reschke
+ * @author Joas Schilling
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Spreed\Controller;
+
+use OCA\Spreed\Participant;
+use OCA\Spreed\Room;
+use OCP\AppFramework\OCSController;
+
+abstract class AEnvironmentAwareController extends OCSController {
+
+ /** @var Room */
+ protected $room;
+ /** @var Participant */
+ protected $participant;
+
+ public function setRoom(Room $room): void {
+ $this->room = $room;
+ }
+
+ public function getRoom(): ?Room {
+ return $this->room;
+ }
+
+ public function setParticipant(Participant $participant): void {
+ $this->participant = $participant;
+ }
+
+ public function getParticipant(): ?Participant {
+ return $this->participant;
+ }
+
+}
diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php
index 30c192b72f..ed2437ecc8 100644
--- a/lib/Controller/ChatController.php
+++ b/lib/Controller/ChatController.php
@@ -28,12 +28,10 @@ use OCA\Spreed\Chat\AutoComplete\Sorter;
use OCA\Spreed\Chat\ChatManager;
use OCA\Spreed\Chat\MessageParser;
use OCA\Spreed\GuestManager;
-use OCA\Spreed\Participant;
use OCA\Spreed\Room;
use OCA\Spreed\TalkSession;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
-use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Collaboration\AutoComplete\IManager;
use OCP\Collaboration\Collaborators\ISearchResult;
@@ -43,7 +41,7 @@ use OCP\IL10N;
use OCP\IRequest;
use OCP\IUserManager;
-class ChatController extends OCSController {
+class ChatController extends AEnvironmentAwareController {
/** @var string */
private $userId;
@@ -80,11 +78,6 @@ class ChatController extends OCSController {
/** @var ITimeFactory */
protected $timeFactory;
- /** @var Room */
- private $room;
- /** @var Participant */
- private $participant;
-
public function __construct(string $appName,
?string $UserId,
IRequest $request,
@@ -113,17 +106,10 @@ class ChatController extends OCSController {
$this->l = $l;
}
- public function setRoom(Room $room): void {
- $this->room = $room;
- }
-
- public function setParticipant(Participant $participant): void {
- $this->participant = $participant;
- }
-
/**
* @PublicPage
* @RequireParticipant
+ * @RequireReadWriteConversation
*
* Sends a new chat message to the given room.
*
@@ -280,6 +266,7 @@ class ChatController extends OCSController {
/**
* @PublicPage
* @RequireParticipant
+ * @RequireReadWriteConversation
*
* @param string $search
* @param int $limit
diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php
index a244142a32..2299bbf3e5 100644
--- a/lib/Controller/RoomController.php
+++ b/lib/Controller/RoomController.php
@@ -39,18 +39,16 @@ use OCA\Spreed\Room;
use OCA\Spreed\TalkSession;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
-use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
use OCP\IL10N;
-use OCP\ILogger;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IGroup;
use OCP\IGroupManager;
-class RoomController extends OCSController {
+class RoomController extends AEnvironmentAwareController {
/** @var string|null */
private $userId;
/** @var TalkSession */
@@ -72,11 +70,6 @@ class RoomController extends OCSController {
/** @var IL10N */
private $l10n;
- /** @var Room */
- private $room;
- /** @var Participant */
- private $participant;
-
public function __construct(string $appName,
?string $UserId,
IRequest $request,
@@ -102,14 +95,6 @@ class RoomController extends OCSController {
$this->l10n = $l10n;
}
- public function setRoom(Room $room): void {
- $this->room = $room;
- }
-
- public function setParticipant(Participant $participant): void {
- $this->participant = $participant;
- }
-
/**
* Get all currently existent rooms which the user has joined
*
@@ -138,7 +123,7 @@ class RoomController extends OCSController {
* @param string $token
* @return DataResponse
*/
- public function getRoom(string $token): DataResponse {
+ public function getSingleRoom(string $token): DataResponse {
try {
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId, true);
@@ -177,6 +162,7 @@ class RoomController extends OCSController {
// Deprecated, use participantFlags instead.
'participantInCall' => false,
'participantFlags' => Participant::FLAG_DISCONNECTED,
+ 'readOnly' => Room::READ_WRITE,
'count' => 0,
'hasPassword' => $room->hasPassword(),
'hasCall' => false,
@@ -213,6 +199,7 @@ class RoomController extends OCSController {
// Deprecated, use participantFlags instead.
'participantInCall' => ($currentParticipant->getInCallFlags() & Participant::FLAG_IN_CALL) !== 0,
'participantFlags' => $currentParticipant->getInCallFlags(),
+ 'readOnly' => $room->getReadOnly(),
'count' => $room->getNumberOfParticipants(false, $this->timeFactory->getTime() - 30),
'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface,
'lastActivity' => $lastActivity,
diff --git a/lib/Manager.php b/lib/Manager.php
index 6dbcebcbfa..559b8e1262 100644
--- a/lib/Manager.php
+++ b/lib/Manager.php
@@ -119,7 +119,7 @@ class Manager {
]));
}
- return new Room($this, $this->db, $this->secureRandom, $this->dispatcher, $this->timeFactory, $this->hasher, (int) $row['id'], (int) $row['type'], $row['token'], $row['name'], $row['password'], (int) $row['active_guests'], $activeSince, $lastActivity, $lastMessage, (string) $row['object_type'], (string) $row['object_id']);
+ return new Room($this, $this->db, $this->secureRandom, $this->dispatcher, $this->timeFactory, $this->hasher, (int) $row['id'], (int) $row['type'], (int) $row['read_only'], $row['token'], $row['name'], $row['password'], (int) $row['active_guests'], $activeSince, $lastActivity, $lastMessage, (string) $row['object_type'], (string) $row['object_id']);
}
/**
diff --git a/lib/Middleware/Exceptions/ReadOnlyException.php b/lib/Middleware/Exceptions/ReadOnlyException.php
new file mode 100644
index 0000000000..83ea3df9f9
--- /dev/null
+++ b/lib/Middleware/Exceptions/ReadOnlyException.php
@@ -0,0 +1,31 @@
+
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Spreed\Middleware\Exceptions;
+
+use OCP\AppFramework\Http;
+
+class ReadOnlyException extends \Exception {
+ public function __construct() {
+ parent::__construct('The conversation is read-only', Http::STATUS_FORBIDDEN);
+ }
+}
diff --git a/lib/Middleware/InjectionMiddleware.php b/lib/Middleware/InjectionMiddleware.php
index 23666ceea6..738da0ebaf 100644
--- a/lib/Middleware/InjectionMiddleware.php
+++ b/lib/Middleware/InjectionMiddleware.php
@@ -23,10 +23,14 @@ declare(strict_types=1);
namespace OCA\Spreed\Middleware;
use OC\AppFramework\Utility\ControllerMethodReflector;
+use OCA\Spreed\Controller\AEnvironmentAwareController;
+use OCA\Spreed\Controller\EnvironmentAwareTrait;
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
use OCA\Spreed\Exceptions\RoomNotFoundException;
use OCA\Spreed\Manager;
use OCA\Spreed\Middleware\Exceptions\NotAModeratorException;
+use OCA\Spreed\Middleware\Exceptions\ReadOnlyException;
+use OCA\Spreed\Room;
use OCA\Spreed\TalkSession;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
@@ -69,8 +73,13 @@ class InjectionMiddleware extends Middleware {
* @throws RoomNotFoundException
* @throws ParticipantNotFoundException
* @throws NotAModeratorException
+ * @throws ReadOnlyException
*/
public function beforeController($controller, $methodName): void {
+ if (!$controller instanceof AEnvironmentAwareController) {
+ return;
+ }
+
if ($this->reflector->hasAnnotation('RequireLoggedInParticipant')) {
$this->getLoggedIn($controller, false);
}
@@ -86,9 +95,18 @@ class InjectionMiddleware extends Middleware {
if ($this->reflector->hasAnnotation('RequireModeratorParticipant')) {
$this->getLoggedInOrGuest($controller, true);
}
+
+ if ($this->reflector->hasAnnotation('RequireReadWriteConversation')) {
+ $this->checkReadOnlyState($controller);
+ }
}
- protected function getLoggedIn(Controller $controller, bool $moderatorRequired): void {
+ /**
+ * @param AEnvironmentAwareController $controller
+ * @param bool $moderatorRequired
+ * @throws NotAModeratorException
+ */
+ protected function getLoggedIn(AEnvironmentAwareController $controller, bool $moderatorRequired): void {
$token = $this->request->getParam('token');
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
$participant = $room->getParticipant($this->userId);
@@ -101,7 +119,12 @@ class InjectionMiddleware extends Middleware {
$controller->setParticipant($participant);
}
- protected function getLoggedInOrGuest(Controller $controller, bool $moderatorRequired): void {
+ /**
+ * @param AEnvironmentAwareController $controller
+ * @param bool $moderatorRequired
+ * @throws NotAModeratorException
+ */
+ protected function getLoggedInOrGuest(AEnvironmentAwareController $controller, bool $moderatorRequired): void {
$token = $this->request->getParam('token');
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
if ($this->userId !== null) {
@@ -119,6 +142,17 @@ class InjectionMiddleware extends Middleware {
$controller->setParticipant($participant);
}
+ /**
+ * @param AEnvironmentAwareController $controller
+ * @throws ReadOnlyException
+ */
+ protected function checkReadOnlyState(AEnvironmentAwareController $controller): void {
+ $room = $controller->getRoom();
+ if (!$room instanceof Room || $room->getReadOnly() === Room::READ_ONLY) {
+ throw new ReadOnlyException();
+ }
+ }
+
/**
* @param Controller $controller
* @param string $methodName
@@ -136,7 +170,8 @@ class InjectionMiddleware extends Middleware {
return new RedirectToDefaultAppResponse();
}
- if ($exception instanceof NotAModeratorException) {
+ if ($exception instanceof NotAModeratorException ||
+ $exception instanceof ReadOnlyException) {
if ($controller instanceof OCSController) {
throw new OCSException('', Http::STATUS_FORBIDDEN);
}
diff --git a/lib/Migration/Version5099Date20190319134820.php b/lib/Migration/Version5099Date20190319134820.php
new file mode 100644
index 0000000000..94428dcf5a
--- /dev/null
+++ b/lib/Migration/Version5099Date20190319134820.php
@@ -0,0 +1,58 @@
+
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Spreed\Migration;
+
+use Closure;
+use Doctrine\DBAL\Types\Type;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\SimpleMigrationStep;
+use OCP\Migration\IOutput;
+
+class Version5099Date20190319134820 extends SimpleMigrationStep {
+
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if ($schema->hasTable('talk_rooms')) {
+ $table = $schema->getTable('talk_rooms');
+
+ if (!$table->hasColumn('read_only')) {
+ $table->addColumn('read_only', Type::INTEGER, [
+ 'notnull' => true,
+ 'length' => 6,
+ 'default' => 0,
+ ]);
+ }
+ }
+
+ return $schema;
+ }
+
+}
diff --git a/lib/Room.php b/lib/Room.php
index 6d4d3ab723..cc8d1c04c5 100644
--- a/lib/Room.php
+++ b/lib/Room.php
@@ -45,6 +45,9 @@ class Room {
public const GROUP_CALL = 2;
public const PUBLIC_CALL = 3;
+ public const READ_WRITE = 0;
+ public const READ_ONLY = 1;
+
public const PARTICIPANT_REMOVED = 'remove';
public const PARTICIPANT_LEFT = 'leave';
@@ -65,6 +68,8 @@ class Room {
private $id;
/** @var int */
private $type;
+ /** @var int */
+ private $readOnly;
/** @var string */
private $token;
/** @var string */
@@ -97,6 +102,7 @@ class Room {
IHasher $hasher,
int $id,
int $type,
+ int $readOnly,
string $token,
string $name,
string $password,
@@ -114,6 +120,7 @@ class Room {
$this->hasher = $hasher;
$this->id = $id;
$this->type = $type;
+ $this->readOnly = $readOnly;
$this->token = $token;
$this->name = $name;
$this->password = $password;
@@ -133,6 +140,10 @@ class Room {
return $this->type;
}
+ public function getReadOnly(): int {
+ return $this->readOnly;
+ }
+
public function getToken(): string {
return $this->token;
}
diff --git a/tests/php/CapabilitiesTest.php b/tests/php/CapabilitiesTest.php
index 56bfc3b50f..1fe580d92d 100644
--- a/tests/php/CapabilitiesTest.php
+++ b/tests/php/CapabilitiesTest.php
@@ -78,6 +78,7 @@ class CapabilitiesTest extends TestCase {
'notification-levels',
'invite-groups-and-mails',
'locked-one-to-one-rooms',
+ 'read-only-rooms',
],
],
], $capabilities->getCapabilities());
@@ -119,6 +120,7 @@ class CapabilitiesTest extends TestCase {
'notification-levels',
'invite-groups-and-mails',
'locked-one-to-one-rooms',
+ 'read-only-rooms',
],
],
], $capabilities->getCapabilities());