Skip to content

Commit c91b8e4

Browse files
authored
Merge pull request #1747 from pbiering/hook-ext-path-upload-file
Hook extension for path of uploaded file
2 parents 6b83c40 + 14fb509 commit c91b8e4

File tree

5 files changed

+24
-8
lines changed

5 files changed

+24
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* Fix: auth/htpasswd related to detection and use of bcrypt
66
* Add: option [auth] ldap_ignore_attribute_create_modify_timestamp for support of Authentik LDAP server
7+
* Extend: [storage] hook supports now placeholder for "cwd" and "path" (and catches unsupported placeholders)
78

89
## 3.5.0
910

DOCUMENTATION.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,9 @@ Command that is run after changes to storage. Take a look at the
13341334
Default:
13351335

13361336
Supported placeholders:
1337-
- `%(user)`: logged-in user
1337+
- `%(user)s`: logged-in user
1338+
- `%(cwd)s`: current working directory _(>= 3.5.1)_
1339+
- `%(path)s`: full path of item _(>= 3.5.1)_
13381340

13391341
Command will be executed with base directory defined in `filesystem_folder` (see above)
13401342

config

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,13 @@
223223

224224
# Command that is run after changes to storage, default is emtpy
225225
# Supported placeholders:
226-
# %(user): logged-in user
226+
# %(user)s: logged-in user
227+
# %(cwd)s : current working directory
228+
# %(path)s: full path of item
227229
# Command will be executed with base directory defined in filesystem_folder
228230
# For "git" check DOCUMENTATION.md for bootstrap instructions
229-
# Example: git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
231+
# Example(test): echo \"user=%(user)s path=%(path)s cwd=%(cwd)s\"
232+
# Example(git): git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
230233
#hook =
231234

232235
# Create predefined user collections

radicale/app/put.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def do_PUT(self, environ: types.WSGIEnviron, base_prefix: str,
165165
bool(rights.intersect(access.permissions, "Ww")),
166166
bool(rights.intersect(access.parent_permissions, "w")))
167167

168-
with self._storage.acquire_lock("w", user):
168+
with self._storage.acquire_lock("w", user, path=path):
169169
item = next(iter(self._storage.discover(path)), None)
170170
parent_item = next(iter(
171171
self._storage.discover(access.parent_path)), None)

radicale/storage/multifilesystem/lock.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# This file is part of Radicale - CalDAV and CardDAV server
22
# Copyright © 2014 Jean-Marc Martins
33
# Copyright © 2012-2017 Guillaume Ayoub
4-
# Copyright © 2017-2019 Unrud <unrud@outlook.com>
4+
# Copyright © 2017-2022 Unrud <unrud@outlook.com>
5+
# Copyright © 2023-2025 Peter Bieringer <pb@bieringer.de>
56
#
67
# This library is free software: you can redistribute it and/or modify
78
# it under the terms of the GNU General Public License as published by
@@ -58,7 +59,7 @@ def __init__(self, configuration: config.Configuration) -> None:
5859
self._hook = configuration.get("storage", "hook")
5960

6061
@types.contextmanager
61-
def acquire_lock(self, mode: str, user: str = "") -> Iterator[None]:
62+
def acquire_lock(self, mode: str, user: str = "", *args, **kwargs) -> Iterator[None]:
6263
with self._lock.acquire(mode):
6364
yield
6465
# execute hook
@@ -73,8 +74,17 @@ def acquire_lock(self, mode: str, user: str = "") -> Iterator[None]:
7374
else:
7475
# Process group is also used to identify child processes
7576
preexec_fn = os.setpgrp
76-
command = self._hook % {
77-
"user": shlex.quote(user or "Anonymous")}
77+
# optional argument
78+
path = kwargs.get('path', "")
79+
try:
80+
command = self._hook % {
81+
"path": shlex.quote(self._get_collection_root_folder() + path),
82+
"cwd": shlex.quote(self._filesystem_folder),
83+
"user": shlex.quote(user or "Anonymous")}
84+
except KeyError as e:
85+
logger.error("Storage hook contains not supported placeholder %s (skip execution of: %r)" % (e, self._hook))
86+
return
87+
7888
logger.debug("Executing storage hook: '%s'" % command)
7989
try:
8090
p = subprocess.Popen(

0 commit comments

Comments
 (0)