feat(tests): Add integration test for file system tags cache bug

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2024-06-28 10:43:21 +02:00
Родитель 10b54a74dc
Коммит 5812ee2235
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F72FA5B49FFA96B0
4 изменённых файлов: 156 добавлений и 19 удалений

Просмотреть файл

@ -9,5 +9,7 @@ declare(strict_types=1);
return [
'ocs' => [
['name' => 'Endpoint#reset', 'url' => '', 'verb' => 'DELETE'],
['name' => 'Endpoint#prepare', 'url' => '', 'verb' => 'POST'],
['name' => 'Endpoint#tagFile', 'url' => '/tag-file', 'verb' => 'POST'],
],
];

Просмотреть файл

@ -10,14 +10,22 @@ namespace OCA\FilesAccessControlTesting\Controller;
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);
}
@ -32,6 +40,39 @@ class EndpointController extends OCSController {
$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();
}
}

Просмотреть файл

@ -42,6 +42,9 @@ class FeatureContext implements Context {
/** @var string */
protected $baseUrl;
protected string $tagId = '';
protected array $createdUsers = [];
/**
* FeatureContext constructor.
*/
@ -55,29 +58,45 @@ class FeatureContext implements Context {
* @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+)$/
*/
@ -89,6 +108,7 @@ class FeatureContext implements Context {
$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]);
}
@ -195,6 +215,26 @@ class FeatureContext implements Context {
];
$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;
}

Просмотреть файл

@ -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 |
@ -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"
@ -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 |