Prefix internal attributes with underscore
This commit is contained in:
parent
4f6a342211
commit
e07df9fd1d
@ -96,7 +96,7 @@ class Application(
|
|||||||
|
|
||||||
return request_environ
|
return request_environ
|
||||||
|
|
||||||
def decode(self, text, environ):
|
def _decode(self, text, environ):
|
||||||
"""Try to magically decode ``text`` according to given ``environ``."""
|
"""Try to magically decode ``text`` according to given ``environ``."""
|
||||||
# List of charsets to try
|
# List of charsets to try
|
||||||
charsets = []
|
charsets = []
|
||||||
@ -238,7 +238,7 @@ class Application(
|
|||||||
login, password = login or "", password or ""
|
login, password = login or "", password or ""
|
||||||
elif authorization.startswith("Basic"):
|
elif authorization.startswith("Basic"):
|
||||||
authorization = authorization[len("Basic"):].strip()
|
authorization = authorization[len("Basic"):].strip()
|
||||||
login, password = self.decode(base64.b64decode(
|
login, password = self._decode(base64.b64decode(
|
||||||
authorization.encode("ascii")), environ).split(":", 1)
|
authorization.encode("ascii")), environ).split(":", 1)
|
||||||
|
|
||||||
user = self._auth.login(login, password) or "" if login else ""
|
user = self._auth.login(login, password) or "" if login else ""
|
||||||
@ -312,7 +312,7 @@ class Application(
|
|||||||
|
|
||||||
return response(status, headers, answer)
|
return response(status, headers, answer)
|
||||||
|
|
||||||
def access(self, user, path, permission, item=None):
|
def _access(self, user, path, permission, item=None):
|
||||||
if permission not in "rw":
|
if permission not in "rw":
|
||||||
raise ValueError("Invalid permission argument: %r" % permission)
|
raise ValueError("Invalid permission argument: %r" % permission)
|
||||||
if not item:
|
if not item:
|
||||||
@ -336,7 +336,7 @@ class Application(
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def read_raw_content(self, environ):
|
def _read_raw_content(self, environ):
|
||||||
content_length = int(environ.get("CONTENT_LENGTH") or 0)
|
content_length = int(environ.get("CONTENT_LENGTH") or 0)
|
||||||
if not content_length:
|
if not content_length:
|
||||||
return b""
|
return b""
|
||||||
@ -345,13 +345,13 @@ class Application(
|
|||||||
raise RuntimeError("Request body too short: %d" % len(content))
|
raise RuntimeError("Request body too short: %d" % len(content))
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def read_content(self, environ):
|
def _read_content(self, environ):
|
||||||
content = self.decode(self.read_raw_content(environ), environ)
|
content = self._decode(self._read_raw_content(environ), environ)
|
||||||
logger.debug("Request content:\n%s", content)
|
logger.debug("Request content:\n%s", content)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def read_xml_content(self, environ):
|
def _read_xml_content(self, environ):
|
||||||
content = self.decode(self.read_raw_content(environ), environ)
|
content = self._decode(self._read_raw_content(environ), environ)
|
||||||
if not content:
|
if not content:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
@ -364,7 +364,7 @@ class Application(
|
|||||||
xmlutils.pretty_xml(xml_content))
|
xmlutils.pretty_xml(xml_content))
|
||||||
return xml_content
|
return xml_content
|
||||||
|
|
||||||
def write_xml_content(self, xml_content):
|
def _write_xml_content(self, xml_content):
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("Response content:\n%s",
|
logger.debug("Response content:\n%s",
|
||||||
xmlutils.pretty_xml(xml_content))
|
xmlutils.pretty_xml(xml_content))
|
||||||
@ -373,10 +373,10 @@ class Application(
|
|||||||
xml_declaration=True)
|
xml_declaration=True)
|
||||||
return f.getvalue()
|
return f.getvalue()
|
||||||
|
|
||||||
def webdav_error_response(self, namespace, name,
|
def _webdav_error_response(self, namespace, name,
|
||||||
status=httputils.WEBDAV_PRECONDITION_FAILED[0]):
|
status=httputils.WEBDAV_PRECONDITION_FAILED[0]):
|
||||||
"""Generate XML error response."""
|
"""Generate XML error response."""
|
||||||
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
||||||
content = self.write_xml_content(
|
content = self._write_xml_content(
|
||||||
xmlutils.webdav_error(namespace, name))
|
xmlutils.webdav_error(namespace, name))
|
||||||
return status, headers, content
|
return status, headers, content
|
||||||
|
@ -49,13 +49,13 @@ def xml_delete(base_prefix, path, collection, href=None):
|
|||||||
class ApplicationDeleteMixin:
|
class ApplicationDeleteMixin:
|
||||||
def do_DELETE(self, environ, base_prefix, path, user):
|
def do_DELETE(self, environ, base_prefix, path, user):
|
||||||
"""Manage DELETE request."""
|
"""Manage DELETE request."""
|
||||||
if not self.access(user, path, "w"):
|
if not self._access(user, path, "w"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
with self._storage.acquire_lock("w", user):
|
with self._storage.acquire_lock("w", 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 self.access(user, path, "w", item):
|
if not self._access(user, path, "w", item):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
if_match = environ.get("HTTP_IF_MATCH", "*")
|
if_match = environ.get("HTTP_IF_MATCH", "*")
|
||||||
if if_match not in ("*", item.etag):
|
if if_match not in ("*", item.etag):
|
||||||
@ -67,4 +67,4 @@ class ApplicationDeleteMixin:
|
|||||||
xml_answer = xml_delete(
|
xml_answer = xml_delete(
|
||||||
base_prefix, path, item.collection, item.href)
|
base_prefix, path, item.collection, item.href)
|
||||||
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
||||||
return client.OK, headers, self.write_xml_content(xml_answer)
|
return client.OK, headers, self._write_xml_content(xml_answer)
|
||||||
|
@ -70,13 +70,13 @@ class ApplicationGetMixin:
|
|||||||
# Dispatch .web URL to web module
|
# Dispatch .web URL to web module
|
||||||
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)
|
||||||
if not self.access(user, path, "r"):
|
if not self._access(user, path, "r"):
|
||||||
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 self.access(user, path, "r", item):
|
if not self._access(user, path, "r", item):
|
||||||
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")
|
||||||
|
@ -33,7 +33,7 @@ class ApplicationMkcalendarMixin:
|
|||||||
if not self._rights.authorized(user, path, "w"):
|
if not self._rights.authorized(user, path, "w"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
try:
|
try:
|
||||||
xml_content = self.read_xml_content(environ)
|
xml_content = self._read_xml_content(environ)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad MKCALENDAR request on %r: %s", path, e, exc_info=True)
|
"Bad MKCALENDAR request on %r: %s", path, e, exc_info=True)
|
||||||
@ -54,7 +54,7 @@ class ApplicationMkcalendarMixin:
|
|||||||
with self._storage.acquire_lock("w", user):
|
with self._storage.acquire_lock("w", user):
|
||||||
item = next(self._storage.discover(path), None)
|
item = next(self._storage.discover(path), None)
|
||||||
if item:
|
if item:
|
||||||
return self.webdav_error_response(
|
return self._webdav_error_response(
|
||||||
"D", "resource-must-be-null")
|
"D", "resource-must-be-null")
|
||||||
parent_path = pathutils.unstrip_path(
|
parent_path = pathutils.unstrip_path(
|
||||||
posixpath.dirname(pathutils.strip_path(path)), True)
|
posixpath.dirname(pathutils.strip_path(path)), True)
|
||||||
|
@ -34,7 +34,7 @@ class ApplicationMkcolMixin:
|
|||||||
if not permissions:
|
if not permissions:
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
try:
|
try:
|
||||||
xml_content = self.read_xml_content(environ)
|
xml_content = self._read_xml_content(environ)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad MKCOL request on %r: %s", path, e, exc_info=True)
|
"Bad MKCOL request on %r: %s", path, e, exc_info=True)
|
||||||
|
@ -34,7 +34,7 @@ class ApplicationMoveMixin:
|
|||||||
logger.info("Unsupported destination address: %r", raw_dest)
|
logger.info("Unsupported destination address: %r", raw_dest)
|
||||||
# Remote destination server, not supported
|
# Remote destination server, not supported
|
||||||
return httputils.REMOTE_DESTINATION
|
return httputils.REMOTE_DESTINATION
|
||||||
if not self.access(user, path, "w"):
|
if not self._access(user, path, "w"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
to_path = pathutils.sanitize_path(to_url.path)
|
to_path = pathutils.sanitize_path(to_url.path)
|
||||||
if not (to_path + "/").startswith(base_prefix + "/"):
|
if not (to_path + "/").startswith(base_prefix + "/"):
|
||||||
@ -42,15 +42,15 @@ class ApplicationMoveMixin:
|
|||||||
"start with base prefix", to_path, path)
|
"start with base prefix", to_path, path)
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
to_path = to_path[len(base_prefix):]
|
to_path = to_path[len(base_prefix):]
|
||||||
if not self.access(user, to_path, "w"):
|
if not self._access(user, to_path, "w"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
|
|
||||||
with self._storage.acquire_lock("w", user):
|
with self._storage.acquire_lock("w", 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 self.access(user, path, "w", item) or
|
if (not self._access(user, path, "w", item) or
|
||||||
not self.access(user, to_path, "w", item)):
|
not self._access(user, to_path, "w", item)):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
if isinstance(item, storage.BaseCollection):
|
if isinstance(item, storage.BaseCollection):
|
||||||
# TODO: support moving collections
|
# TODO: support moving collections
|
||||||
@ -74,7 +74,7 @@ class ApplicationMoveMixin:
|
|||||||
not to_item and
|
not to_item and
|
||||||
to_collection.path != item.collection.path and
|
to_collection.path != item.collection.path and
|
||||||
to_collection.has_uid(item.uid)):
|
to_collection.has_uid(item.uid)):
|
||||||
return self.webdav_error_response(
|
return self._webdav_error_response(
|
||||||
"C" if tag == "VCALENDAR" else "CR", "no-uid-conflict")
|
"C" if tag == "VCALENDAR" else "CR", "no-uid-conflict")
|
||||||
to_href = posixpath.basename(pathutils.strip_path(to_path))
|
to_href = posixpath.basename(pathutils.strip_path(to_path))
|
||||||
try:
|
try:
|
||||||
|
@ -357,10 +357,10 @@ class ApplicationPropfindMixin:
|
|||||||
|
|
||||||
def do_PROPFIND(self, environ, base_prefix, path, user):
|
def do_PROPFIND(self, environ, base_prefix, path, user):
|
||||||
"""Manage PROPFIND request."""
|
"""Manage PROPFIND request."""
|
||||||
if not self.access(user, path, "r"):
|
if not self._access(user, path, "r"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
try:
|
try:
|
||||||
xml_content = self.read_xml_content(environ)
|
xml_content = self._read_xml_content(environ)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad PROPFIND request on %r: %s", path, e, exc_info=True)
|
"Bad PROPFIND request on %r: %s", path, e, exc_info=True)
|
||||||
@ -375,7 +375,7 @@ class ApplicationPropfindMixin:
|
|||||||
item = next(items, None)
|
item = next(items, None)
|
||||||
if not item:
|
if not item:
|
||||||
return httputils.NOT_FOUND
|
return httputils.NOT_FOUND
|
||||||
if not self.access(user, path, "r", item):
|
if not self._access(user, path, "r", item):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
# put item back
|
# put item back
|
||||||
items = itertools.chain([item], items)
|
items = itertools.chain([item], items)
|
||||||
@ -387,4 +387,4 @@ class ApplicationPropfindMixin:
|
|||||||
self._encoding)
|
self._encoding)
|
||||||
if status == client.FORBIDDEN:
|
if status == client.FORBIDDEN:
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
return status, headers, self.write_xml_content(xml_answer)
|
return status, headers, self._write_xml_content(xml_answer)
|
||||||
|
@ -87,10 +87,10 @@ def xml_proppatch(base_prefix, path, xml_request, collection):
|
|||||||
class ApplicationProppatchMixin:
|
class ApplicationProppatchMixin:
|
||||||
def do_PROPPATCH(self, environ, base_prefix, path, user):
|
def do_PROPPATCH(self, environ, base_prefix, path, user):
|
||||||
"""Manage PROPPATCH request."""
|
"""Manage PROPPATCH request."""
|
||||||
if not self.access(user, path, "w"):
|
if not self._access(user, path, "w"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
try:
|
try:
|
||||||
xml_content = self.read_xml_content(environ)
|
xml_content = self._read_xml_content(environ)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad PROPPATCH request on %r: %s", path, e, exc_info=True)
|
"Bad PROPPATCH request on %r: %s", path, e, exc_info=True)
|
||||||
@ -102,7 +102,7 @@ class ApplicationProppatchMixin:
|
|||||||
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 self.access(user, path, "w", item):
|
if not self._access(user, path, "w", item):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
if not isinstance(item, storage.BaseCollection):
|
if not isinstance(item, storage.BaseCollection):
|
||||||
return httputils.FORBIDDEN
|
return httputils.FORBIDDEN
|
||||||
@ -116,4 +116,4 @@ class ApplicationProppatchMixin:
|
|||||||
"Bad PROPPATCH request on %r: %s", path, e, exc_info=True)
|
"Bad PROPPATCH request on %r: %s", path, e, exc_info=True)
|
||||||
return httputils.BAD_REQUEST
|
return httputils.BAD_REQUEST
|
||||||
return (client.MULTI_STATUS, headers,
|
return (client.MULTI_STATUS, headers,
|
||||||
self.write_xml_content(xml_answer))
|
self._write_xml_content(xml_answer))
|
||||||
|
@ -114,10 +114,10 @@ def prepare(vobject_items, path, content_type, permissions, parent_permissions,
|
|||||||
class ApplicationPutMixin:
|
class ApplicationPutMixin:
|
||||||
def do_PUT(self, environ, base_prefix, path, user):
|
def do_PUT(self, environ, base_prefix, path, user):
|
||||||
"""Manage PUT request."""
|
"""Manage PUT request."""
|
||||||
if not self.access(user, path, "w"):
|
if not self._access(user, path, "w"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
try:
|
try:
|
||||||
content = self.read_content(environ)
|
content = self._read_content(environ)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
logger.warning("Bad PUT request on %r: %s", path, e, exc_info=True)
|
logger.warning("Bad PUT request on %r: %s", path, e, exc_info=True)
|
||||||
return httputils.BAD_REQUEST
|
return httputils.BAD_REQUEST
|
||||||
@ -201,7 +201,7 @@ class ApplicationPutMixin:
|
|||||||
prepared_item, = prepared_items
|
prepared_item, = prepared_items
|
||||||
if (item and item.uid != prepared_item.uid or
|
if (item and item.uid != prepared_item.uid or
|
||||||
not item and parent_item.has_uid(prepared_item.uid)):
|
not item and parent_item.has_uid(prepared_item.uid)):
|
||||||
return self.webdav_error_response(
|
return self._webdav_error_response(
|
||||||
"C" if tag == "VCALENDAR" else "CR",
|
"C" if tag == "VCALENDAR" else "CR",
|
||||||
"no-uid-conflict")
|
"no-uid-conflict")
|
||||||
|
|
||||||
|
@ -257,10 +257,10 @@ def xml_item_response(base_prefix, href, found_props=(), not_found_props=(),
|
|||||||
class ApplicationReportMixin:
|
class ApplicationReportMixin:
|
||||||
def do_REPORT(self, environ, base_prefix, path, user):
|
def do_REPORT(self, environ, base_prefix, path, user):
|
||||||
"""Manage REPORT request."""
|
"""Manage REPORT request."""
|
||||||
if not self.access(user, path, "r"):
|
if not self._access(user, path, "r"):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
try:
|
try:
|
||||||
xml_content = self.read_xml_content(environ)
|
xml_content = self._read_xml_content(environ)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
||||||
@ -273,7 +273,7 @@ class ApplicationReportMixin:
|
|||||||
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 self.access(user, path, "r", item):
|
if not self._access(user, path, "r", item):
|
||||||
return httputils.NOT_ALLOWED
|
return httputils.NOT_ALLOWED
|
||||||
if isinstance(item, storage.BaseCollection):
|
if isinstance(item, storage.BaseCollection):
|
||||||
collection = item
|
collection = item
|
||||||
@ -288,4 +288,4 @@ class ApplicationReportMixin:
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
||||||
return httputils.BAD_REQUEST
|
return httputils.BAD_REQUEST
|
||||||
return (status, headers, self.write_xml_content(xml_answer))
|
return (status, headers, self._write_xml_content(xml_answer))
|
||||||
|
@ -63,24 +63,24 @@ from radicale import auth
|
|||||||
class Auth(auth.BaseAuth):
|
class Auth(auth.BaseAuth):
|
||||||
def __init__(self, configuration):
|
def __init__(self, configuration):
|
||||||
super().__init__(configuration)
|
super().__init__(configuration)
|
||||||
self.filename = configuration.get("auth", "htpasswd_filename")
|
self._filename = configuration.get("auth", "htpasswd_filename")
|
||||||
self.encryption = configuration.get("auth", "htpasswd_encryption")
|
encryption = configuration.get("auth", "htpasswd_encryption")
|
||||||
|
|
||||||
if self.encryption == "ssha":
|
if encryption == "ssha":
|
||||||
self.verify = self._ssha
|
self._verify = self._ssha
|
||||||
elif self.encryption == "sha1":
|
elif encryption == "sha1":
|
||||||
self.verify = self._sha1
|
self._verify = self._sha1
|
||||||
elif self.encryption == "plain":
|
elif encryption == "plain":
|
||||||
self.verify = self._plain
|
self._verify = self._plain
|
||||||
elif self.encryption == "md5":
|
elif encryption == "md5":
|
||||||
try:
|
try:
|
||||||
from passlib.hash import apr_md5_crypt
|
from passlib.hash import apr_md5_crypt
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"The htpasswd encryption method 'md5' requires "
|
"The htpasswd encryption method 'md5' requires "
|
||||||
"the passlib module.") from e
|
"the passlib module.") from e
|
||||||
self.verify = functools.partial(self._md5apr1, apr_md5_crypt)
|
self._verify = functools.partial(self._md5apr1, apr_md5_crypt)
|
||||||
elif self.encryption == "bcrypt":
|
elif encryption == "bcrypt":
|
||||||
try:
|
try:
|
||||||
from passlib.hash import bcrypt
|
from passlib.hash import bcrypt
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
@ -91,19 +91,18 @@ class Auth(auth.BaseAuth):
|
|||||||
# good error message if bcrypt backend is not available. Trigger
|
# good error message if bcrypt backend is not available. Trigger
|
||||||
# this here.
|
# this here.
|
||||||
bcrypt.hash("test-bcrypt-backend")
|
bcrypt.hash("test-bcrypt-backend")
|
||||||
self.verify = functools.partial(self._bcrypt, bcrypt)
|
self._verify = functools.partial(self._bcrypt, bcrypt)
|
||||||
elif self.encryption == "crypt":
|
elif encryption == "crypt":
|
||||||
try:
|
try:
|
||||||
import crypt
|
import crypt
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"The htpasswd encryption method 'crypt' requires "
|
"The htpasswd encryption method 'crypt' requires "
|
||||||
"the crypt() system support.") from e
|
"the crypt() system support.") from e
|
||||||
self.verify = functools.partial(self._crypt, crypt)
|
self._verify = functools.partial(self._crypt, crypt)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError("The htpasswd encryption method %r is not "
|
||||||
"The htpasswd encryption method %r is not "
|
"supported." % encryption)
|
||||||
"supported." % self.encryption)
|
|
||||||
|
|
||||||
def _plain(self, hash_value, password):
|
def _plain(self, hash_value, password):
|
||||||
"""Check if ``hash_value`` and ``password`` match, plain method."""
|
"""Check if ``hash_value`` and ``password`` match, plain method."""
|
||||||
@ -162,7 +161,7 @@ class Auth(auth.BaseAuth):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with open(self.filename) as f:
|
with open(self._filename) as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.rstrip("\n")
|
line = line.rstrip("\n")
|
||||||
if line.lstrip() and not line.lstrip().startswith("#"):
|
if line.lstrip() and not line.lstrip().startswith("#"):
|
||||||
@ -172,13 +171,13 @@ class Auth(auth.BaseAuth):
|
|||||||
# Always compare both login and password to avoid
|
# Always compare both login and password to avoid
|
||||||
# timing attacks, see #591.
|
# timing attacks, see #591.
|
||||||
login_ok = hmac.compare_digest(hash_login, login)
|
login_ok = hmac.compare_digest(hash_login, login)
|
||||||
password_ok = self.verify(hash_value, password)
|
password_ok = self._verify(hash_value, password)
|
||||||
if login_ok and password_ok:
|
if login_ok and password_ok:
|
||||||
return login
|
return login
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise RuntimeError("Invalid htpasswd file %r: %s" %
|
raise RuntimeError("Invalid htpasswd file %r: %s" %
|
||||||
(self.filename, e)) from e
|
(self._filename, e)) from e
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise RuntimeError("Failed to load htpasswd file %r: %s" %
|
raise RuntimeError("Failed to load htpasswd file %r: %s" %
|
||||||
(self.filename, e)) from e
|
(self._filename, e)) from e
|
||||||
return ""
|
return ""
|
||||||
|
@ -43,7 +43,7 @@ from radicale.log import logger
|
|||||||
class Rights(rights.BaseRights):
|
class Rights(rights.BaseRights):
|
||||||
def __init__(self, configuration):
|
def __init__(self, configuration):
|
||||||
super().__init__(configuration)
|
super().__init__(configuration)
|
||||||
self.filename = configuration.get("rights", "file")
|
self._filename = configuration.get("rights", "file")
|
||||||
|
|
||||||
def authorized(self, user, path, permissions):
|
def authorized(self, user, path, permissions):
|
||||||
user = user or ""
|
user = user or ""
|
||||||
@ -54,12 +54,12 @@ class Rights(rights.BaseRights):
|
|||||||
rights_config = configparser.ConfigParser(
|
rights_config = configparser.ConfigParser(
|
||||||
{"login": user_escaped, "path": sane_path_escaped})
|
{"login": user_escaped, "path": sane_path_escaped})
|
||||||
try:
|
try:
|
||||||
if not rights_config.read(self.filename):
|
if not rights_config.read(self._filename):
|
||||||
raise RuntimeError("No such file: %r" %
|
raise RuntimeError("No such file: %r" %
|
||||||
self.filename)
|
self._filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError("Failed to load rights file %r: %s" %
|
raise RuntimeError("Failed to load rights file %r: %s" %
|
||||||
(self.filename, e)) from e
|
(self._filename, e)) from e
|
||||||
for section in rights_config.sections():
|
for section in rights_config.sections():
|
||||||
try:
|
try:
|
||||||
user_pattern = rights_config.get(section, "user")
|
user_pattern = rights_config.get(section, "user")
|
||||||
@ -70,7 +70,7 @@ class Rights(rights.BaseRights):
|
|||||||
*map(re.escape, user_match.groups())), sane_path)
|
*map(re.escape, user_match.groups())), 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
|
||||||
if user_match and collection_match:
|
if user_match and collection_match:
|
||||||
logger.debug("Rule %r:%r matches %r:%r from section %r",
|
logger.debug("Rule %r:%r matches %r:%r from section %r",
|
||||||
user, sane_path, user_pattern,
|
user, sane_path, user_pattern,
|
||||||
|
Loading…
Reference in New Issue
Block a user