Skip to content

Commit 00a8e4a

Browse files
committed
feat(conversation): Add option to allow deleting one-to-one conversations
Signed-off-by: Joas Schilling <[email protected]>
1 parent 047c89d commit 00a8e4a

File tree

6 files changed

+71
-7
lines changed

6 files changed

+71
-7
lines changed

docs/settings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Legend:
112112
| `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" |
113113
| `conversations_files` | string<br>`1` or `0` | `1` | No | 🖌️ | Whether the files app integration is enabled allowing to start conversations in the right sidebar |
114114
| `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) |
115+
| `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 |
115116
| `enable_matterbridge` | string<br>`1` or `0` | `0` | No | 🖌️ | Whether the Matterbridge integration is enabled and can be configured |
116117
| `force_passwords` | string<br>`1` or `0` | `0` | No || Whether public chats are forced to use a password |
117118
| `inactivity_lock_after_days` | int | `0` | No | | A duration (in days) after which rooms are locked. Calculated from the last activity in the room. |

lib/Controller/ChatController.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,10 +1185,15 @@ protected function validateMessageExists(int $messageId, bool $sync = false): vo
11851185
#[RequireReadWriteConversation]
11861186
public function clearHistory(): DataResponse {
11871187
$attendee = $this->participant->getAttendee();
1188-
if (!$this->participant->hasModeratorPermissions(false)
1189-
|| $this->room->getType() === Room::TYPE_ONE_TO_ONE
1190-
|| $this->room->getType() === Room::TYPE_ONE_TO_ONE_FORMER) {
1191-
// Actor is not a moderator or not the owner of the message
1188+
if (!$this->participant->hasModeratorPermissions(false)) {
1189+
// Actor is not a moderator
1190+
return new DataResponse(null, Http::STATUS_FORBIDDEN);
1191+
}
1192+
1193+
if (!$this->appConfig->getAppValueBool('delete_one_to_one_conversations')
1194+
&& ($this->room->getType() === Room::TYPE_ONE_TO_ONE
1195+
|| $this->room->getType() === Room::TYPE_ONE_TO_ONE_FORMER)) {
1196+
// Not allowed to purge one-to-one conversations
11921197
return new DataResponse(null, Http::STATUS_FORBIDDEN);
11931198
}
11941199

lib/Controller/RoomController.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
use OCP\AppFramework\Http\Attribute\OpenAPI;
7171
use OCP\AppFramework\Http\Attribute\PublicPage;
7272
use OCP\AppFramework\Http\DataResponse;
73+
use OCP\AppFramework\Services\IAppConfig;
7374
use OCP\AppFramework\Utility\ITimeFactory;
7475
use OCP\EventDispatcher\IEventDispatcher;
7576
use OCP\Federation\ICloudIdManager;
@@ -116,6 +117,7 @@ public function __construct(
116117
protected ChecksumVerificationService $checksumVerificationService,
117118
protected RoomFormatter $roomFormatter,
118119
protected IConfig $config,
120+
protected IAppConfig $appConfig,
119121
protected Config $talkConfig,
120122
protected ICloudIdManager $cloudIdManager,
121123
protected IPhoneNumberUtil $phoneNumberUtil,
@@ -857,7 +859,8 @@ public function setDescription(string $description): DataResponse {
857859
#[PublicPage]
858860
#[RequireModeratorParticipant]
859861
public function deleteRoom(): DataResponse {
860-
if ($this->room->getType() === Room::TYPE_ONE_TO_ONE || $this->room->getType() === Room::TYPE_ONE_TO_ONE_FORMER) {
862+
if (!$this->appConfig->getAppValueBool('delete_one_to_one_conversations')
863+
&& in_array($this->room->getType(), [Room::TYPE_ONE_TO_ONE, Room::TYPE_ONE_TO_ONE_FORMER], true)) {
861864
return new DataResponse(null, Http::STATUS_BAD_REQUEST);
862865
}
863866

@@ -1375,7 +1378,7 @@ protected function removeSelfFromRoomLogic(Room $room, Participant $participant)
13751378
}
13761379

13771380
if ($room->getType() !== Room::TYPE_CHANGELOG &&
1378-
$room->getObjectType() !== 'file' &&
1381+
$room->getObjectType() !== Room::OBJECT_TYPE_FILE &&
13791382
$this->participantService->getNumberOfUsers($room) === 1 &&
13801383
\in_array($participant->getAttendee()->getParticipantType(), [
13811384
Participant::USER,
@@ -1386,6 +1389,12 @@ protected function removeSelfFromRoomLogic(Room $room, Participant $participant)
13861389
return new DataResponse(null);
13871390
}
13881391

1392+
if ($this->appConfig->getAppValueBool('delete_one_to_one_conversations')
1393+
&& in_array($this->room->getType(), [Room::TYPE_ONE_TO_ONE, Room::TYPE_ONE_TO_ONE_FORMER], true)) {
1394+
$this->roomService->deleteRoom($room);
1395+
return new DataResponse(null);
1396+
}
1397+
13891398
$currentUser = $this->userManager->get($this->userId);
13901399
if (!$currentUser instanceof IUser) {
13911400
return new DataResponse(['error' => 'participant'], Http::STATUS_NOT_FOUND);

lib/Service/RoomFormatter.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use OCA\Talk\Webinary;
2121
use OCP\App\IAppManager;
2222
use OCP\AppFramework\Db\DoesNotExistException;
23+
use OCP\AppFramework\Services\IAppConfig;
2324
use OCP\AppFramework\Utility\ITimeFactory;
2425
use OCP\Comments\IComment;
2526
use OCP\IConfig;
@@ -36,6 +37,7 @@
3637
class RoomFormatter {
3738
public function __construct(
3839
protected Config $talkConfig,
40+
protected IAppConfig $appConfig,
3941
protected AvatarService $avatarService,
4042
protected ParticipantService $participantService,
4143
protected ChatManager $chatManager,
@@ -320,6 +322,13 @@ public function formatRoomV4(
320322
&& $room->getType() !== Room::TYPE_ONE_TO_ONE_FORMER
321323
&& $currentParticipant->hasModeratorPermissions(false);
322324
$roomData['canLeaveConversation'] = $room->getType() !== Room::TYPE_NOTE_TO_SELF;
325+
326+
if ($this->appConfig->getAppValueBool('delete_one_to_one_conversations')
327+
&& in_array($room->getType(), [Room::TYPE_ONE_TO_ONE, Room::TYPE_ONE_TO_ONE_FORMER], true)) {
328+
$roomData['canDeleteConversation'] = true;
329+
$roomData['canLeaveConversation'] = false;
330+
}
331+
323332
$roomData['canEnableSIP'] =
324333
$this->talkConfig->isSIPConfigured()
325334
&& !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken())

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,13 @@ Feature: chat/delete
235235
Then user "participant2" sees the following system messages in room "room1" with 200 (v1)
236236
| room | actorType | actorId | actorDisplayName | systemMessage |
237237
| room1 | users | participant1 | participant1-displayname | history_cleared |
238+
239+
Scenario: Can delete chat history in one-to-one conversations when config is set
240+
Given user "participant1" creates room "room" with 201 (v4)
241+
| roomType | 1 |
242+
| invite | participant2 |
243+
And user "participant1" sends message "Message" to room "room" with 201
244+
Then user "participant1" deletes chat history for room "room" with 403
245+
When the following "spreed" app config is set
246+
| delete_one_to_one_conversations | 1 |
247+
Then user "participant1" deletes chat history for room "room" with 200

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ Feature: conversation-2/one-to-one
198198
| users | participant1 | 1 |
199199
| users | participant2 | 1 |
200200

201-
Scenario: Check share restrictions on one to one conversatio
201+
Scenario: Check share restrictions on one to one conversation
202202
Given the following "core" app config is set
203203
| shareapi_restrict_user_enumeration_full_match | no |
204204
| shareapi_allow_share_dialog_user_enumeration | yes |
@@ -207,3 +207,33 @@ Feature: conversation-2/one-to-one
207207
And user "participant1" creates room "room15" with 403 (v4)
208208
| roomType | 1 |
209209
| invite | participant2 |
210+
211+
Scenario: Remove self from one-to-one conversations when deletable config is set deletes it
212+
Given user "participant1" creates room "room" with 201 (v4)
213+
| roomType | 1 |
214+
| invite | participant2 |
215+
Then user "participant1" removes themselves from room "room" with 200 (v4)
216+
And user "participant1" is participant of the following rooms (v4)
217+
And user "participant2" is participant of the following rooms (v4)
218+
| id | type | participantType |
219+
| room | 1 | 1 |
220+
When user "participant1" creates room "room" with 200 (v4)
221+
| roomType | 1 |
222+
| invite | participant2 |
223+
And the following "spreed" app config is set
224+
| delete_one_to_one_conversations | 1 |
225+
Then user "participant1" removes themselves from room "room" with 200 (v4)
226+
And user "participant1" is participant of the following rooms (v4)
227+
And user "participant2" is participant of the following rooms (v4)
228+
229+
Scenario: Deleting one-to-one conversations is possible when deletable config is set
230+
Given user "participant1" creates room "room" with 201 (v4)
231+
| roomType | 1 |
232+
| invite | participant2 |
233+
And user "participant1" sends message "Message" to room "room" with 201
234+
Then user "participant1" deletes room "room" with 400 (v4)
235+
When the following "spreed" app config is set
236+
| delete_one_to_one_conversations | 1 |
237+
Then user "participant1" deletes room "room" with 200 (v4)
238+
And user "participant1" is participant of the following rooms (v4)
239+
And user "participant2" is participant of the following rooms (v4)

0 commit comments

Comments
 (0)