Skip to content

Commit

Permalink
Merge pull request #707 from nextcloud/backport/705/stable25
Browse files Browse the repository at this point in the history
[stable25] fix: Check tag attribute
  • Loading branch information
blizzz authored Mar 23, 2023
2 parents 3d27fbe + 2500c8b commit f578002
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

## 1.15.3 – 2023-03-23
### Fixed
* Check tag attribute

## 1.15.2 – 2023-02-15
### Fixed
* [Allow selecting any tag when many exist (#684)](https://github.com/nextcloud/files_automatedtagging/pull/684)
Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The tags can later be used to control retention, file access, automatic script e
To define tags, administrators can create and manage a set of rule groups. Each rule group consists of one or more rules combined through operators. Rules can include criteria like file type, size, time and more. A request matches a group if all rules evaluate to true. On uploading a file all defined groups are evaluated and when matching, the given tags are assigned to the file.
</description>

<version>1.15.2</version>
<version>1.15.3</version>
<licence>agpl</licence>
<author>Joas Schilling</author>
<namespace>FilesAutomatedTagging</namespace>
Expand Down
37 changes: 31 additions & 6 deletions lib/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@
use OCP\Files\Node;
use OCP\Files\Storage\IStorage;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
Expand All @@ -54,6 +57,10 @@ class Operation implements ISpecificOperation, IComplexOperation {
private IMountManager $mountManager;
private IRootFolder $rootFolder;
private File $fileEntity;
/** @var IUserSession */
protected $userSession;
/** @var IGroupManager */
protected $groupManager;

public function __construct(
ISystemTagObjectMapper $objectMapper,
Expand All @@ -64,7 +71,9 @@ public function __construct(
IURLGenerator $urlGenerator,
IMountManager $mountManager,
IRootFolder $rootFolder,
File $fileEntity
File $fileEntity,
IUserSession $userSession,
IGroupManager $groupManager
) {
$this->objectMapper = $objectMapper;
$this->tagManager = $tagManager;
Expand All @@ -75,6 +84,8 @@ public function __construct(
$this->mountManager = $mountManager;
$this->rootFolder = $rootFolder;
$this->fileEntity = $fileEntity;
$this->userSession = $userSession;
$this->groupManager = $groupManager;
}

public function checkOperations(IStorage $storage, int $fileId, string $file): void {
Expand All @@ -100,16 +111,27 @@ public function checkOperations(IStorage $storage, int $fileId, string $file): v
*/
public function validateOperation(string $name, array $checks, string $operation): void {
if ($operation === '') {
throw new UnexpectedValueException($this->l->t('No tags given'));
throw new UnexpectedValueException($this->l->t('No tags given'), 1);
}

$systemTagIds = explode(',', $operation);
try {
$this->tagManager->getTagsByIds($systemTagIds);
$tags = $this->tagManager->getTagsByIds($systemTagIds);

$user = $this->userSession->getUser();
$isAdmin = $user instanceof IUser && $this->groupManager->isAdmin($user->getUID());

if (!$isAdmin) {
foreach ($tags as $tag) {
if (!$tag->isUserAssignable() || !$tag->isUserVisible()) {
throw new UnexpectedValueException($this->l->t('At least one of the given tags is invalid'), 4);
}
}
}
} catch (TagNotFoundException $e) {
throw new UnexpectedValueException($this->l->t('Tag(s) could not be found: %s', implode(', ', $e->getMissingTags())));
throw new UnexpectedValueException($this->l->t('At least one of the given tags is invalid'), 2);
} catch (InvalidArgumentException $e) {
throw new UnexpectedValueException($this->l->t('At least one of the given tags is invalid'));
throw new UnexpectedValueException($this->l->t('At least one of the given tags is invalid'), 3);
}
}

Expand Down Expand Up @@ -181,7 +203,10 @@ public function getIcon(): string {
}

public function isAvailableForScope(int $scope): bool {
return true;
return in_array($scope, [
IManager::SCOPE_ADMIN,
IManager::SCOPE_USER,
], true);
}

public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatcher): void {
Expand Down
86 changes: 85 additions & 1 deletion tests/OperationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Storage\IStorage;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
use OCP\WorkflowEngine\IManager;
use OCP\WorkflowEngine\IRuleMatcher;
use PHPUnit\Framework\MockObject\MockObject;
Expand All @@ -59,6 +64,10 @@ class OperationTest extends TestCase {
protected $ruleMatcher;
/** @var IMountManager|MockObject */
protected $mountManager;
/** @var IUserSession|MockObject */
protected $userSession;
/** @var IGroupManager|MockObject */
protected $groupManager;

protected function setUp(): void {
parent::setUp();
Expand All @@ -85,6 +94,8 @@ protected function setUp(): void {
$this->mountManager = $this->createMock(IMountManager::class);
$this->rootFolder = $this->createMock(IRootFolder::class);
$this->fileEntity = $this->createMock(\OCA\WorkflowEngine\Entity\File::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->groupManager = $this->createMock(IGroupManager::class);

$this->operation = new Operation(
$this->objectMapper,
Expand All @@ -95,7 +106,9 @@ protected function setUp(): void {
$this->urlGenerator,
$this->mountManager,
$this->rootFolder,
$this->fileEntity
$this->fileEntity,
$this->userSession,
$this->groupManager
);
}

Expand Down Expand Up @@ -161,6 +174,77 @@ public function testCheckOperations(IStorage $storage, $fileId, $file, array $ma
$this->operation->checkOperations($storage, $fileId, $file);
}

public function dataValidateOperation() {
$public = $this->createMock(ISystemTag::class);
$public->method('isUserVisible')
->willReturn(true);
$public->method('isUserAssignable')
->willReturn(true);
$restricted = $this->createMock(ISystemTag::class);
$restricted->method('isUserVisible')
->willReturn(true);
$restricted->method('isUserAssignable')
->willReturn(false);
$invisible = $this->createMock(ISystemTag::class);
$invisible->method('isUserVisible')
->willReturn(false);
$invisible->method('isUserAssignable')
->willReturn(false);

return [
['', null, false, 1],
['1', [$public], false, null],
['2,1', [$restricted, $public], false, 4],
['1,3', [$public, $invisible], false, 4],
['1', [$public], true, null],
['2,1', [$restricted, $public], true, null],
['1,3', [$public, $invisible], true, null],
['4', new TagNotFoundException(), false, 2],
['5', new \InvalidArgumentException(), false, 3],
];
}

/**
* @dataProvider dataValidateOperation
*
* @param string $operation
* @param ISystemTag[]|\Exception|null $tags
* @param bool $isAdmin
* @param int|null $exceptionCode
*/
public function testValidateOperation(string $operation, $tags, bool $isAdmin, ?int $exceptionCode) {
if ($tags === null) {
$this->tagManager->expects($this->never())
->method('getTagsByIds');
} elseif (is_array($tags)) {
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->willReturn($tags);
} else {
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->willThrowException($tags);
}

if ($isAdmin) {
$userId = 'admin';
$user = $this->createMock(IUser::class);
$user->method('getUID')
->willReturn($userId);
$this->userSession->method('getUser')
->willReturn($user);
$this->groupManager->method('isAdmin')
->with($userId)
->willReturn(true);
}

if ($exceptionCode !== null) {
$this->expectExceptionCode($exceptionCode);
}

$this->operation->validateOperation('', [], $operation);
}

public function taggingPathDataProvider() {
$homeId = 'home::alice';
$localId = 'local::/mnt/users/alice';
Expand Down

0 comments on commit f578002

Please sign in to comment.