Browse Source

feat(conversation): Add option to allow deleting one-to-one conversations

Signed-off-by: Joas Schilling <coding@schilljs.com>
pull/14064/head
Joas Schilling 11 months ago
parent
commit
00a8e4a3f1
No known key found for this signature in database GPG Key ID: F72FA5B49FFA96B0
  1. 1
      docs/settings.md
  2. 13
      lib/Controller/ChatController.php
  3. 13
      lib/Controller/RoomController.php
  4. 9
      lib/Service/RoomFormatter.php
  5. 10
      tests/integration/features/chat-1/delete.feature
  6. 32
      tests/integration/features/conversation-3/one-to-one.feature

1
docs/settings.md

@ -112,6 +112,7 @@ Legend:
| `federation_only_trusted_servers` | string<br>`1` or `0` | `0` | Yes | | 🏗️ *Work in progress:* Whether federation should be limited to the list of "Trusted servers" |
| `conversations_files` | string<br>`1` or `0` | `1` | No | 🖌️ | Whether the files app integration is enabled allowing to start conversations in the right sidebar |
| `conversations_files_public_shares` | string<br>`1` or `0` | `1` | No | 🖌️ | Whether the public share integration is enabled allowing to start conversations in the right sidebar on the public share page (Requires `conversations_files` also to be enabled) |
| `delete_one_to_one_conversations` | string<br>`1` or `0` | `0` | No | ️ | Whether one-to-one conversations can be left by either participant or should be deleted when one participant leaves |
| `enable_matterbridge` | string<br>`1` or `0` | `0` | No | 🖌️ | Whether the Matterbridge integration is enabled and can be configured |
| `force_passwords` | string<br>`1` or `0` | `0` | No | ️ | Whether public chats are forced to use a password |
| `inactivity_lock_after_days` | int | `0` | No | | A duration (in days) after which rooms are locked. Calculated from the last activity in the room. |

13
lib/Controller/ChatController.php

