From d700ba095ba1e51e730fd19a9044c595a95c8b4d Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 30 Sep 2021 11:08:03 +0200 Subject: [PATCH] Documents: Fix student/admin access in course + add test --- .../Extension/CDocumentExtension.php | 5 +- tests/AbstractApiTest.php | 2 +- .../Repository/CDocumentRepositoryTest.php | 235 +++++++++++++++--- 3 files changed, 208 insertions(+), 34 deletions(-) diff --git a/src/CoreBundle/DataProvider/Extension/CDocumentExtension.php b/src/CoreBundle/DataProvider/Extension/CDocumentExtension.php index 1e3a8d7488..0edde3c571 100644 --- a/src/CoreBundle/DataProvider/Extension/CDocumentExtension.php +++ b/src/CoreBundle/DataProvider/Extension/CDocumentExtension.php @@ -79,14 +79,15 @@ final class CDocumentExtension implements QueryCollectionExtensionInterface //, ->innerJoin('node.resourceLinks', 'links') ; + // Do not show deleted resources. $queryBuilder ->andWhere('links.visibility != :visibilityDeleted') ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED) ; - $isAllowedToSeeDraft = $this->security->isGranted(['ROLE_ADMIN', 'ROLE_CURRENT_COURSE_TEACHER']); + $allowDraft = $this->security->isGranted('ROLE_ADMIN') || $this->security->isGranted('ROLE_CURRENT_COURSE_TEACHER'); - if ($isAllowedToSeeDraft) { + if (!$allowDraft) { $queryBuilder ->andWhere('links.visibility != :visibilityDraft') ->setParameter('visibilityDraft', ResourceLink::VISIBILITY_DRAFT) diff --git a/tests/AbstractApiTest.php b/tests/AbstractApiTest.php index 438325ce93..037f171360 100644 --- a/tests/AbstractApiTest.php +++ b/tests/AbstractApiTest.php @@ -50,7 +50,7 @@ abstract class AbstractApiTest extends ApiTestCase } /** - * Use credentials with token. + * Use credentials with token, by default it returns the admin token. */ protected function getUserToken($body = [], $cleanToken = false): string { diff --git a/tests/CourseBundle/Repository/CDocumentRepositoryTest.php b/tests/CourseBundle/Repository/CDocumentRepositoryTest.php index d3d04ae77d..cbbc1fb98e 100644 --- a/tests/CourseBundle/Repository/CDocumentRepositoryTest.php +++ b/tests/CourseBundle/Repository/CDocumentRepositoryTest.php @@ -96,13 +96,44 @@ class CDocumentRepositoryTest extends AbstractApiTest 'title' => $folderName, 'parentResourceNode' => $course->getResourceNode()->getId(), ]); + } + + public function testUpdateFolder(): void + { + $course = $this->createCourse('Test'); + $courseId = $course->getId(); + + // Create folder. + $resourceLinkList = [ + [ + 'cid' => $courseId, + 'visibility' => ResourceLink::VISIBILITY_PUBLISHED, + ], + ]; + + $folderName = 'folder1'; + $token = $this->getUserToken([]); + $response = $this->createClientWithCredentials($token)->request( + 'POST', + '/api/documents', + [ + 'json' => [ + 'title' => $folderName, + 'filetype' => 'folder', + 'parentResourceNodeId' => $course->getResourceNode()->getId(), + 'resourceLinkList' => $resourceLinkList, + ], + ] + ); + + $this->assertResponseIsSuccessful(); // Update. - $id = $response->toArray()['@id']; + $iri = $response->toArray()['@id']; $this->createClientWithCredentials($token)->request( 'PUT', - $id, + $iri, [ 'json' => [ 'title' => 'edited', @@ -117,14 +148,95 @@ class CDocumentRepositoryTest extends AbstractApiTest '@type' => 'Documents', 'title' => 'edited', ]); + } + + public function testDeleteFolder(): void + { + $course = $this->createCourse('Test'); + $courseId = $course->getId(); + + // Create folder. + $resourceLinkList = [ + [ + 'cid' => $courseId, + 'visibility' => ResourceLink::VISIBILITY_PUBLISHED, + ], + ]; + + $folderName = 'folder1'; + $token = $this->getUserToken([]); + $response = $this->createClientWithCredentials($token)->request( + 'POST', + '/api/documents', + [ + 'json' => [ + 'title' => $folderName, + 'filetype' => 'folder', + 'parentResourceNodeId' => $course->getResourceNode()->getId(), + 'resourceLinkList' => $resourceLinkList, + ], + ] + ); + + $this->assertResponseIsSuccessful(); + + $iri = $response->toArray()['@id']; + + $this->createClientWithCredentials($token)->request( + 'DELETE', + $iri + ); + + $this->assertResponseIsSuccessful(); + $this->assertResponseStatusCodeSame(204); + + $this->createClientWithCredentials($token)->request( + 'GET', + $iri, + [ + 'query' => [ + 'getFile' => true, + ], + ] + ); + $this->assertResponseStatusCodeSame(404); + } + + public function testAccessFolder(): void + { + $course = $this->createCourse('Test'); + $courseId = $course->getId(); + + // Create folder. + $resourceLinkList = [ + [ + 'cid' => $courseId, + 'visibility' => ResourceLink::VISIBILITY_PUBLISHED, + ], + ]; + + $folderName = 'folder1'; + $token = $this->getUserToken([]); + $response = $this->createClientWithCredentials($token)->request( + 'POST', + '/api/documents', + [ + 'json' => [ + 'title' => $folderName, + 'filetype' => 'folder', + 'parentResourceNodeId' => $course->getResourceNode()->getId(), + 'resourceLinkList' => $resourceLinkList, + ], + ] + ); + $this->assertResponseIsSuccessful(); // Test access. - $data = json_decode($response->getContent()); - $documentId = $data->iid; + $iri = $response->toArray()['@id']; $this->createClientWithCredentials($token)->request( 'GET', - '/api/documents/'.$documentId, + $iri, [ 'query' => [ 'getFile' => true, @@ -133,19 +245,57 @@ class CDocumentRepositoryTest extends AbstractApiTest ); $this->assertResponseIsSuccessful(); - $this->createUser('test'); + // Test as student. + $this->createUser('student'); - $testToken = $this->getUserToken( + $studentToken = $this->getUserToken( [ - 'username' => 'test', - 'password' => 'test', + 'username' => 'student', + 'password' => 'student', ], true ); - $this->createClientWithCredentials($testToken)->request( + $this->createClientWithCredentials($studentToken)->request( 'GET', - '/api/documents/'.$documentId, + $iri, + [ + 'query' => [ + 'cid' => 'abc', + 'sid' => 'abc', + 'gip' => 'abc', + ], + ] + ); + $this->assertResponseStatusCodeSame(403); + + $this->createClientWithCredentials($studentToken)->request( + 'GET', + $iri, + [ + 'query' => [ + 'cid' => $courseId, + ], + ] + ); + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@context' => '/api/contexts/Documents', + '@type' => 'Documents', + 'title' => 'folder1', + ]); + + $documentId = $response->toArray()['iid']; + + // Change visibility to draft. + $documentRepo = self::getContainer()->get(CDocumentRepository::class); + $document = $documentRepo->find($documentId); + $documentRepo->setVisibilityDraft($document); + + // Admin access. + $this->createClientWithCredentials($token)->request( + 'GET', + $iri, [ 'query' => [ 'cid' => $courseId, @@ -154,18 +304,41 @@ class CDocumentRepositoryTest extends AbstractApiTest ); $this->assertResponseIsSuccessful(); - $this->createClientWithCredentials($testToken)->request( + $response = $this->createClientWithCredentials($token)->request( 'GET', - '/api/documents/'.$documentId, + '/api/documents', [ 'query' => [ - 'cid' => 'abc', - 'sid' => 'abc', - 'gip' => 'abc', + 'cid' => $courseId, + 'resourceNode.parent' => $course->getResourceNode()->getId(), + ], + ] + ); + $this->assertCount(1, $response->toArray()['hydra:member']); + + // Student access. + $this->createClientWithCredentials($studentToken)->request( + 'GET', + $iri, + [ + 'query' => [ + 'cid' => $courseId, ], ] ); $this->assertResponseStatusCodeSame(403); + + $response = $this->createClientWithCredentials($studentToken)->request( + 'GET', + '/api/documents', + [ + 'query' => [ + 'cid' => $courseId, + 'resourceNode.parent' => $course->getResourceNode()->getId(), + ], + ] + ); + $this->assertCount(0, $response->toArray()['hydra:member']); } public function testUploadFile(): void @@ -688,9 +861,9 @@ class CDocumentRepositoryTest extends AbstractApiTest $this->assertInstanceOf(ResourceLink::class, $link); $this->assertSame($link->getVisibility(), ResourceLink::VISIBILITY_PUBLISHED); $this->assertSame($link->getCourse(), $course); - $this->assertSame($link->getGroup(), null); - $this->assertSame($link->getUser(), null); - $this->assertSame($link->getUserGroup(), null); + $this->assertNull($link->getGroup()); + $this->assertNull($link->getUser()); + $this->assertNull($link->getUserGroup()); $teacher = $this->createUser('teacher'); @@ -732,14 +905,14 @@ class CDocumentRepositoryTest extends AbstractApiTest $this->assertInstanceOf(ResourceLink::class, $secondLink); $this->assertSame($firstLink->getCourse(), $course); - $this->assertSame($firstLink->getGroup(), null); - $this->assertSame($firstLink->getSession(), null); - $this->assertSame($firstLink->getUser(), null); + $this->assertNull($firstLink->getGroup()); + $this->assertNull($firstLink->getSession()); + $this->assertNull($firstLink->getUser()); $this->assertSame($secondLink->getCourse(), $course); $this->assertSame($secondLink->getGroup(), $group); $this->assertSame($secondLink->getSession(), $session); - $this->assertSame($secondLink->getUser(), null); + $this->assertNull($secondLink->getUser()); $user = $this->createUser('test2'); $document->addResourceToUserList([$user]); @@ -769,8 +942,8 @@ class CDocumentRepositoryTest extends AbstractApiTest $fourthLink = $document->getResourceNode()->getResourceLinks()[3]; $this->assertInstanceOf(ResourceLink::class, $fourthLink); - $this->assertSame($fourthLink->getUser(), null); - $this->assertSame($fourthLink->getSession(), null); + $this->assertNull($fourthLink->getUser()); + $this->assertNull($fourthLink->getSession()); $this->assertSame($fourthLink->getGroup(), $group2); $this->assertTrue($document->isVisible($course)); @@ -783,21 +956,21 @@ class CDocumentRepositoryTest extends AbstractApiTest $usersAndGroups = $document->getUsersAndGroupSubscribedToResource(); $this->assertFalse($usersAndGroups['everyone']); - $this->assertSame(1, \count($usersAndGroups['users'])); - $this->assertSame(2, \count($usersAndGroups['groups'])); + $this->assertCount(1, $usersAndGroups['users']); + $this->assertCount(2, $usersAndGroups['groups']); } public function testSeparateUsersGroups(): void { $usersAndGroupsSeparated = CDocument::separateUsersGroups(['USER:1']); - $this->assertSame(1, \count($usersAndGroupsSeparated['users'])); - $this->assertSame(0, \count($usersAndGroupsSeparated['groups'])); + $this->assertCount(1, $usersAndGroupsSeparated['users']); + $this->assertCount(0, $usersAndGroupsSeparated['groups']); $usersAndGroupsSeparated = CDocument::separateUsersGroups(['USER:1', 'GROUP:1']); - $this->assertSame(1, \count($usersAndGroupsSeparated['users'])); - $this->assertSame(1, \count($usersAndGroupsSeparated['groups'])); + $this->assertCount(1, $usersAndGroupsSeparated['users']); + $this->assertCount(1, $usersAndGroupsSeparated['groups']); } public function testSetVisibility(): void