diff --git a/lib/ACL/RuleManager.php b/lib/ACL/RuleManager.php index 4e39239f4..ef1e91917 100644 --- a/lib/ACL/RuleManager.php +++ b/lib/ACL/RuleManager.php @@ -26,18 +26,20 @@ use OCA\GroupFolders\ACL\UserMapping\IUserMapping; use OCA\GroupFolders\ACL\UserMapping\IUserMappingManager; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; use OCP\IUser; +use OCP\Log\Audit\CriticalActionPerformedEvent; class RuleManager { - /** @var IDBConnection */ - private $connection; - /** @var IUserMappingManager */ - private $userMappingManager; + private IDBConnection $connection; + private IUserMappingManager $userMappingManager; + private IEventDispatcher $eventDispatcher; - public function __construct(IDBConnection $connection, IUserMappingManager $userMappingManager) { + public function __construct(IDBConnection $connection, IUserMappingManager $userMappingManager, IEventDispatcher $eventDispatcher) { $this->connection = $connection; $this->userMappingManager = $userMappingManager; + $this->eventDispatcher = $eventDispatcher; } private function createRule(array $data): ?Rule { @@ -293,6 +295,26 @@ public function saveRule(Rule $rule): void { ->andWhere($query->expr()->eq('mapping_type', $query->createNamedParameter($rule->getUserMapping()->getType()))) ->andWhere($query->expr()->eq('mapping_id', $query->createNamedParameter($rule->getUserMapping()->getId()))); $query->executeStatement(); + + if ($rule->getUserMapping()->getType() === 'user') { + $logMessage = 'The ACL rule was updated to permission "%s" and mask "%s" for file/folder with id "%s" for user "%s"'; + $params = [ + 'permissions' => $rule->getPermissions(), + 'mask' => $rule->getMask(), + 'fileId' => $rule->getFileId(), + 'user' => $rule->getUserMapping()->getDisplayName() . ' (' . $rule->getUserMapping()->getId() . ')', + ]; + } else { + $logMessage = 'The ACL rule was updated to permission "%s" and mask "%s" for file/folder with id "%s" for group "%s"'; + $params = [ + 'permissions' => $rule->getPermissions(), + 'mask' => $rule->getMask(), + 'fileId' => $rule->getFileId(), + 'user' => $rule->getUserMapping()->getDisplayName(), + ]; + } + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent($logMessage, $params)); } else { $query = $this->connection->getQueryBuilder(); $query->insert('group_folders_acl') @@ -304,6 +326,26 @@ public function saveRule(Rule $rule): void { 'permissions' => $query->createNamedParameter($rule->getPermissions(), IQueryBuilder::PARAM_INT) ]); $query->executeStatement(); + + if ($rule->getUserMapping()->getType() === 'user') { + $logMessage = 'A new ACL rule was created to permission "%s" and mask "%s" for file/folder with id "%s" for user "%s"'; + $params = [ + 'permissions' => $rule->getPermissions(), + 'mask' => $rule->getMask(), + 'fileId' => $rule->getFileId(), + 'user' => $rule->getUserMapping()->getDisplayName() . ' (' . $rule->getUserMapping()->getId() . ')', + ]; + } else { + $logMessage = 'A new ACL rule was created to permission "%s" and mask "%s" for file/folder with id "%s" for group "%s"'; + $params = [ + 'permissions' => $rule->getPermissions(), + 'mask' => $rule->getMask(), + 'fileId' => $rule->getFileId(), + 'group' => $rule->getUserMapping()->getDisplayName(), + ]; + } + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent($logMessage, $params)); } } @@ -314,5 +356,21 @@ public function deleteRule(Rule $rule): void { ->andWhere($query->expr()->eq('mapping_type', $query->createNamedParameter($rule->getUserMapping()->getType()))) ->andWhere($query->expr()->eq('mapping_id', $query->createNamedParameter($rule->getUserMapping()->getId()))); $query->executeStatement(); + + if ($rule->getUserMapping()->getType() === 'user') { + $logMessage = 'The ACL rule was deleted for file/folder with id: "%s" for the user "%s"'; + $params = [ + 'fileId' => $rule->getFileId(), + 'user' => $rule->getUserMapping()->getDisplayName() . ' (' . $rule->getUserMapping()->getId() . ')', + ]; + } else { + $logMessage = 'The ACL rule was deleted for file/folder with id: "%s" for the group "%s"'; + $params = [ + 'fileId' => $rule->getFileId(), + 'group' => $rule->getUserMapping()->getDisplayName(), + ]; + } + + $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent($logMessage, $params)); } } diff --git a/tests/ACL/RuleManagerTest.php b/tests/ACL/RuleManagerTest.php index 7f4d898d3..e86dd0c9f 100644 --- a/tests/ACL/RuleManagerTest.php +++ b/tests/ACL/RuleManagerTest.php @@ -28,6 +28,8 @@ use OCA\GroupFolders\ACL\RuleManager; use OCA\GroupFolders\ACL\UserMapping\IUserMappingManager; use OCA\GroupFolders\ACL\UserMapping\UserMapping; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Log\Audit\CriticalActionPerformedEvent; use OCP\IUser; use Test\TestCase; @@ -42,6 +44,9 @@ class RuleManagerTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject | IUser */ private $user; + /** @var \PHPUnit_Framework_MockObject_MockObject | IEventDispatcher */ + private $eventDispatcher; + protected function setUp(): void { parent::setUp(); @@ -53,18 +58,51 @@ protected function setUp(): void { $this->userMappingManager->expects($this->any()) ->method('mappingFromId') ->willReturnCallback(function ($type, $id) { - return new UserMapping($type, $id); + if ($type === 'user') { + return new UserMapping($type, $id, 'The User'); + } else { + return new UserMapping($type, $id); + } }); - $this->ruleManager = new RuleManager(\OC::$server->getDatabaseConnection(), $this->userMappingManager); + + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->ruleManager = new RuleManager(\OC::$server->getDatabaseConnection(), $this->userMappingManager, $this->eventDispatcher); } public function testGetSetRule() { - $mapping = new UserMapping('test', '1'); + $mapping = new UserMapping('user', '1', 'The User'); $this->userMappingManager->expects($this->any()) ->method('getMappingsForUser') ->with($this->user) ->willReturn([$mapping]); + $this->eventDispatcher->expects($this->any()) + ->method('dispatchTyped') + ->withConsecutive( + [$this->callback(function(CriticalActionPerformedEvent $event): bool { + return $event->getParameters() === [ + 'permissions' => 0b00001001, + 'mask' => 0b00001111, + 'fileId' => 10, + 'user' => 'The User (1)', + ]; + })], + [$this->callback(function(CriticalActionPerformedEvent $event): bool { + return $event->getParameters() === [ + 'permissions' => 0b00001000, + 'mask' => 0b00001111, + 'fileId' => 10, + 'user' => 'The User (1)', + ]; + })], + [$this->callback(function(CriticalActionPerformedEvent $event): bool { + return $event->getParameters() === [ + 'fileId' => 10, + 'user' => 'The User (1)', + ]; + })], + ); + $rule = new Rule($mapping, 10, 0b00001111, 0b00001001); $this->ruleManager->saveRule($rule); @@ -89,6 +127,9 @@ public function testGetMultiple() { ->with($this->user) ->willReturn([$mapping1, $mapping2]); + $this->eventDispatcher->expects($this->any()) + ->method('dispatchTyped'); + $rule1 = new Rule($mapping1, 10, 0b00001111, 0b00001001); $rule2 = new Rule($mapping2, 10, 0b00001111, 0b00001000); $rule3 = new Rule($mapping2, 11, 0b00001111, 0b00001000); @@ -121,6 +162,9 @@ public function testGetByPath() { ->with($this->user) ->willReturn([$mapping]); + $this->eventDispatcher->expects($this->any()) + ->method('dispatchTyped'); + $rule1 = new Rule($mapping, $id1, 0b00001111, 0b00001001); $rule2 = new Rule($mapping, $id2, 0b00001111, 0b00001000); $this->ruleManager->saveRule($rule1); @@ -160,6 +204,8 @@ public function testGetByPathMore() { $rule = new Rule($mapping, $id1, 0b00001111, 0b00001001); $this->ruleManager->saveRule($rule); + $this->eventDispatcher->expects($this->any()) + ->method('dispatchTyped'); $result = $this->ruleManager->getRulesForFilesByPath($this->user, $storageId, array_merge(['foo'], $paths));