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:
|
||||
|
||||
* **R:** read a collection (excluding address book or calendar collections)
|
||||
* **r:** read an address book or calendar collection
|
||||
* **W:** write a collection (excluding address book or calendar collections)
|
||||
* **w:** write an address book or calendar collection
|
||||
* **R:** read collections (excluding address books and calendars)
|
||||
* **r:** read address book and calendar collections
|
||||
* **i:** subset of **r** that only allows direct access via HTTP method GET
|
||||
(CalDAV/CardDAV is susceptible to expensive search requests)
|
||||
* **W:** write collections (excluding address books and calendars)
|
||||
* **w:** write address book and calendar collections
|
||||
|
||||
## Storage
|
||||
|
||||
|
@ -71,21 +71,28 @@ class ApplicationGetMixin:
|
||||
if path == "/.web" or path.startswith("/.web/"):
|
||||
return self._web.get(environ, base_prefix, path, user)
|
||||
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
|
||||
with self._storage.acquire_lock("r", user):
|
||||
item = next(self._storage.discover(path), None)
|
||||
if not item:
|
||||
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
|
||||
if isinstance(item, storage.BaseCollection):
|
||||
tag = item.get_meta("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_disposition = self._content_disposition_attachement(
|
||||
propose_filename(item))
|
||||
elif limited_access:
|
||||
return httputils.NOT_ALLOWED
|
||||
else:
|
||||
content_type = xmlutils.OBJECT_MIMETYPES[item.name]
|
||||
content_disposition = ""
|
||||
|
@ -21,10 +21,12 @@ collections and entries.
|
||||
|
||||
Permissions:
|
||||
|
||||
- R: read a collection (excluding address book or calendar collections)
|
||||
- r: read an address book or calendar collection
|
||||
- W: write a collection (excluding address book or calendar collections)
|
||||
- w: write an address book or calendar collection
|
||||
- R: read collections (excluding address books and calendars)
|
||||
- r: read address book and calendar collections
|
||||
- i: subset of **r** that only allows direct access via HTTP method GET
|
||||
(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.
|
||||
|
||||
|
@ -136,6 +136,30 @@ permissions: Rr""")
|
||||
self._test_rights("from_file", "", "/custom/sub", "w", 401)
|
||||
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):
|
||||
"""Custom rights management."""
|
||||
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
|
||||
# the collection "public"
|
||||
|
||||
# Allow reading collection "public"
|
||||
# Allow reading collection "public" for authenticated users
|
||||
#[public-principal]
|
||||
#user: .*
|
||||
#user: .+
|
||||
#collection: public
|
||||
#permissions: R
|
||||
|
||||
# Allow reading all calendars and address books that are direct children of
|
||||
# the collection "public"
|
||||
# the collection "public" for authenticated users
|
||||
#[public-calendars]
|
||||
#user: .*
|
||||
#user: .+
|
||||
#collection: public/[^/]+
|
||||
#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
|
||||
# collection "domain.tld"
|
||||
|
Loading…
Reference in New Issue
Block a user