def test_project_rules(): anonymous = AnonymousUser() admin_collaborator = UserFactory() edit_collaborator = UserFactory() view_collaborator = UserFactory() public_project = ProjectFactory( admin_collaborators=[admin_collaborator], edit_collaborators=[edit_collaborator], collaborators=[view_collaborator], private=False, ) private_project = ProjectFactory( admin_collaborators=[admin_collaborator], edit_collaborators=[edit_collaborator], collaborators=[view_collaborator], private=True, ) for user, project, can_view, can_change in [ (anonymous, public_project, True, False), (anonymous, private_project, False, False), (admin_collaborator, public_project, True, True), (admin_collaborator, private_project, True, True), (edit_collaborator, public_project, True, False), (edit_collaborator, private_project, True, False), (view_collaborator, public_project, True, False), (view_collaborator, private_project, True, False), ]: assert user.has_perm("projects.view_project", project) is can_view assert user.has_perm("projects.change_project", project) is can_change assert user.has_perm("projects.delete_project", project) is can_change
def test_update_bulk(self, client, user, mocker): """Test replacing the document set in a project""" mock_solr_index = mocker.patch( "documentcloud.projects.views.solr_index") old_documents = DocumentFactory.create_batch(5, user=user) new_documents = old_documents[:2] + DocumentFactory.create_batch( 3, user=user) project = ProjectFactory(user=user, documents=old_documents) other_project = ProjectFactory(user=user, documents=old_documents) client.force_authenticate(user=user) response = client.put( f"/api/projects/{project.pk}/documents/", [{ "document": d.pk } for d in new_documents], format="json", ) assert response.status_code == status.HTTP_200_OK assert {d.pk for d in new_documents } == {d.pk for d in project.documents.all()} assert {d.pk for d in old_documents } == {d.pk for d in other_project.documents.all()} # check that the solr index was properly updated for all documents run_commit_hooks() calls = [] for update in old_documents[:2]: calls.append( mocker.call( update.pk, field_updates={ "projects": "set", "projects_edit_access": "set" }, )) for add in new_documents[2:]: calls.append( mocker.call( add.pk, field_updates={ "projects": "set", "projects_edit_access": "set" }, )) for delete in old_documents[2:]: calls.append( mocker.call( delete.pk, field_updates={ "projects": "set", "projects_edit_access": "set" }, )) mock_solr_index.delay.assert_has_calls(calls, any_order=True)
def test_destroy_bad_no_collaborator(self, client, user, document): """You cannot remove a document from a project you are not a collaborator on""" project = ProjectFactory(user=document.user, documents=[document]) client.force_authenticate(user=user) response = client.delete( f"/api/projects/{project.pk}/documents/{document.pk}/") assert response.status_code == status.HTTP_403_FORBIDDEN
def test_update_bad_user(self, client, user): """You may not change a user on a Collaboration""" project = ProjectFactory(collaborators=[user]) client.force_authenticate(user=project.user) response = client.patch(f"/api/projects/{project.pk}/users/{user.pk}/", {"email": "*****@*****.**"}) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_retrieve_bad(self, client): """Test retrieving a document from project""" document = DocumentFactory(access=Access.private) project = ProjectFactory(documents=[document]) response = client.get( f"/api/projects/{project.pk}/documents/{document.pk}/") assert response.status_code == status.HTTP_404_NOT_FOUND
def test_destroy_bad_admin(self, client): """You may not remove the last admin from a project""" project = ProjectFactory() client.force_authenticate(user=project.user) response = client.delete( f"/api/projects/{project.pk}/users/{project.user.pk}/") assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_update_bad_admin(self, client): """You may not remove admin permissions from the last admin""" project = ProjectFactory() client.force_authenticate(user=project.user) response = client.patch( f"/api/projects/{project.pk}/users/{project.user.pk}/", {"access": "edit"}) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_destroy(self, client, user): """Test removing a user from a project""" project = ProjectFactory(admin_collaborators=[user]) client.force_authenticate(user=project.user) response = client.delete( f"/api/projects/{project.pk}/users/{user.pk}/") assert response.status_code == status.HTTP_204_NO_CONTENT assert not project.collaborators.filter(pk=user.pk).exists()
def test_update_bad(self, client, user): """Test updating a project by a edit collaborator""" project = ProjectFactory(edit_collaborators=[user]) client.force_authenticate(user=user) title = "New Title" response = client.patch(f"/api/projects/{project.pk}/", {"title": title}) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_destroy(self, client, document): """Test removing a document from a project""" project = ProjectFactory(user=document.user, documents=[document]) client.force_authenticate(user=project.user) response = client.delete( f"/api/projects/{project.pk}/documents/{document.pk}/") assert response.status_code == status.HTTP_204_NO_CONTENT assert not project.documents.filter(pk=document.pk).exists()
def test_list(self, client): """List documents in a project""" size = 10 project = ProjectFactory(documents=DocumentFactory.create_batch(size)) response = client.get(f"/api/projects/{project.pk}/documents/") assert response.status_code == status.HTTP_200_OK response_json = json.loads(response.content) assert len(response_json["results"]) == size
def test_update_bad_no_collaborator(self, client, document): """You may not update a document in a project if you are not a collaborator""" project = ProjectFactory(documents=[document]) client.force_authenticate(user=document.user) response = client.patch( f"/api/projects/{project.pk}/documents/{document.pk}/", {"edit_access": True}, ) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_update_bad_edit_access(self, client, user, document): """You may not enable edit access in a project if you do not have edit access""" project = ProjectFactory(user=user, documents=[document]) client.force_authenticate(user=user) response = client.patch( f"/api/projects/{project.pk}/documents/{document.pk}/", {"edit_access": True}, ) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_destroy_edit_collaborator(self, client, user, document): """You can remove a document from a project you are an edit collaborator on""" project = ProjectFactory(user=document.user, documents=[document], edit_collaborators=[user]) client.force_authenticate(user=user) response = client.delete( f"/api/projects/{project.pk}/documents/{document.pk}/") assert response.status_code == status.HTTP_204_NO_CONTENT
def test_update(self, client, user): """Test updating a collaborator in a project""" project = ProjectFactory(collaborators=[user]) client.force_authenticate(user=project.user) response = client.patch(f"/api/projects/{project.pk}/users/{user.pk}/", {"access": "admin"}) assert response.status_code == status.HTTP_200_OK collaborator = project.collaboration_set.get(user=user) assert collaborator.access == CollaboratorAccess.admin
def test_destroy_bulk_bad(self, client, user): """Test removing a document from a project you do not have permission to""" documents = DocumentFactory.create_batch(3, user=user) project = ProjectFactory(documents=documents) client.force_authenticate(user=user) doc_ids = ",".join(str(d.pk) for d in documents) response = client.delete( f"/api/projects/{project.pk}/documents/?document_id__in={doc_ids}") assert response.status_code == status.HTTP_403_FORBIDDEN
def test_create_bad_view_collaborator(self, client, user, document): """You may not add a document to a project you are a view collaborator on""" project = ProjectFactory(collaborators=[user]) client.force_authenticate(user=user) response = client.post( f"/api/projects/{project.pk}/documents/", {"document": document.pk}, format="json", ) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_create_edit_collaborator(self, client, user, document): """You may add a document to a project you are an edit collaborator on""" project = ProjectFactory(edit_collaborators=[user]) client.force_authenticate(user=user) response = client.post( f"/api/projects/{project.pk}/documents/", {"document": document.pk}, format="json", ) assert response.status_code == status.HTTP_201_CREATED
def test_update_non_owner_admin(self, client, user): """Test updating a project by a non owner admin""" project = ProjectFactory(admin_collaborators=[user]) client.force_authenticate(user=user) title = "New Title" response = client.patch(f"/api/projects/{project.pk}/", {"title": title}) assert response.status_code == status.HTTP_200_OK project.refresh_from_db() assert project.title == title
def test_update_edit_collaborator(self, client, document): """You may update a document in a project if you are a edit collaborator""" project = ProjectFactory(documents=[document], edit_collaborators=[document.user]) client.force_authenticate(user=document.user) response = client.patch( f"/api/projects/{project.pk}/documents/{document.pk}/", {"edit_access": True}, ) assert response.status_code == status.HTTP_200_OK
def test_retrieve(self, client, user): """Test retrieving a user from project""" project = ProjectFactory(collaborators=[user]) client.force_authenticate(user=project.user) response = client.get(f"/api/projects/{project.pk}/users/{user.pk}/") assert response.status_code == status.HTTP_200_OK response_json = json.loads(response.content) collaboration = project.collaboration_set.get(user=user) serializer = CollaborationSerializer(collaboration) assert response_json == serializer.data
def test_create_bad_edit_collaborator(self, client, user): """You may not add a collaborator to a project you are just an edit collaborator on """ project = ProjectFactory(edit_collaborators=[user]) other_user = UserFactory() client.force_authenticate(user=user) response = client.post(f"/api/projects/{project.pk}/users/", {"email": other_user.email}) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_list(self, client): """List users in a project""" size = 10 project = ProjectFactory(collaborators=UserFactory.create_batch(size)) client.force_authenticate(user=project.user) response = client.get(f"/api/projects/{project.pk}/users/") assert response.status_code == status.HTTP_200_OK response_json = json.loads(response.content) # add one for the projects owner assert len(response_json["results"]) == size + 1
def test_destroy_bulk(self, client, user): """Test removing a document from a project""" documents = DocumentFactory.create_batch(3, user=user) project = ProjectFactory(user=user, documents=documents) client.force_authenticate(user=user) doc_ids = ",".join(str(d.pk) for d in documents[:2]) response = client.delete( f"/api/projects/{project.pk}/documents/?document_id__in={doc_ids}") assert response.status_code == status.HTTP_204_NO_CONTENT assert project.documents.count() == 1
def test_retrieve(self, client, document): """Test retrieving a document from project""" project = ProjectFactory(documents=[document]) response = client.get( f"/api/projects/{project.pk}/documents/{document.pk}/") assert response.status_code == status.HTTP_200_OK response_json = json.loads(response.content) projectmembership = project.projectmembership_set.get( document=document) serializer = ProjectMembershipSerializer(projectmembership) assert response_json == serializer.data
def test_update_bad_document(self, client): """You may not try to change the document ID""" documents = DocumentFactory.create_batch(2) project = ProjectFactory(user=documents[0].user, documents=[documents[0]]) client.force_authenticate(user=project.user) response = client.patch( f"/api/projects/{project.pk}/documents/{documents[0].pk}/", {"document": documents[1].pk}, ) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_list_bad(self, client): """List documents in a project including some you cannot view""" size = 10 documents = DocumentFactory.create_batch(size, access=Access.public) documents.extend( DocumentFactory.create_batch(size, access=Access.private)) project = ProjectFactory(documents=documents) response = client.get(f"/api/projects/{project.pk}/documents/") assert response.status_code == status.HTTP_200_OK response_json = json.loads(response.content) assert len(response_json["results"]) == size
def test_partial_update(self, client, document): """Test updating a document in a project""" project = ProjectFactory(user=document.user, documents=[document]) client.force_authenticate(user=project.user) response = client.patch( f"/api/projects/{project.pk}/documents/{document.pk}/", {"edit_access": True}, ) assert response.status_code == status.HTTP_200_OK projectmembership = project.projectmembership_set.get( document=document) assert projectmembership.edit_access
def test_list_permissions(self, client): """List users you can view""" # the current user, a user in the same organization, a user in the same # project, a user with a public document, a user with a private document users = UserFactory.create_batch(5) OrganizationFactory(members=users[:2]) ProjectFactory(user=users[0], collaborators=[users[2]]) DocumentFactory(user=users[3], access=Access.public) DocumentFactory(user=users[4], access=Access.private) client.force_authenticate(user=users[0]) response = client.get("/api/users/") assert response.status_code == status.HTTP_200_OK response_json = json.loads(response.content) # you can see all users except for the user with a private document assert len(response_json["results"]) == 4
def test_partial_update_bulk_bad_missing(self, client, user): """Test updating multiple documents in a project""" documents = DocumentFactory.create_batch(5, user=user) other_document = DocumentFactory(user=user) project = ProjectFactory(user=user, documents=documents) client.force_authenticate(user=user) response = client.patch( f"/api/projects/{project.pk}/documents/", [{ "document": other_document.pk, "edit_access": True }], format="json", ) assert response.status_code == status.HTTP_400_BAD_REQUEST