From 71b987da57de62f7cb4ffe47905965bcc4eb4ccf Mon Sep 17 00:00:00 2001
From: Houkime <>
Date: Mon, 17 Apr 2023 15:37:11 +0000
Subject: [PATCH] refactor(services): add folder owner derivation

---
 selfprivacy_api/services/service.py | 37 +++++++++++++++++++++++++----
 tests/test_services.py              | 20 ++++++++++++++++
 2 files changed, 53 insertions(+), 4 deletions(-)
 create mode 100644 tests/test_services.py

diff --git a/selfprivacy_api/services/service.py b/selfprivacy_api/services/service.py
index cc34aa2..1a1d56f 100644
--- a/selfprivacy_api/services/service.py
+++ b/selfprivacy_api/services/service.py
@@ -9,6 +9,7 @@ from selfprivacy_api.jobs import Job
 from selfprivacy_api.utils.block_devices import BlockDevice
 
 from selfprivacy_api.services.generic_size_counter import get_storage_usage
+from selfprivacy_api.services.owned_path import OwnedPath
 
 
 class ServiceStatus(Enum):
@@ -152,10 +153,29 @@ class Service(ABC):
     def get_drive() -> str:
         pass
 
-    @staticmethod
-    @abstractmethod
-    def get_folders() -> str:
-        pass
+    @classmethod
+    def get_folders(cls) -> str:
+        """
+        get a plain list of occupied directories
+        Default extracts info from overriden get_owned_folders()
+        """
+        if cls.get_owned_folders == Service.get_owned_folders:
+            raise NotImplementedError(
+                "you need to implement at least one of get_folders() or get_owned_folders()"
+            )
+        return [owned_folder.path for owned_folder in cls.get_owned_folders()]
+
+    @classmethod
+    def get_owned_folders(cls) -> str:
+        """
+        Get a list of occupied directories with ownership info
+        Default extracts info from overriden get_folders()
+        """
+        if cls.get_folders == Service.get_folders:
+            raise NotImplementedError(
+                "you need to implement at least one of get_folders() or get_owned_folders()"
+            )
+        return [cls.owned_path(path) for path in cls.get_folders()]
 
     @staticmethod
     def get_foldername(path: str) -> str:
@@ -165,6 +185,15 @@ class Service(ABC):
     def move_to_volume(self, volume: BlockDevice) -> Job:
         pass
 
+    @classmethod
+    def owned_path(cls, path: str):
+        """A default guess on folder ownership"""
+        return OwnedPath(
+            path=path,
+            owner=cls.get_user(),
+            group=cls.get_group(),
+        )
+
     def pre_backup(self):
         pass
 
diff --git a/tests/test_services.py b/tests/test_services.py
new file mode 100644
index 0000000..52164a9
--- /dev/null
+++ b/tests/test_services.py
@@ -0,0 +1,20 @@
+"""
+    Tests for generic service methods
+"""
+from pytest import raises
+
+from selfprivacy_api.services.test_service import DummyService
+from selfprivacy_api.services.service import Service
+
+
+def test_unimplemented_folders_raises():
+    with raises(NotImplementedError):
+        Service.get_folders()
+    with raises(NotImplementedError):
+        Service.get_owned_folders()
+
+    class OurDummy(DummyService, folders=["testydir", "dirtessimo"]):
+        pass
+
+    owned_folders = OurDummy.get_owned_folders()
+    assert owned_folders is not None