Skip to content

Commit

Permalink
feat(tests): Add integration test for file system tags cache bug
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
nickvergessen authored and backportbot[bot] committed Oct 15, 2024
1 parent 5bc4454 commit 4f22083
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 19 deletions.
2 changes: 2 additions & 0 deletions tests/Integration/app/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
return [
'ocs' => [
['name' => 'Endpoint#reset', 'url' => '', 'verb' => 'DELETE'],
['name' => 'Endpoint#prepare', 'url' => '', 'verb' => 'POST'],
['name' => 'Endpoint#tagFile', 'url' => '/tag-file', 'verb' => 'POST'],
],
];
41 changes: 41 additions & 0 deletions tests/Integration/app/lib/Controller/EndpointController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@

use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\Files\IRootFolder;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;

class EndpointController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
protected IDBConnection $db,
protected ISystemTagManager $systemTagManager,
protected ISystemTagObjectMapper $systemTagObjectMapper,
protected IRootFolder $rootFolder,
protected string $userId,
) {
parent::__construct($appName, $request);
}
Expand All @@ -32,6 +40,39 @@ public function reset(): DataResponse {
$query->delete('flow_operations')->executeStatement();
$query->delete('flow_operations_scope')->executeStatement();


try {
$tag = $this->systemTagManager->getTag('files_accesscontrol_intergrationtest', true, true);
$this->systemTagManager->deleteTags([$tag->getId()]);
} catch (TagNotFoundException) {
}

return new DataResponse();
}

/**
* @return DataResponse
*/
public function prepare(): DataResponse {
try {
$tag = $this->systemTagManager->getTag('files_accesscontrol_intergrationtest', true, true);
} catch (TagNotFoundException) {
$tag = $this->systemTagManager->createTag('files_accesscontrol_intergrationtest', true, true);
}
return new DataResponse(['tagId' => $tag->getId()]);
}

