Skip to content

Commit

Permalink
feat(conversation): Add option to allow deleting one-to-one conversat…
Browse files Browse the repository at this point in the history
…ions

Signed-off-by: Joas Schilling <[email protected]>
  • Loading branch information
nickvergessen committed Jan 8, 2025
1 parent 047c89d commit 00a8e4a
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand Down
13 changes: 9 additions & 4 deletions lib/Controller/ChatController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1185,10 +1185,15 @@ protected function validateMessageExists(int $messageId, bool $sync = false): vo
#[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);
}

Expand Down
13 changes: 11 additions & 2 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
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;
Expand Down Expand Up @@ -116,6 +117,7 @@ public function __construct(
protected ChecksumVerificationService $checksumVerificationService,
protected RoomFormatter $roomFormatter,
protected IConfig $config,
protected IAppConfig $appConfig,
protected Config $talkConfig,
protected ICloudIdManager $cloudIdManager,
protected IPhoneNumberUtil $phoneNumberUtil,
Expand Down Expand Up @@ -857,7 +859,8 @@ public function setDescription(string $description): DataResponse {
#[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);
}

Expand Down Expand Up @@ -1375,7 +1378,7 @@ protected function removeSelfFromRoomLogic(Room $room, Participant $participant)
}

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,
Expand All @@ -1386,6 +1389,12 @@ protected function removeSelfFromRoomLogic(Room $room, Participant $participant)
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);
Expand Down
9 changes: 9 additions & 0 deletions lib/Service/RoomFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -36,6 +37,7 @@
class RoomFormatter {
public function __construct(
protected Config $talkConfig,
protected IAppConfig $appConfig,
protected AvatarService $avatarService,
protected ParticipantService $participantService,
protected ChatManager $chatManager,
Expand Down Expand Up @@ -320,6 +322,13 @@ public function formatRoomV4(
&& $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())
Expand Down
10 changes: 10 additions & 0 deletions tests/integration/features/chat-1/delete.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 31 additions & 1 deletion tests/integration/features/conversation-3/one-to-one.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand All @@ -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)

0 comments on commit 00a8e4a

Please sign in to comment.