New right "i": Only allowing HTTP method GET
This commit is contained in:
parent
9bd852ba5e
commit
7f2d5cea62
@ -963,10 +963,12 @@ if you want to use regular curly braces in the `user` and `collection` regexes.
|
|||||||
|
|
||||||
The following `permissions` are recognized:
|
The following `permissions` are recognized:
|
||||||
|
|
||||||
* **R:** read a collection (excluding address book or calendar collections)
|
* **R:** read collections (excluding address books and calendars)
|
||||||
* **r:** read an address book or calendar collection
|
* **r:** read address book and calendar collections
|
||||||
* **W:** write a collection (excluding address book or calendar collections)
|
* **i:** subset of **r** that only allows direct access via HTTP method GET
|
||||||
* **w:** write an address book or calendar collection
|
(CalDAV/CardDAV is susceptible to expensive search requests)
|
||||||
|
* **W:** write collections (excluding address books and calendars)
|
||||||
|
* **w:** write address book and calendar collections
|
||||||
|
|
||||||
## Storage
|
## Storage
|
||||||
|
|
||||||
|
@ -71,21 +71,28 @@ class ApplicationGetMixin:
|
|||||||
if path == "/.web" or path.startswith("/.web/"):
|
if path == "/.web" or path.startswith("/.web/"):
|
||||||
return self._web.get(environ, base_prefix, path, user)
|
return self._web.get(environ, base_prefix, path, user)
|
||||||
access = app.Access(self._rights, user, path)
|
access = app.Access(self._rights, user, path)
|
||||||
if not access.check("r"):
|
if not access.check("r") and "i" not in access.permissions:
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
with self._storage.acquire_lock("r", user):
|
with self._storage.acquire_lock("r", user):
|
||||||
item = next(self._storage.discover(path), None)
|
item = next(self._storage.discover(path), None)
|
||||||
if not item:
|
if not item:
|
||||||
return httputils.NOT_FOUND
|
return httputils.NOT_FOUND
|
||||||
if not access.check("r", item):
|
if access.check("r", item):
|
||||||
|
limited_access = False
|
||||||
|
elif "i" in access.permissions:
|
||||||
|
limited_access = True
|
||||||
|
else:
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
if isinstance(item, storage.BaseCollection):
|
if isinstance(item, storage.BaseCollection):
|
||||||
tag = item.get_meta("tag")
|
tag = item.get_meta("tag")
|
||||||
if not tag:
|
if not tag:
|
||||||
return httputils.DIRECTORY_LISTING
|
return (httputils.NOT_ALLOWED if limited_access else
|
||||||
|
httputils.DIRECTORY_LISTING)
|
||||||
content_type = xmlutils.MIMETYPES[tag]
|
content_type = xmlutils.MIMETYPES[tag]
|
||||||
content_disposition = self._content_disposition_attachement(
|
content_disposition = self._content_disposition_attachement(
|
||||||
propose_filename(item))
|
propose_filename(item))
|
||||||
|
elif limited_access:
|
||||||
|
return httputils.NOT_ALLOWED
|
||||||
else:
|
else:
|
||||||
content_type = xmlutils.OBJECT_MIMETYPES[item.name]
|
content_type = xmlutils.OBJECT_MIMETYPES[item.name]
|
||||||
content_disposition = ""
|
content_disposition = ""
|
||||||
|
@ -21,10 +21,12 @@ collections and entries.
|
|||||||
|
|
||||||
Permissions:
|
Permissions:
|
||||||
|
|
||||||
- R: read a collection (excluding address book or calendar collections)
|
- R: read collections (excluding address books and calendars)
|
||||||
- r: read an address book or calendar collection
|
- r: read address book and calendar collections
|
||||||
- W: write a collection (excluding address book or calendar collections)
|
- i: subset of **r** that only allows direct access via HTTP method GET
|
||||||
- w: write an address book or calendar collection
|
(CalDAV/CardDAV is susceptible to expensive search requests)
|
||||||
|
- W: write collections (excluding address books and calendars)
|
||||||
|
- w: write address book and calendar collections
|
||||||
|
|
||||||
Take a look at the class ``BaseRights`` if you want to implement your own.
|
Take a look at the class ``BaseRights`` if you want to implement your own.
|
||||||
|
|
||||||
|
@ -136,6 +136,30 @@ permissions: Rr""")
|
|||||||
self._test_rights("from_file", "", "/custom/sub", "w", 401)
|
self._test_rights("from_file", "", "/custom/sub", "w", 401)
|
||||||
self._test_rights("from_file", "tmp", "/custom/sub", "w", 403)
|
self._test_rights("from_file", "tmp", "/custom/sub", "w", 403)
|
||||||
|
|
||||||
|
def test_from_file_limited_get(self):
|
||||||
|
rights_file_path = os.path.join(self.colpath, "rights")
|
||||||
|
with open(rights_file_path, "w") as f:
|
||||||
|
f.write("""\
|
||||||
|
[write-all]
|
||||||
|
user: tmp
|
||||||
|
collection: .*
|
||||||
|
permissions: RrWw
|
||||||
|
[limited-public]
|
||||||
|
user: .*
|
||||||
|
collection: public/[^/]*
|
||||||
|
permissions: i""")
|
||||||
|
self.configuration.update(
|
||||||
|
{"rights": {"type": "from_file",
|
||||||
|
"file": rights_file_path}}, "test")
|
||||||
|
self.application = Application(self.configuration)
|
||||||
|
self.mkcalendar("/tmp/calendar", login="tmp:bepo")
|
||||||
|
self.mkcol("/public", login="tmp:bepo")
|
||||||
|
self.mkcalendar("/public/calendar", login="tmp:bepo")
|
||||||
|
self.get("/tmp/calendar", check=401)
|
||||||
|
self.get("/public/", check=401)
|
||||||
|
self.get("/public/calendar")
|
||||||
|
self.get("/public/calendar/1.ics", check=401)
|
||||||
|
|
||||||
def test_custom(self):
|
def test_custom(self):
|
||||||
"""Custom rights management."""
|
"""Custom rights management."""
|
||||||
self._test_rights("radicale.tests.custom.rights", "", "/", "r", 401)
|
self._test_rights("radicale.tests.custom.rights", "", "/", "r", 401)
|
||||||
|
13
rights
13
rights
@ -75,19 +75,24 @@
|
|||||||
# Example: Allow everybody (including unauthenticated users) to read
|
# Example: Allow everybody (including unauthenticated users) to read
|
||||||
# the collection "public"
|
# the collection "public"
|
||||||
|
|
||||||
# Allow reading collection "public"
|
# Allow reading collection "public" for authenticated users
|
||||||
#[public-principal]
|
#[public-principal]
|
||||||
#user: .*
|
#user: .+
|
||||||
#collection: public
|
#collection: public
|
||||||
#permissions: R
|
#permissions: R
|
||||||
|
|
||||||
# Allow reading all calendars and address books that are direct children of
|
# Allow reading all calendars and address books that are direct children of
|
||||||
# the collection "public"
|
# the collection "public" for authenticated users
|
||||||
#[public-calendars]
|
#[public-calendars]
|
||||||
#user: .*
|
#user: .+
|
||||||
#collection: public/[^/]+
|
#collection: public/[^/]+
|
||||||
#permissions: r
|
#permissions: r
|
||||||
|
|
||||||
|
# Allow access to public calendars and address books via HTTP GET for everyone
|
||||||
|
#[public-calendars-restricted]
|
||||||
|
#user: .*
|
||||||
|
#collection: public/[^/]+
|
||||||
|
#permissions: i
|
||||||
|
|
||||||
# Example: Grant users of the form user@domain.tld read access to the
|
# Example: Grant users of the form user@domain.tld read access to the
|
||||||
# collection "domain.tld"
|
# collection "domain.tld"
|
||||||
|
Loading…
Reference in New Issue
Block a user