@ -1185,10 +1185,15 @@ class ChatController extends AEnvironmentAwareOCSController {
#[RequireReadWriteConversation]
public function clearHistory(): DataResponse {
$attendee = $this->participant->getAttendee();
if (!$this->participant->hasModeratorPermissions(false)
|| $this->room->getType() === Room::TYPE_ONE_TO_ONE
|| $this->room->getType() === Room::TYPE_ONE_TO_ONE_FORMER) {
// Actor is not a moderator or not the owner of the message
if (!$this->participant->hasModeratorPermissions(false)) {
// Actor is not a moderator
return new DataResponse(null, Http::STATUS_FORBIDDEN);
}
if (!$this->appConfig->getAppValueBool('delete_one_to_one_conversations')
&& ($this->room->getType() === Room::TYPE_ONE_TO_ONE
|| $this->room->getType() === Room::TYPE_ONE_TO_ONE_FORMER)) {
// Not allowed to purge one-to-one conversations
return new DataResponse(null, Http::STATUS_FORBIDDEN);
}

13
lib/Controller/RoomController.php

@ -70,6 +70,7 @@ use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudIdManager;
@ -116,6 +117,7 @@ class RoomController extends AEnvironmentAwareOCSController {
protected ChecksumVerificationService $checksumVerificationService,
protected RoomFormatter $roomFormatter,
protected IConfig $config,
protected IAppConfig $appConfig,
protected Config $talkConfig,
protected ICloudIdManager $cloudIdManager,
protected IPhoneNumberUtil $phoneNumberUtil,
@ -857,7 +859,8 @@ class RoomController extends AEnvironmentAwareOCSController {
#[PublicPage]
#[RequireModeratorParticipant]
public function deleteRoom(): DataResponse {
if ($this->room->getType() === Room::TYPE_ONE_TO_ONE || $this->room->getType() === Room::TYPE_ONE_TO_ONE_FORMER) {
if (!$this->appConfig->getAppValueBool('delete_one_to_one_conversations')
&& in_array($this->room->getType(), [Room::TYPE_ONE_TO_ONE, Room::TYPE_ONE_TO_ONE_FORMER], true)) {
return new DataResponse(null, Http::STATUS_BAD_REQUEST);
}
@ -1375,7 +1378,7 @@ class RoomController extends AEnvironmentAwareOCSController {
}
if ($room->getType() !== Room::TYPE_CHANGELOG &&
$room->getObjectType() !== 'file' &&
$room->getObjectType() !== Room::OBJECT_TYPE_FILE &&
$this->participantService->getNumberOfUsers($room) === 1 &&
\in_array($participant->getAttendee()->getParticipantType(), [
Participant::USER,
@ -1386,6 +1389,12 @@ class RoomController extends AEnvironmentAwareOCSController {
return new DataResponse(null);
}
if ($this->appConfig->getAppValueBool('delete_one_to_one_conversations')
&& in_array($this->room->getType(), [Room::TYPE_ONE_TO_ONE, Room::TYPE_ONE_TO_ONE_FORMER], true)) {
$this->roomService->deleteRoom($room);
return new DataResponse(null);
}
$currentUser = $this->userManager->get($this->userId);
if (!$currentUser instanceof IUser) {
return new DataResponse(['error' => 'participant'], Http::STATUS_NOT_FOUND);

9
lib/Service/RoomFormatter.php

@ -20,6 +20,7 @@ use OCA\Talk\Room;
use OCA\Talk\Webinary;
use OCP\App\IAppManager;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
use OCP\IConfig;
@ -36,6 +37,7 @@ use OCP\UserStatus\IUserStatus;
class RoomFormatter {
public function __construct(
protected Config $talkConfig,
protected IAppConfig $appConfig,
protected AvatarService $avatarService,
protected ParticipantService $participantService,
protected ChatManager $chatManager,
@ -320,6 +322,13 @@ class RoomFormatter {
&& $room->getType() !== Room::TYPE_ONE_TO_ONE_FORMER
&& $currentParticipant->hasModeratorPermissions(false);
$roomData['canLeaveConversation'] = $room->getType() !== Room::TYPE_NOTE_TO_SELF;
if ($this->appConfig->getAppValueBool('delete_one_to_one_conversations')
&& in_array($room->getType(), [Room::TYPE_ONE_TO_ONE, Room::TYPE_ONE_TO_ONE_FORMER], true)) {
$roomData['canDeleteConversation'] = true;
$roomData['canLeaveConversation'] = false;
}
$roomData['canEnableSIP'] =
$this->talkConfig->isSIPConfigured()
&& !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken())

10
tests/integration/features/chat-1/delete.feature

@ -235,3 +235,13 @@ Feature: chat/delete
Then user "participant2" sees the following system messages in room "room1" with 200 (v1)
| room | actorType | actorId | actorDisplayName | systemMessage |
| room1 | users | participant1 | participant1-displayname | history_cleared |
Scenario: Can delete chat history in one-to-one conversations when config is set
Given user "participant1" creates room "room" with 201 (v4)
| roomType | 1 |
| invite | participant2 |
And user "participant1" sends message "Message" to room "room" with 201
Then user "participant1" deletes chat history for room "room" with 403
When the following "spreed" app config is set
| delete_one_to_one_conversations | 1 |
Then user "participant1" deletes chat history for room "room" with 200

32
tests/integration/features/conversation-3/one-to-one.feature

@ -198,7 +198,7 @@ Feature: conversation-2/one-to-one
| users | participant1 | 1 |
| users | participant2 | 1 |
Scenario: Check share restrictions on one to one conversatio
Scenario: Check share restrictions on one to one conversation
Given the following "core" app config is set
| shareapi_restrict_user_enumeration_full_match | no |
| shareapi_allow_share_dialog_user_enumeration | yes |
@ -207,3 +207,33 @@ Feature: conversation-2/one-to-one
And user "participant1" creates room "room15" with 403 (v4)
| roomType | 1 |
| invite | participant2 |
Scenario: Remove self from one-to-one conversations when deletable config is set deletes it
Given user "participant1" creates room "room" with 201 (v4)
| roomType | 1 |
| invite | participant2 |
Then user "participant1" removes themselves from room "room" with 200 (v4)
And user "participant1" is participant of the following rooms (v4)
And user "participant2" is participant of the following rooms (v4)
| id | type | participantType |
| room | 1 | 1 |
When user "participant1" creates room "room" with 200 (v4)
| roomType | 1 |
| invite | participant2 |
And the following "spreed" app config is set
| delete_one_to_one_conversations | 1 |
Then user "participant1" removes themselves from room "room" with 200 (v4)
And user "participant1" is participant of the following rooms (v4)
And user "participant2" is participant of the following rooms (v4)
Scenario: Deleting one-to-one conversations is possible when deletable config is set
Given user "participant1" creates room "room" with 201 (v4)
| roomType | 1 |
| invite | participant2 |
And user "participant1" sends message "Message" to room "room" with 201
Then user "participant1" deletes room "room" with 400 (v4)
When the following "spreed" app config is set
| delete_one_to_one_conversations | 1 |
Then user "participant1" deletes room "room" with 200 (v4)
And user "participant1" is participant of the following rooms (v4)
And user "participant2" is participant of the following rooms (v4)
Loading…
Cancel
Save