mirror of
https://github.com/Kozea/Radicale.git
synced 2025-04-03 21:27:36 +03:00
Skip group collection match when groups are not used
This commit is contained in:
parent
ff5fae1663
commit
916c9db3c8
4 changed files with 19 additions and 7 deletions
|
@ -888,7 +888,7 @@ Default: `(cn={0})`
|
||||||
Load the ldap groups of the authenticated user. These groups can be used later on to define rights. This also gives you access to the group calendars, if they exist.
|
Load the ldap groups of the authenticated user. These groups can be used later on to define rights. This also gives you access to the group calendars, if they exist.
|
||||||
* The group calendar will be placed under collection_root_folder/GROUPS
|
* The group calendar will be placed under collection_root_folder/GROUPS
|
||||||
* The name of the calendar directory is the base64 encoded group name.
|
* The name of the calendar directory is the base64 encoded group name.
|
||||||
* The group calneder folders will not be created automaticaly. This must be created manualy. [Here](https://github.com/Kozea/Radicale/wiki/LDAP-authentication) you can find a script to create group calneder folders https://github.com/Kozea/Radicale/wiki/LDAP-authentication
|
* The group calendar folders will not be created automaticaly. This must be created manualy. [Here](https://github.com/Kozea/Radicale/wiki/LDAP-authentication) you can find a script to create group calendar folders https://github.com/Kozea/Radicale/wiki/LDAP-authentication
|
||||||
|
|
||||||
Default: False
|
Default: False
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,8 @@ class Rights(rights.BaseRights):
|
||||||
collection_pattern.format(
|
collection_pattern.format(
|
||||||
*(re.escape(s) for s in user_match.groups()),
|
*(re.escape(s) for s in user_match.groups()),
|
||||||
user=escaped_user), sane_path)
|
user=escaped_user), sane_path)
|
||||||
group_collection_match = re.fullmatch(collection_pattern.format(user=escaped_user), sane_path)
|
group_collection_match = group_match and re.fullmatch(
|
||||||
|
collection_pattern.format(user=escaped_user), sane_path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError("Error in section %r of rights file %r: "
|
raise RuntimeError("Error in section %r of rights file %r: "
|
||||||
"%s" % (section, self._filename, e)) from e
|
"%s" % (section, self._filename, e)) from e
|
||||||
|
|
|
@ -29,6 +29,7 @@ import wsgiref.util
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import defusedxml.ElementTree as DefusedET
|
import defusedxml.ElementTree as DefusedET
|
||||||
import vobject
|
import vobject
|
||||||
|
@ -167,7 +168,7 @@ class BaseTest:
|
||||||
assert answer is not None
|
assert answer is not None
|
||||||
responses = self.parse_responses(answer)
|
responses = self.parse_responses(answer)
|
||||||
if kwargs.get("HTTP_DEPTH", "0") == "0":
|
if kwargs.get("HTTP_DEPTH", "0") == "0":
|
||||||
assert len(responses) == 1 and path in responses
|
assert len(responses) == 1 and quote(path) in responses
|
||||||
return status, responses
|
return status, responses
|
||||||
|
|
||||||
def proppatch(self, path: str, data: Optional[str] = None,
|
def proppatch(self, path: str, data: Optional[str] = None,
|
||||||
|
|
|
@ -30,10 +30,10 @@ class TestBaseRightsRequests(BaseTest):
|
||||||
def _test_rights(self, rights_type: str, user: str, path: str, mode: str,
|
def _test_rights(self, rights_type: str, user: str, path: str, mode: str,
|
||||||
expected_status: int, with_auth: bool = True) -> None:
|
expected_status: int, with_auth: bool = True) -> None:
|
||||||
assert mode in ("r", "w")
|
assert mode in ("r", "w")
|
||||||
assert user in ("", "tmp")
|
assert user in ("", "tmp", "user@domain.test")
|
||||||
htpasswd_file_path = os.path.join(self.colpath, ".htpasswd")
|
htpasswd_file_path = os.path.join(self.colpath, ".htpasswd")
|
||||||
with open(htpasswd_file_path, "w") as f:
|
with open(htpasswd_file_path, "w") as f:
|
||||||
f.write("tmp:bepo\nother:bepo")
|
f.write("tmp:bepo\nother:bepo\nuser@domain.test:bepo")
|
||||||
self.configure({
|
self.configure({
|
||||||
"rights": {"type": rights_type},
|
"rights": {"type": rights_type},
|
||||||
"auth": {"type": "htpasswd" if with_auth else "none",
|
"auth": {"type": "htpasswd" if with_auth else "none",
|
||||||
|
@ -42,8 +42,9 @@ class TestBaseRightsRequests(BaseTest):
|
||||||
for u in ("tmp", "other"):
|
for u in ("tmp", "other"):
|
||||||
# Indirect creation of principal collection
|
# Indirect creation of principal collection
|
||||||
self.propfind("/%s/" % u, login="%s:bepo" % u)
|
self.propfind("/%s/" % u, login="%s:bepo" % u)
|
||||||
|
os.makedirs(os.path.join(self.colpath, "collection-root", "domain.test"), exist_ok=True)
|
||||||
(self.propfind if mode == "r" else self.proppatch)(
|
(self.propfind if mode == "r" else self.proppatch)(
|
||||||
path, check=expected_status, login="tmp:bepo" if user else None)
|
path, check=expected_status, login="%s:bepo" % user if user else None)
|
||||||
|
|
||||||
def test_owner_only(self) -> None:
|
def test_owner_only(self) -> None:
|
||||||
self._test_rights("owner_only", "", "/", "r", 401)
|
self._test_rights("owner_only", "", "/", "r", 401)
|
||||||
|
@ -110,14 +111,23 @@ permissions: RrWw
|
||||||
[custom]
|
[custom]
|
||||||
user: .*
|
user: .*
|
||||||
collection: custom(/.*)?
|
collection: custom(/.*)?
|
||||||
permissions: Rr""")
|
permissions: Rr
|
||||||
|
[read-domain-principal]
|
||||||
|
user: .+@([^@]+)
|
||||||
|
collection: {0}
|
||||||
|
permissions: R""")
|
||||||
self.configure({"rights": {"file": rights_file_path}})
|
self.configure({"rights": {"file": rights_file_path}})
|
||||||
self._test_rights("from_file", "", "/other/", "r", 401)
|
self._test_rights("from_file", "", "/other/", "r", 401)
|
||||||
|
self._test_rights("from_file", "tmp", "/tmp/", "r", 207)
|
||||||
self._test_rights("from_file", "tmp", "/other/", "r", 403)
|
self._test_rights("from_file", "tmp", "/other/", "r", 403)
|
||||||
self._test_rights("from_file", "", "/custom/sub", "r", 404)
|
self._test_rights("from_file", "", "/custom/sub", "r", 404)
|
||||||
self._test_rights("from_file", "tmp", "/custom/sub", "r", 404)
|
self._test_rights("from_file", "tmp", "/custom/sub", "r", 404)
|
||||||
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)
|
||||||
|
self._test_rights("from_file", "tmp", "/custom/sub", "w", 403)
|
||||||
|
self._test_rights("from_file", "user@domain.test", "/domain.test/", "r", 207)
|
||||||
|
self._test_rights("from_file", "user@domain.test", "/tmp/", "r", 403)
|
||||||
|
self._test_rights("from_file", "user@domain.test", "/other/", "r", 403)
|
||||||
|
|
||||||
def test_from_file_limited_get(self):
|
def test_from_file_limited_get(self):
|
||||||
rights_file_path = os.path.join(self.colpath, "rights")
|
rights_file_path = os.path.join(self.colpath, "rights")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue