Explorar o código

Merge pull request #1747 from pbiering/hook-ext-path-upload-file

Hook extension for path of uploaded file
Peter Bieringer hai 10 meses
pai
achega
c91b8e49d5
Modificáronse 5 ficheiros con 24 adicións e 8 borrados
  1. 1 0
      CHANGELOG.md
  2. 3 1
      DOCUMENTATION.md
  3. 5 2
      config
  4. 1 1
      radicale/app/put.py
  5. 14 4
      radicale/storage/multifilesystem/lock.py

+ 1 - 0
CHANGELOG.md

@@ -4,6 +4,7 @@
 
 * Fix: auth/htpasswd related to detection and use of bcrypt
 * Add: option [auth] ldap_ignore_attribute_create_modify_timestamp for support of Authentik LDAP server
+* Extend: [storage] hook supports now placeholder for "cwd" and "path" (and catches unsupported placeholders)
 
 ## 3.5.0
 

+ 3 - 1
DOCUMENTATION.md

@@ -1334,7 +1334,9 @@ Command that is run after changes to storage. Take a look at the
 Default:
 
 Supported placeholders:
- - `%(user)`: logged-in user
+ - `%(user)s`: logged-in user
+ - `%(cwd)s`: current working directory _(>= 3.5.1)_
+ - `%(path)s`: full path of item _(>= 3.5.1)_
 
 Command will be executed with base directory defined in `filesystem_folder` (see above)
 

+ 5 - 2
config

@@ -223,10 +223,13 @@
 
 # Command that is run after changes to storage, default is emtpy
 #  Supported placeholders:
-#   %(user): logged-in user
+#   %(user)s: logged-in user
+#   %(cwd)s : current working directory
+#   %(path)s: full path of item
 #  Command will be executed with base directory defined in filesystem_folder
 #  For "git" check DOCUMENTATION.md for bootstrap instructions
-# Example: git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
+# Example(test): echo \"user=%(user)s path=%(path)s cwd=%(cwd)s\"
+# Example(git): git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
 #hook =
 
 # Create predefined user collections

+ 1 - 1
radicale/app/put.py

@@ -165,7 +165,7 @@ class ApplicationPartPut(ApplicationBase):
              bool(rights.intersect(access.permissions, "Ww")),
              bool(rights.intersect(access.parent_permissions, "w")))
 
-        with self._storage.acquire_lock("w", user):
+        with self._storage.acquire_lock("w", user, path=path):
             item = next(iter(self._storage.discover(path)), None)
             parent_item = next(iter(
                 self._storage.discover(access.parent_path)), None)

+ 14 - 4
radicale/storage/multifilesystem/lock.py

@@ -1,7 +1,8 @@
 # This file is part of Radicale - CalDAV and CardDAV server
 # Copyright © 2014 Jean-Marc Martins
 # Copyright © 2012-2017 Guillaume Ayoub
-# Copyright © 2017-2019 Unrud <unrud@outlook.com>
+# Copyright © 2017-2022 Unrud <unrud@outlook.com>
+# Copyright © 2023-2025 Peter Bieringer <pb@bieringer.de>
 #
 # This library is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -58,7 +59,7 @@ class StoragePartLock(StorageBase):
         self._hook = configuration.get("storage", "hook")
 
     @types.contextmanager
-    def acquire_lock(self, mode: str, user: str = "") -> Iterator[None]:
+    def acquire_lock(self, mode: str, user: str = "", *args, **kwargs) -> Iterator[None]:
         with self._lock.acquire(mode):
             yield
             # execute hook
@@ -73,8 +74,17 @@ class StoragePartLock(StorageBase):
                 else:
                     # Process group is also used to identify child processes
                     preexec_fn = os.setpgrp
-                command = self._hook % {
-                    "user": shlex.quote(user or "Anonymous")}
+                # optional argument
+                path = kwargs.get('path', "")
+                try:
+                    command = self._hook % {
+                        "path": shlex.quote(self._get_collection_root_folder() + path),
+                        "cwd": shlex.quote(self._filesystem_folder),
+                        "user": shlex.quote(user or "Anonymous")}
+                except KeyError as e:
+                    logger.error("Storage hook contains not supported placeholder %s (skip execution of: %r)" % (e, self._hook))
+                    return
+
                 logger.debug("Executing storage hook: '%s'" % command)
                 try:
                     p = subprocess.Popen(