Skip to content

Commit

Permalink
Merge pull request #10606 from nextcloud/bugfix/10605/duplicate-note-…
Browse files Browse the repository at this point in the history
…to-self

fix(note-to-self): Prevent creating duplicate "Note to self" conversa…
  • Loading branch information
nickvergessen authored Oct 4, 2023
2 parents cae5ca3 + 3d4d473 commit c35b78d
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
4 changes: 4 additions & 0 deletions lib/Participant.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ public function hasModeratorPermissions(bool $guestModeratorAllowed = true): boo
}

public function canStartCall(IConfig $config): bool {
if ($this->room->getType() === Room::TYPE_NOTE_TO_SELF) {
return false;
}

$defaultStartCall = (int) $config->getAppValue('spreed', 'start_calls', (string) Room::START_CALL_EVERYONE);

if ($defaultStartCall === Room::START_CALL_NOONE) {
Expand Down
30 changes: 26 additions & 4 deletions lib/Service/NoteToSelfService.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
use OCP\IL10N;
use OCP\IUser;
use OCP\IUserManager;
use OCP\PreConditionNotMetException;
use OCP\Security\ISecureRandom;

class NoteToSelfService {
public function __construct(
Expand All @@ -40,6 +42,7 @@ public function __construct(
protected RoomService $roomService,
protected AvatarService $avatarService,
protected ParticipantService $participantService,
protected ISecureRandom $secureRandom,
protected IL10N $l,
) {
}
Expand All @@ -60,7 +63,7 @@ public function ensureNoteToSelfExistsForUser(string $userId): Room {
throw new \InvalidArgumentException('User not found');
}

return $this->createNoteToSelfConversation($currentUser);
return $this->createNoteToSelfConversation($currentUser, $noteToSelfId);
}

public function initialCreateNoteToSelfForUser(string $userId): void {
Expand All @@ -69,23 +72,42 @@ public function initialCreateNoteToSelfForUser(string $userId): void {
return;
}

// Prefixing with zz, so that casting to int does not give a random roomId for other requests
$randomLock = 'zz' . $this->secureRandom->generate(3);
$this->config->setUserValue($userId, 'spreed', 'note_to_self', $randomLock);

$currentUser = $this->userManager->get($userId);
if (!$currentUser instanceof IUser) {
throw new \InvalidArgumentException('User not found');
}

$this->createNoteToSelfConversation($currentUser);
$this->createNoteToSelfConversation($currentUser, $randomLock);
}

protected function createNoteToSelfConversation(IUser $user): Room {
protected function createNoteToSelfConversation(IUser $user, string|int $previousValue): Room {
$room = $this->roomService->createConversation(
Room::TYPE_NOTE_TO_SELF,
$this->l->t('Note to self'),
$user,
'note_to_self',
$user->getUID()
);
$this->config->setUserValue($user->getUID(), 'spreed', 'note_to_self', (string) $room->getId());

try {
$this->config->setUserValue($user->getUID(), 'spreed', 'note_to_self', (string) $room->getId(), (string) $previousValue);
} catch (PreConditionNotMetException $e) {
// This process didn't win the race for creating the conversation, so fetch the other one
$this->roomService->deleteRoom($room);

// This is a little trick to bypass local caching
$values = $this->config->getUserValueForUsers('spreed', 'note_to_self', [$user->getUID()]);
if (isset($values[$user->getUID()])) {
return $this->manager->getRoomById($values[$user->getUID()]);
}

// Failed to read parallel note-to-self creation
throw new RoomNotFoundException('Failed due to parallel requests');
}

$this->roomService->setDescription(
$room,
Expand Down
2 changes: 1 addition & 1 deletion lib/Service/RoomFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ public function formatRoomV4(
$roomData['canDeleteConversation'] = $room->getType() !== Room::TYPE_ONE_TO_ONE
&& $room->getType() !== Room::TYPE_ONE_TO_ONE_FORMER
&& $currentParticipant->hasModeratorPermissions(false);
$roomData['canLeaveConversation'] = true;
$roomData['canLeaveConversation'] = $room->getType() !== Room::TYPE_NOTE_TO_SELF;
$roomData['canEnableSIP'] =
$this->talkConfig->isSIPConfigured()
&& !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken())
Expand Down

0 comments on commit c35b78d

Please sign in to comment.