Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use OCA\Circles\Dashboard\TeamDashboardWidget;
use OCA\Circles\Events\AddingCircleMemberEvent;
use OCA\Circles\Events\CircleMemberAddedEvent;
use OCA\Circles\Events\CircleMemberRemovedEvent;
use OCA\Circles\Events\DestroyingCircleEvent;
use OCA\Circles\Events\Files\CreatingFileShareEvent;
use OCA\Circles\Events\Files\FileShareCreatedEvent;
Expand All @@ -26,6 +27,7 @@
use OCA\Circles\FileSharingTeamResourceProvider;
use OCA\Circles\Handlers\WebfingerHandler;
use OCA\Circles\Listeners\AccountUpdated;
use OCA\Circles\Listeners\CircleMemberRemoved;
use OCA\Circles\Listeners\Files\AddingMemberSendMail as ListenerFilesAddingMemberSendMail;
use OCA\Circles\Listeners\Files\CreatingShareSendMail as ListenerFilesCreatingShareSendMail;
use OCA\Circles\Listeners\Files\DestroyingCircle as ListenerFilesDestroyingCircle;
Expand Down Expand Up @@ -98,6 +100,9 @@ public function register(IRegistrationContext $context): void {
$context->registerEventListener(UserChangedEvent::class, AccountUpdated::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeleted::class);

// Circle Events
$context->registerEventListener(CircleMemberRemovedEvent::class, CircleMemberRemoved::class);

// Group Events
$context->registerEventListener(GroupCreatedEvent::class, GroupCreated::class);
$context->registerEventListener(GroupChangedEvent::class, GroupChanged::class);
Expand Down
78 changes: 78 additions & 0 deletions lib/Listeners/CircleMemberRemoved.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Circles\Listeners;

use Exception;
use OCA\Circles\Events\CircleMemberRemovedEvent;
use OCP\App\IAppManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\Config\IUserMountCache;
use OCP\IUserManager;
use OCP\Server;
use Psr\Log\LoggerInterface;
use Throwable;

/** @template-implements IEventListener<CircleMemberRemovedEvent> */
class CircleMemberRemoved implements IEventListener {
public function __construct(
private readonly IUserManager $userManager,
private readonly IAppManager $appManager,
private readonly IUserMountCache $userMountCache,
private readonly IMountProviderCollection $mountProviderCollection,
private readonly LoggerInterface $logger,
) {
}

public function handle(Event $event): void {
if (!($event instanceof CircleMemberRemovedEvent)) {
return;
}

$member = $event->getMember();
if ($member === null) {
return;
}

$user = $this->userManager->get($member->getUserId());
if ($user === null) {
return;
}

$circle = $event->getCircle();
if (!$this->circleHasAssociatedGroupFolder($circle->getSingleId())) {
return;
}

try {
// refresh list of mounts for user
$mounts = $this->mountProviderCollection->getMountsForUser($user);
$mounts[] = $this->mountProviderCollection->getHomeMountForUser($user);
$this->userMountCache->registerMounts($user, $mounts);
} catch (Exception $e) {
$this->logger->debug('Failed to refresh mounts for user ' . $user->getUID(), ['exception' => $e]);
}
}

private function circleHasAssociatedGroupFolder(string $circleId): bool {
if (!$this->appManager->isEnabledForUser('groupfolders')) {
return false;
}

try {
$folderManager = Server::get(\OCA\GroupFolders\Folder\FolderManager::class);
return $folderManager->hasFolderForCircle($circleId);
} catch (Throwable $e) {
$this->logger->debug('Failed to check if circle ' . $circleId . ' has an associated team folder', ['exception' => $e]);
return false;
}
}
}
62 changes: 59 additions & 3 deletions lib/Listeners/GroupMemberRemoved.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,85 @@

use Exception;
use OCA\Circles\Service\SyncService;
use OCP\App\IAppManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\Config\IUserMountCache;
use OCP\Group\Events\UserRemovedEvent;
use OCP\Server;
use Psr\Log\LoggerInterface;
use Throwable;

/** @template-implements IEventListener<UserRemovedEvent|Event> */
/** @template-implements IEventListener<UserRemovedEvent> */
class GroupMemberRemoved implements IEventListener {
/** @var SyncService */
private $syncService;

public function __construct(SyncService $syncService) {
/** @var IAppManager */
private $appManager;

/** @var IUserMountCache */
private $userMountCache;

/** @var IMountProviderCollection */
private $mountProviderCollection;

/** @var LoggerInterface */
private $logger;

public function __construct(
SyncService $syncService,
IAppManager $appManager,
IUserMountCache $userMountCache,
IMountProviderCollection $mountProviderCollection,
LoggerInterface $logger,
) {
$this->syncService = $syncService;
$this->appManager = $appManager;
$this->userMountCache = $userMountCache;
$this->mountProviderCollection = $mountProviderCollection;
$this->logger = $logger;
}

public function handle(Event $event): void {
if (!($event instanceof UserRemovedEvent)) {
return;
}

$group = $event->getGroup();
$user = $event->getUser();
$group = $event->getGroup();

try {
$this->syncService->groupMemberRemoved($group->getGID(), $user->getUID());
} catch (Exception $e) {
}

if (!$this->groupHasAssociatedGroupFolder($group->getGID())) {
return;
}

try {
// refresh list of mounts for user
$mounts = $this->mountProviderCollection->getMountsForUser($user);
$mounts[] = $this->mountProviderCollection->getHomeMountForUser($user);
$this->userMountCache->registerMounts($user, $mounts);
} catch (Exception $e) {
$this->logger->debug('Failed to refresh mounts for user ' . $user->getUID(), ['exception' => $e]);
}
}

private function groupHasAssociatedGroupFolder(string $groupId): bool {
if (!$this->appManager->isEnabledForUser('groupfolders')) {
return false;
}

try {
$folderManager = Server::get(\OCA\GroupFolders\Folder\FolderManager::class);
return $folderManager->hasFolderForGroup($groupId);
} catch (Throwable $e) {
$this->logger->debug('Failed to check if group ' . $groupId . ' has an associated team folder', ['exception' => $e]);
return false;
}
}
}
10 changes: 10 additions & 0 deletions tests/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -424,4 +424,14 @@
<code><![CDATA[$s[$e]]]></code>
</InvalidArrayOffset>
</file>
<file src="lib/Listeners/GroupMemberRemoved.php">
<UndefinedClass>
<code><![CDATA[\OCA\GroupFolders\Folder\FolderManager]]></code>
</UndefinedClass>
</file>
<file src="lib/Listeners/CircleMemberRemoved.php">
<UndefinedClass>
<code><![CDATA[\OCA\GroupFolders\Folder\FolderManager]]></code>
</UndefinedClass>
</file>
</files>
Loading