/**
* @NoAdminRequired
* @return DataResponse
*/
public function tagFile(string $path): DataResponse {
$tag = $this->systemTagManager->getTag('files_accesscontrol_intergrationtest', true, true);

$userFolder = $this->rootFolder->getUserFolder($this->userId);
$node = $userFolder->get($path);
$this->systemTagObjectMapper->assignTags((string)$node->getId(), 'files', [$tag->getId()]);

return new DataResponse();
}
}
72 changes: 56 additions & 16 deletions tests/Integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class FeatureContext implements Context {
/** @var string */
protected $baseUrl;

protected string $tagId = '';
protected array $createdUsers = [];

/**
* FeatureContext constructor.
*/
Expand All @@ -55,29 +58,45 @@ public function __construct() {
* @AfterScenario
*/
public function cleanUpBetweenTests() {
// TODO: Remove all created tags?
$this->setCurrentUser('admin');
$this->sendingTo('DELETE', '/apps/files_accesscontrol_testing');
$this->assertStatusCode($this->response, 200);
}

try {
$this->userDeletesFile('test1', 'folder', '/subdir');
} catch (\Exception $e) {
}
try {
$this->userDeletesFile('test1', 'file', '/foobar.txt');
} catch (\Exception $e) {
}
try {
$this->userDeletesFile('test1', 'file', '/definitely.notexe');
} catch (\Exception $e) {
}
try {
$this->emptyTrashbin('test1');
} catch (\Exception $e) {
/**
* @AfterScenario
*/
public function tearDown() {
foreach ($this->createdUsers as $user) {
$this->deleteUser($user);
}
}

/**
* @Given /^Ensure tag exists$/
*/
public function createTag() {
$this->setCurrentUser('admin');
$this->sendingTo('POST', '/apps/files_accesscontrol_testing');
$this->assertStatusCode($this->response, 200);

$ocsData = json_decode($this->response->getBody()->getContents(), true, flags: JSON_THROW_ON_ERROR);
$data = $ocsData['ocs']['data'];
$this->tagId = $data['tagId'];
}

/**
* @Given /^user "([^"]*)" tags file "([^"]*)"$/
*/
public function tagFile(string $user, string $path) {
// TODO: Remove all created tags?
$this->setCurrentUser($user);
$this->sendingToWith('POST', '/apps/files_accesscontrol_testing/tag-file', [
'path' => $path,
]);
$this->assertStatusCode($this->response, 200);
}

/**
* @Given /^user "([^"]*)" creates (global|user) flow with (\d+)$/
*/
Expand All @@ -89,6 +108,7 @@ public function createFlow(string $user, string $scope, int $statusCode, TableNo
$checks = [];
foreach ($formData as $key => $value) {
if (strpos($key, 'checks-') === 0) {
$value = str_replace('{{{FILES_ACCESSCONTROL_INTEGRATIONTEST_TAGID}}}', $this->tagId, $value);
$checks[] = json_decode($value, true);
unset($formData[$key]);
}
Expand Down Expand Up @@ -195,6 +215,26 @@ private function createUser(string $user): void {
];
$client->get($userProvisioningUrl . '/' . $user, $options2);

$this->createdUsers[] = $user;
$this->currentUser = $previous_user;
}

private function deleteUser(string $user): void {
$previous_user = $this->currentUser;
$this->currentUser = 'admin';

$userProvisioningUrl = $this->baseUrl . 'ocs/v2.php/cloud/users/' . $user;
$client = new Client();
$options = [
'auth' => ['admin', 'admin'],
'headers' => [
'OCS-APIREQUEST' => 'true',
],
];
$client->delete($userProvisioningUrl, $options);

unset($this->createdUsers[$user]);

$this->currentUser = $previous_user;
}

Expand Down
60 changes: 57 additions & 3 deletions tests/Integration/features/sharing-user.feature
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Feature: Sharing user
When User "test2" deletes file "/subdir/foobar.txt"
Then The webdav response should have a status code "403"

Scenario: Upload and share a file that is allowed by mimetype exludes
Scenario: Upload and share a file that is allowed by mimetype excludes
And user "admin" creates global flow with 200
| name | Admin flow |
| class | OCA\FilesAccessControl\Operation |
Expand All @@ -102,7 +102,7 @@ Feature: Sharing user
And Downloading file "/nextcloud.pdf" as "test2"
And The webdav response should have a status code "200"

Scenario: Share a file that is allowed by mimetype exludes
Scenario: Share a file that is allowed by mimetype excludes
Given User "test1" uploads file "data/nextcloud.pdf" to "/nextcloud2.pdf"
And The webdav response should have a status code "201"
And user "test1" shares file "/nextcloud2.pdf" with user "test2"
Expand All @@ -117,4 +117,58 @@ Feature: Sharing user
| checks-0 | {"class":"OCA\\WorkflowEngine\\Check\\FileMimeType", "operator": "!is", "value": "httpd/directory"} |
| checks-1 | {"class":"OCA\\WorkflowEngine\\Check\\FileMimeType", "operator": "!is", "value": "application/pdf"} |
And Downloading file "/nextcloud2.pdf" as "test2"
And The webdav response should have a status code "200"
And The webdav response should have a status code "200"

Scenario: Jailed storage cache bug blocking first
Given Ensure tag exists
Given User "test1" uploads file "data/textfile.txt" to "/nextcloud2.txt"
And The webdav response should have a status code "201"
Given User "test1" uploads file "data/textfile.txt" to "/nextcloud3.txt"
And The webdav response should have a status code "201"
And user "test1" shares file "/nextcloud2.txt" with user "test2"
And Downloading file "/nextcloud2.txt" as "test2"
And The webdav response should have a status code "200"
And user "test1" shares file "/nextcloud3.txt" with user "test2"
And Downloading file "/nextcloud3.txt" as "test2"
And The webdav response should have a status code "200"
And user "test1" tags file "/nextcloud2.txt"
When user "admin" creates global flow with 200
| name | Admin flow |
| class | OCA\FilesAccessControl\Operation |
| entity | OCA\WorkflowEngine\Entity\File |
| events | [] |
| operation | deny |
| checks-0 | {"class":"OCA\\WorkflowEngine\\Check\\FileSystemTags", "operator": "is", "value": "{{{FILES_ACCESSCONTROL_INTEGRATIONTEST_TAGID}}}"} |
Then Downloading file "/nextcloud2.txt" as "test2"
And The webdav response should have a status code "404"
And Downloading file "/nextcloud3.txt" as "test2"
And The webdav response should have a status code "200"
And user "test2" should see following elements
| /nextcloud3.txt |

Scenario: Jailed storage cache bug blocking last
Given Ensure tag exists
Given User "test1" uploads file "data/textfile.txt" to "/nextcloud2.txt"
And The webdav response should have a status code "201"
Given User "test1" uploads file "data/textfile.txt" to "/nextcloud3.txt"
And The webdav response should have a status code "201"
And user "test1" shares file "/nextcloud2.txt" with user "test2"
And Downloading file "/nextcloud2.txt" as "test2"
And The webdav response should have a status code "200"
And user "test1" shares file "/nextcloud3.txt" with user "test2"
And Downloading file "/nextcloud3.txt" as "test2"
And The webdav response should have a status code "200"
And user "test1" tags file "/nextcloud3.txt"
When user "admin" creates global flow with 200
| name | Admin flow |
| class | OCA\FilesAccessControl\Operation |
| entity | OCA\WorkflowEngine\Entity\File |
| events | [] |
| operation | deny |
| checks-0 | {"class":"OCA\\WorkflowEngine\\Check\\FileSystemTags", "operator": "is", "value": "{{{FILES_ACCESSCONTROL_INTEGRATIONTEST_TAGID}}}"} |
Then Downloading file "/nextcloud2.txt" as "test2"
And The webdav response should have a status code "200"
And Downloading file "/nextcloud3.txt" as "test2"
And The webdav response should have a status code "404"
And user "test2" should see following elements
| /nextcloud2.txt |

0 comments on commit 4f22083

Please sign in to comment.