From 86859a0794c0ab3846e7102d5676b94dd3d6706a Mon Sep 17 00:00:00 2001
From: Stefan Hynek <stefan.hynek@uni-goettingen.de>
Date: Thu, 21 Oct 2021 09:59:27 +0200
Subject: [PATCH] feat: implement basic textgrid DomainController and
 DAVProvider

allow authentication with username only; deliver a RootCollection built from textgrid projects
---
 src/repdav/textgrid_dav_provider.py      | 90 ++++++++++++++++++++++++
 src/repdav/textgrid_domain_controller.py | 36 ++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 src/repdav/textgrid_dav_provider.py
 create mode 100644 src/repdav/textgrid_domain_controller.py

diff --git a/src/repdav/textgrid_dav_provider.py b/src/repdav/textgrid_dav_provider.py
new file mode 100644
index 0000000..893f2b3
--- /dev/null
+++ b/src/repdav/textgrid_dav_provider.py
@@ -0,0 +1,90 @@
+import logging
+
+from wsgidav.dav_provider import DAVCollection, DAVNonCollection, DAVProvider
+from wsgidav.util import join_uri
+
+from .tgapi import TextgridAuth
+
+_logger = logging.getLogger(__name__)
+
+
+class TextgridRootCollection(DAVCollection):
+    """top level collection that incorporates so called "projects"
+
+    this is implemented as READ-ONLY as project may not be created with webDAV
+    """
+
+    def __init__(self, environ):
+        DAVCollection.__init__(self, "/", environ)
+        self._sid = environ["wsgidav.auth.user_name"]
+        _logger.debug("MY SID: %s", self._sid)
+        self._tg_auth = TextgridAuth()
+        self._projects = tuple(self._tg_auth.assigned_projects(self._sid))
+        _logger.debug("MY PROJECTS: %s", self._projects)
+
+    def get_member_names(self):
+        _logger.debug("Called get_member_names(self).")
+        return self._projects
+
+    def get_member(self, name):
+        _logger.debug("Called get_member(self, name).")
+        if name in self._projects:
+            return TextgridCollection(join_uri(self.path, name), self.environ)
+        return None
+
+
+class TextgridCollection(DAVCollection):
+    def __init__(self, path, environ):
+        DAVCollection.__init__(self, path, environ)
+
+    def create_empty_resource(self, name):
+        pass
+
+    def create_collection(self, name):
+        pass
+
+    def get_member_names(self):
+        pass
+
+    def delete(self):
+        pass
+
+    def copy_move_single(self, dest_path, is_move):
+        pass
+
+
+class TextgridResource(DAVNonCollection):
+    def __init__(self, path, environ):
+        DAVNonCollection.__init__(self, path, environ)
+
+    def get_content_length(self):
+        pass
+
+    def get_content_type(self):
+        pass
+
+    def get_content(self):
+        pass
+
+    def begin_write(self, content_type=None):
+        pass
+
+
+# ============================================================================
+# TextgridResourceProvider
+# ============================================================================
+class TextgridResourceProvider(DAVProvider):
+    """
+    DAV provider that serves Textgrid resources
+    """
+
+    def __init__(self):
+        super(TextgridResourceProvider, self).__init__()
+
+    def get_resource_inst(self, path, environ):
+        _logger.debug("PATH: %s", path)
+        _logger.debug("ENVIRON: %s", environ)
+        self._count_get_resource_inst += 1
+        root = TextgridRootCollection(environ)
+        # an instance of _DAVResource (i.e. either DAVCollection or DAVNonCollection)
+        return root.resolve("", path)
diff --git a/src/repdav/textgrid_domain_controller.py b/src/repdav/textgrid_domain_controller.py
new file mode 100644
index 0000000..382a669
--- /dev/null
+++ b/src/repdav/textgrid_domain_controller.py
@@ -0,0 +1,36 @@
+import logging
+from wsgidav.dc.base_dc import BaseDomainController
+# see https://github.com/mar10/wsgidav/blob/master/wsgidav/dc/base_dc.py
+# for the implementation of the BaseDomainController
+
+_logger = logging.getLogger(__name__)
+
+
+# see https://github.com/mar10/wsgidav/blob/master/wsgidav/dc/simple_dc.py
+# for the implementation of the SimpleDomainController
+class TextgridDC(BaseDomainController):
+    def __init__(self, wsgidav_app, config):
+        super(TextgridDC, self).__init__(wsgidav_app, config)
+        return
+
+    def __str__(self):
+        return "{}()".format(self.__class__.__name__)
+
+    def get_domain_realm(self, path_info, environ):
+        """Resolve a relative url to the appropriate realm name."""
+        realm = self._calc_realm_from_path_provider(path_info, environ)
+        _logger.debug("REALM: %s", realm)
+        return realm
+
+    def require_authentication(self, realm, environ):
+        """Authentication with a valid session ID as the username is required."""
+        return True
+
+    def basic_auth_user(self, realm, user_name, password, environ):
+        """Authentication will always be granted in the first place because sid
+        validation is an "expensive" request.
+        """
+        return True
+
+    def supports_http_digest_auth(self):
+        return False
-- 
GitLab