1
0
Fork 0
mirror of https://github.com/Kozea/Radicale.git synced 2025-09-15 20:36:55 +00:00

Improve rights checking and request handlers

* Access rights are checked before the storage is locked and
    collections are loaded.
  * DELETE sends 410 instead of doing nothing or crashing if the target
    doesn't exist.
  * GET always returns 404 if the target doesn't exist.
  * GET doesn't crash if a collection without tag property is requested.
  * MKCOL and MKCALENDAR send 409 if the target already exists.
  * MOVE checks if the target collection of an item actually exists and
    sends 409 otherwise.
  * PUT doesn't crash if a whole collection that doesn't exist yet is
    uploaded and ``content-type`` is ``text/vcard`` or
    ``text/calendar``.
  * PUT distinguishes between simple items and whole collections by the
    following criteria: Target is a collection; Parent exists; Parent
    has the tag property set; Parent contains other items. Before only
    the first two criteria where used, which was very unrelieable. #384
  * PROPPATCH is only allowed on collections and 409 is send otherwise.
  * ``Rights.authorized`` takes a path instead of a collection.
  * ``Collection.discover`` only returns items in ``path``, that
    actually exist. #442
This commit is contained in:
Unrud 2016-08-04 06:08:08 +02:00
parent b71664b322
commit 066b5994d1
5 changed files with 293 additions and 318 deletions

View file

@ -211,9 +211,7 @@ class BaseCollection:
returned.
If ``depth`` is anything but "0", it is considered as "1" and direct
children are included in the result. If ``include_container`` is
``True`` (the default), the containing object is included in the
result.
children are included in the result.
The ``path`` is relative.
@ -368,41 +366,39 @@ class Collection(BaseCollection):
attributes = sane_path.split("/")
if not attributes[0]:
attributes.pop()
# Try to guess if the path leads to a collection or an item
folder = os.path.expanduser(
cls.configuration.get("storage", "filesystem_folder"))
if not os.path.isdir(path_to_filesystem(folder, sane_path)):
# path is not a collection
if attributes and os.path.isfile(path_to_filesystem(folder,
sane_path)):
# path is an item
attributes.pop()
elif attributes and os.path.isdir(path_to_filesystem(
folder, *attributes[:-1])):
# path parent is a collection
attributes.pop()
# TODO: else: return?
try:
filesystem_path = path_to_filesystem(folder, sane_path)
except ValueError:
# Path is unsafe
return
href = None
if not os.path.isdir(filesystem_path):
if attributes and os.path.isfile(filesystem_path):
href = attributes.pop()
else:
return
path = "/".join(attributes)
principal = len(attributes) == 1
collection = cls(path, principal)
if href:
yield collection.get(href)
return
yield collection
if depth != "0":
# TODO: fix this
items = list(collection.list())
if items:
for item in items:
yield collection.get(item[0])
_, directories, _ = next(os.walk(collection._filesystem_path))
for sub_path in directories:
if not is_safe_filesystem_path_component(sub_path):
cls.logger.debug("Skipping collection: %s", sub_path)
continue
full_path = os.path.join(collection._filesystem_path, sub_path)
if os.path.exists(full_path):
yield cls(posixpath.join(path, sub_path))
if depth == "0":
return
for item in collection.list():
yield collection.get(item[0])
for href in os.listdir(filesystem_path):
if not is_safe_filesystem_path_component(href):
cls.logger.debug("Skipping collection: %s", href)
continue
child_filesystem_path = path_to_filesystem(filesystem_path, href)
if os.path.isdir(child_filesystem_path):
child_principal = len(attributes) == 0
yield cls(child_filesystem_path, child_principal)
@classmethod
def create_collection(cls, href, collection=None, tag=None):