From dbfccd6485f1956803006a12ccae584d4dfca766 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 7 Aug 2024 13:31:30 +0200 Subject: [PATCH] feat: emit audit log events for changes to groupfolders Signed-off-by: Robin Appelman --- lib/DAV/ACLPlugin.php | 32 +++++++++++++++++++++--------- lib/Folder/FolderManager.php | 26 +++++++++++++++++++++++- tests/Folder/FolderManagerTest.php | 6 +++++- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/lib/DAV/ACLPlugin.php b/lib/DAV/ACLPlugin.php index 2d99f714c..e29aa4bc4 100644 --- a/lib/DAV/ACLPlugin.php +++ b/lib/DAV/ACLPlugin.php @@ -29,8 +29,10 @@ use OCA\GroupFolders\Folder\FolderManager; use OCA\GroupFolders\Mount\GroupMountPoint; use OCP\Constants; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IUser; use OCP\IUserSession; +use OCP\Log\Audit\CriticalActionPerformedEvent; use Sabre\DAV\INode; use Sabre\DAV\PropFind; use Sabre\DAV\PropPatch; @@ -46,19 +48,14 @@ class ACLPlugin extends ServerPlugin { public const GROUP_FOLDER_ID = '{http://nextcloud.org/ns}group-folder-id'; private ?Server $server = null; - private RuleManager $ruleManager; - private FolderManager $folderManager; - private IUserSession $userSession; private ?IUser $user = null; public function __construct( - RuleManager $ruleManager, - IUserSession $userSession, - FolderManager $folderManager + private RuleManager $ruleManager, + private IUserSession $userSession, + private FolderManager $folderManager, + private IEventDispatcher $eventDispatcher, ) { - $this->ruleManager = $ruleManager; - $this->userSession = $userSession; - $this->folderManager = $folderManager; } private function isAdmin(string $path): bool { @@ -211,6 +208,23 @@ public function propPatch(string $path, PropPatch $propPatch): void { ); }, $rawRules); + $formattedRules = array_map(function (Rule $rule) { + return $rule->getUserMapping()->getType() . ' ' . $rule->getUserMapping()->getDisplayName() . ': ' . $rule->formatPermissions(); + }, $rules); + if (count($formattedRules)) { + $formattedRules = implode(', ', $formattedRules); + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The advanced permissions for "%s" in groupfolder with id %d was set to "%s"', [ + $fileInfo->getInternalPath(), + $mount->getFolderId(), + $formattedRules, + ])); + } else { + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The advanced permissions for "%s" in groupfolder with id %d was cleared', [ + $fileInfo->getInternalPath(), + $mount->getFolderId(), + ])); + } + $existingRules = array_reduce( $this->ruleManager->getAllRulesForPaths($mount->getNumericStorageId(), [$path]), function (array $rules, array $rulesForPath) { diff --git a/lib/Folder/FolderManager.php b/lib/Folder/FolderManager.php index 4f828d411..3f48cd6cf 100644 --- a/lib/Folder/FolderManager.php +++ b/lib/Folder/FolderManager.php @@ -32,6 +32,7 @@ use OCP\Constants; use OCP\DB\Exception; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICacheEntry; use OCP\Files\IMimeTypeLoader; use OCP\Files\IRootFolder; @@ -39,6 +40,7 @@ use OCP\IGroupManager; use OCP\IUser; use OCP\IUserManager; +use OCP\Log\Audit\CriticalActionPerformedEvent; use OCP\Server; use Psr\Container\ContainerExceptionInterface; use Psr\Log\LoggerInterface; @@ -51,7 +53,8 @@ public function __construct( private IDBConnection $connection, private IGroupManager $groupManager, private IMimeTypeLoader $mimeTypeLoader, - private LoggerInterface $logger + private LoggerInterface $logger, + private IEventDispatcher $eventDispatcher, ) { } @@ -674,6 +677,9 @@ public function createFolder(string $mountPoint): int { 'mount_point' => $query->createNamedParameter($mountPoint) ]); $query->executeStatement(); + $id = $query->getLastInsertId(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new groupfolder "%s" was created with id %d', [$mountPoint, $id])); return $query->getLastInsertId(); } @@ -697,6 +703,8 @@ public function addApplicableGroup(int $folderId, string $groupId): void { 'permissions' => $query->createNamedParameter(Constants::PERMISSION_ALL) ]); $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The group "%s" was given access to the groupfolder with id %d', [$groupId, $folderId])); } /** @@ -718,6 +726,8 @@ public function removeApplicableGroup(int $folderId, string $groupId): void { ) ); $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The group "%s" was revoked access to the groupfolder with id %d', [$groupId, $folderId])); } @@ -742,6 +752,8 @@ public function setGroupPermissions(int $folderId, string $groupId, int $permiss ); $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The permissions of group "%s" to the groupfolder with id %d was set to %d', [$groupId, $folderId, $permissions])); } /** @@ -763,6 +775,9 @@ public function setManageACL(int $folderId, string $type, string $id, bool $mana ->andWhere($query->expr()->eq('mapping_id', $query->createNamedParameter($id))); } $query->executeStatement(); + + $action = $manageAcl ? "given" : "revoked"; + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The %s "%s" was %s acl management rights to the groupfolder with id %d', [$type, $id, $action, $folderId])); } /** @@ -774,6 +789,8 @@ public function removeFolder(int $folderId): void { $query->delete('group_folders') ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT))); $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The groupfolder with id %d was removed', [$folderId])); } /** @@ -786,6 +803,8 @@ public function setFolderQuota(int $folderId, int $quota): void { ->set('quota', $query->createNamedParameter($quota)) ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId))); $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The quote for groupfolder with id %d was set to %d bytes', [$folderId, $quota])); } /** @@ -798,6 +817,8 @@ public function renameFolder(int $folderId, string $newMountPoint): void { ->set('mount_point', $query->createNamedParameter($newMountPoint)) ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId, IQueryBuilder::PARAM_INT))); $query->executeStatement(); + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('The groupfolder with id %d was renamed to "%s"', [$folderId, $newMountPoint])); } /** @@ -858,6 +879,9 @@ public function setFolderACL(int $folderId, bool $acl): void { ->where($query->expr()->eq('folder_id', $query->createNamedParameter($folderId))); $query->executeStatement(); } + + $action = $acl ? "enabled" : "disabled"; + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('Advanced permissions for the groupfolder with id %d was %s', [$folderId, $action])); } /** diff --git a/tests/Folder/FolderManagerTest.php b/tests/Folder/FolderManagerTest.php index 0b2a7d83e..e186635c7 100644 --- a/tests/Folder/FolderManagerTest.php +++ b/tests/Folder/FolderManagerTest.php @@ -23,6 +23,7 @@ use OCA\GroupFolders\Folder\FolderManager; use OCP\Constants; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IMimeTypeLoader; use OCP\IDBConnection; use OCP\IGroupManager; @@ -38,6 +39,7 @@ class FolderManagerTest extends TestCase { private IGroupManager $groupManager; private IMimeTypeLoader $mimeLoader; private LoggerInterface $logger; + private IEventDispatcher $eventDispatcher; protected function setUp(): void { parent::setUp(); @@ -45,11 +47,13 @@ protected function setUp(): void { $this->groupManager = $this->createMock(IGroupManager::class); $this->mimeLoader = $this->createMock(IMimeTypeLoader::class); $this->logger = $this->createMock(LoggerInterface::class); + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->manager = new FolderManager( \OC::$server->getDatabaseConnection(), $this->groupManager, $this->mimeLoader, - $this->logger + $this->logger, + $this->eventDispatcher, ); $this->clean(); }