From 05f549c2c3626b33bc0feea72f47175dfa6bfc3e Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Fri, 12 Aug 2022 01:22:07 +0300 Subject: [PATCH] Fix checking for permission when package is uploaded by a collaborator with lower perms --- .../qfieldcloud/core/tests/test_packages.py | 56 +++++++++++++++++-- .../qfieldcloud/core/views/package_views.py | 9 ++- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/docker-app/qfieldcloud/core/tests/test_packages.py b/docker-app/qfieldcloud/core/tests/test_packages.py index eecdaf17f..26630effc 100644 --- a/docker-app/qfieldcloud/core/tests/test_packages.py +++ b/docker-app/qfieldcloud/core/tests/test_packages.py @@ -10,7 +10,14 @@ from django.utils import timezone from qfieldcloud.authentication.models import AuthToken from qfieldcloud.core.geodb_utils import delete_db_and_role -from qfieldcloud.core.models import Geodb, Job, Project, Secret, User +from qfieldcloud.core.models import ( + Geodb, + Job, + Project, + ProjectCollaborator, + Secret, + User, +) from rest_framework import status from rest_framework.test import APITransactionTestCase @@ -25,9 +32,6 @@ def setUp(self): # Create a user self.user1 = User.objects.create_user(username="user1", password="abc123") - - self.user2 = User.objects.create_user(username="user2", password="abc123") - self.token1 = AuthToken.objects.get_or_create(user=self.user1)[0] # Create a project @@ -120,9 +124,21 @@ def upload_files_and_check_package( tempdir: str = None, invalid_layers: List[str] = [], ): - self.client.credentials(HTTP_AUTHORIZATION=f"Token {token}") - self.upload_files(token, project, files) + self.check_package( + token, project, expected_files, job_create_error, tempdir, invalid_layers + ) + + def check_package( + self, + token: str, + project: Project, + expected_files: List[str], + job_create_error: Tuple[int, str] = None, + tempdir: str = None, + invalid_layers: List[str] = [], + ): + self.client.credentials(HTTP_AUTHORIZATION=f"Token {token}") before_started_ts = timezone.now() @@ -552,3 +568,31 @@ def test_filename_with_whitespace(self): "project_qfield.qgs", ], ) + + def test_collaborator_can_package(self): + self.upload_files( + token=self.token1, + project=self.project1, + files=[ + ("delta/nonspatial.csv", "nonspatial.csv"), + ("delta/testdata.gpkg", "testdata.gpkg"), + ("delta/points.geojson", "points.geojson"), + ("delta/polygons.geojson", "polygons.geojson"), + ("delta/project.qgs", "project.qgs"), + ], + ) + + for idx, role in enumerate(ProjectCollaborator.Roles): + reader = User.objects.create(username=f"user_with_role_{idx}") + ProjectCollaborator.objects.create( + collaborator=reader, project=self.project1, role=role + ) + + self.check_package( + token=AuthToken.objects.get_or_create(user=reader)[0], + project=self.project1, + expected_files=[ + "data.gpkg", + "project_qfield.qgs", + ], + ) diff --git a/docker-app/qfieldcloud/core/views/package_views.py b/docker-app/qfieldcloud/core/views/package_views.py index c2fdef034..f6079ba15 100644 --- a/docker-app/qfieldcloud/core/views/package_views.py +++ b/docker-app/qfieldcloud/core/views/package_views.py @@ -1,6 +1,8 @@ from django.core.exceptions import ObjectDoesNotExist from qfieldcloud.authentication.models import AuthToken -from qfieldcloud.core import exceptions, permissions_utils, utils +from qfieldcloud.core import exceptions +from qfieldcloud.core import permissions_utils as perms +from qfieldcloud.core import utils from qfieldcloud.core.models import PackageJob, Project from qfieldcloud.core.utils import ( check_s3_key, @@ -17,7 +19,7 @@ def has_permission(self, request, view): try: project_id = request.parser_context["kwargs"].get("project_id") project = Project.objects.get(pk=project_id) - return permissions_utils.can_access_project(request.user, project) + return perms.can_access_project(request.user, project) except ObjectDoesNotExist: return False @@ -31,7 +33,8 @@ def has_permission(self, request, view): project_id = request.parser_context["kwargs"].get("project_id") job_id = request.parser_context["kwargs"].get("job_id") project = Project.objects.get(pk=project_id) - if not permissions_utils.can_update_project(request.user, project): + + if not perms.can_retrieve_project(request.user, project): return False # Check if the package job exists and it is already started, but not finished yet.