فهرست منبع

[doc2] Fix issue where a copy of a shared document in user home becomes unreachable

This takes care of an issue where a copy of a shared document ends up in the original owners home directory and becomes unreachable by the user making the copy. With this change these copied files are now put in the home directory of the user that makes the copy instead. If the file to be copied exists in a shared folder the copy will end up in that same shared folder, a user being able to copy such a document implies that the user is also able to browse that directory.
Johan Åhlén 1 سال پیش
والد
کامیت
a2c3090cba
2فایلهای تغییر یافته به همراه75 افزوده شده و 2 حذف شده
  1. 13 0
      desktop/core/src/desktop/models.py
  2. 62 2
      desktop/core/src/desktop/models_tests.py

+ 13 - 0
desktop/core/src/desktop/models.py

@@ -1276,13 +1276,26 @@ class Document2(models.Model):
     return (self.uuid, self.version, self.is_history)
 
   def copy(self, name, owner, description=None):
+    # TODO: Check why we choose to mutate the object (x in x.copy()).
+    # There's some code in api2.py that creates Workflow etc with the mutated reference after copy..
     copy_doc = self
+    source_owner = self.owner
+    target_directory = self.parent_directory
 
     copy_doc.pk = None
     copy_doc.id = None
     copy_doc.uuid = uuid_default()
     copy_doc.name = name
     copy_doc.owner = owner
+
+    # If this is a shared document with the user, and it resides in the owner's home directory, we have to put the
+    # copy in the user's home directory (as the user will not be able to browse the owner's home directory).
+    # Note that if the document to be copied resides in a shared directory (not home) the copy will end up in the same
+    # shared directory. Being able to copy it implies that the user can browse the parent directory.
+    if source_owner != owner and (target_directory is None or target_directory.is_home_directory):
+      user_home_directory = Document2.objects.get_home_directory(owner)
+      copy_doc.parent_directory = user_home_directory
+
     if description:
       copy_doc.description = description
     copy_doc.save()

+ 62 - 2
desktop/core/src/desktop/models_tests.py

@@ -123,13 +123,24 @@ class TestClusterConfig(object):
 @pytest.mark.django_db
 class TestDocument2(object):
   def setup_method(self):
-    self.client = make_logged_in_client(username="doc2", groupname="doc2", recreate=True, is_superuser=False)
+    self.default_group = get_default_user_group()
+
+    self.client = make_logged_in_client(username="doc2", groupname=self.default_group.name, recreate=True, is_superuser=False)
+    self.client_not_me = make_logged_in_client(username="not_doc2", groupname=self.default_group.name, recreate=True, is_superuser=False)
+
     self.user = User.objects.get(username="doc2")
+    self.user_not_me = User.objects.get(username="not_doc2")
 
-    # This creates the user directories for the new user
+    grant_access(self.user.username, self.user.username, "desktop")
+    grant_access(self.user_not_me.username, self.user_not_me.username, "desktop")
+
+    # This creates the user directories for the new users
     response = self.client.get('/desktop/api2/doc/')
     data = json.loads(response.content)
     assert '/' == data['document']['path'], data
+    response = self.client_not_me.get('/desktop/api2/doc/')
+    data = json.loads(response.content)
+    assert '/' == data['document']['path'], data
 
     self.home_dir = Document2.objects.get_home_directory(user=self.user)
 
@@ -292,6 +303,55 @@ class TestDocument2(object):
     assert copy_doc.uuid != workflow_doc.uuid
     assert copy_workflow.get_data()['workflow']['uuid'] != workflow.get_data()['workflow']['uuid']
 
+  def test_copy_of_shared_doc_in_home(self):
+    user_not_me_home_dir = Document2.objects.get_home_directory(user=self.user_not_me)
+
+    doc_to_copy = Document2.objects.create(
+      name='new_doc', type='query-hive', owner=self.user_not_me, data={}, parent_directory=user_not_me_home_dir
+    )
+    # "user_not_me" can view document
+    assert doc_to_copy.can_read(self.user_not_me)
+    # "user" cannot view document
+    assert not doc_to_copy.can_read(self.user)
+    # "user_not_me" shares with user
+    doc_to_copy.share(self.user_not_me, users=[self.user])
+    # "user" can view document
+    assert doc_to_copy.can_read(self.user)
+    # The doc resides in the home directory of "user_not_me"
+    assert doc_to_copy.parent_directory == user_not_me_home_dir
+
+    # "user" makes a copy of the doc owned by "user_not_me" which resides in the home directory of "user_not_me"
+    copied_doc = doc_to_copy.copy(name=doc_to_copy.name + '-copy', owner=self.user)
+
+    # The copy should be located in the home folder of "user"
+    user_home_dir = Document2.objects.get_home_directory(user=self.user)
+    assert user_home_dir != user_not_me_home_dir
+    assert copied_doc.parent_directory == user_home_dir
+
+  def test_copy_of_doc_in_shared_folder(self):
+    user_not_me_home_dir = Document2.objects.get_home_directory(user=self.user_not_me)
+    user_not_me_shared_dir = Directory.objects.create(name='test_dir', owner=self.user_not_me, parent_directory=user_not_me_home_dir)
+
+    doc_to_copy = Document2.objects.create(
+        name='new_doc', type='query-hive', owner=self.user_not_me, data={}, parent_directory=user_not_me_shared_dir
+    )
+    # "user_not_me" can view document
+    assert doc_to_copy.can_read(self.user_not_me)
+    # "user" cannot view document
+    assert not doc_to_copy.can_read(self.user)
+    # "user_not_me" shares the parent directory with user
+    user_not_me_shared_dir.share(self.user_not_me, users=[self.user])
+    # "user" can view document
+    assert doc_to_copy.can_read(self.user)
+    # The doc resides in the shared directory of "user_not_me"
+    assert doc_to_copy.parent_directory == user_not_me_shared_dir
+
+    # "user" makes a copy of the doc owned by "user_not_me" which resides in the shared directory of "user_not_me"
+    copied_doc = doc_to_copy.copy(name=doc_to_copy.name + '-copy', owner=self.user)
+
+    # The copy should be located in the shared directory of "user_not_me"
+    assert copied_doc.parent_directory == user_not_me_shared_dir
+
   def test_directory_move(self):
     source_dir = Directory.objects.create(name='test_mv', owner=self.user, parent_directory=self.home_dir)
     target_dir = Directory.objects.create(name='test_mv_dst', owner=self.user, parent_directory=self.home_dir)