sharing: add support for proppatch

This commit is contained in:
Peter Bieringer
2026-02-24 06:44:16 +01:00
parent c2edfee738
commit 128b328569

View File

@@ -24,7 +24,7 @@ import re
import socket import socket
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from http import client from http import client
from typing import Dict, Optional, cast from typing import Dict, Optional, Union, cast
import defusedxml.ElementTree as DefusedET import defusedxml.ElementTree as DefusedET
@@ -37,7 +37,7 @@ from radicale.log import logger
def xml_proppatch(base_prefix: str, path: str, def xml_proppatch(base_prefix: str, path: str,
xml_request: Optional[ET.Element], xml_request: Optional[ET.Element],
collection: storage.BaseCollection) -> ET.Element: collection: storage.BaseCollection, sharing: Union[dict, None] = None) -> ET.Element:
"""Read and answer PROPPATCH requests. """Read and answer PROPPATCH requests.
Read rfc4918-9.2 for info. Read rfc4918-9.2 for info.
@@ -48,6 +48,9 @@ def xml_proppatch(base_prefix: str, path: str,
multistatus.append(response) multistatus.append(response)
href = ET.Element(xmlutils.make_clark("D:href")) href = ET.Element(xmlutils.make_clark("D:href"))
href.text = xmlutils.make_href(base_prefix, path) href.text = xmlutils.make_href(base_prefix, path)
if sharing:
# backmap
href.text = href.text.replace(sharing['PathMapped'], sharing['PathOrToken'])
response.append(href) response.append(href)
# Create D:propstat element for props with status 200 OK # Create D:propstat element for props with status 200 OK
propstat = ET.Element(xmlutils.make_clark("D:propstat")) propstat = ET.Element(xmlutils.make_clark("D:propstat"))
@@ -76,6 +79,15 @@ class ApplicationPartProppatch(ApplicationBase):
path: str, user: str, remote_host: str, remote_useragent: str) -> types.WSGIResponse: path: str, user: str, remote_host: str, remote_useragent: str) -> types.WSGIResponse:
"""Manage PROPPATCH request.""" """Manage PROPPATCH request."""
permissions_filter = None permissions_filter = None
sharing = None
if self._sharing._enabled:
# Sharing by token or map (if enabled)
sharing = self._sharing.sharing_collection_resolver(path, user)
if sharing:
# overwrite and run through extended permission check
path = sharing['PathMapped']
user = sharing['Owner']
permissions_filter = sharing['Permissions']
access = Access(self._rights, user, path, permissions_filter) access = Access(self._rights, user, path, permissions_filter)
if not access.check("w"): if not access.check("w"):
return httputils.NOT_ALLOWED return httputils.NOT_ALLOWED
@@ -100,7 +112,7 @@ class ApplicationPartProppatch(ApplicationBase):
"Content-Type": "text/xml; charset=%s" % self._encoding} "Content-Type": "text/xml; charset=%s" % self._encoding}
try: try:
xml_answer = xml_proppatch(base_prefix, path, xml_content, xml_answer = xml_proppatch(base_prefix, path, xml_content,
item) item, sharing)
if xml_content is not None: if xml_content is not None:
content = DefusedET.tostring( content = DefusedET.tostring(
xml_content, xml_content,