remove everything marked as DEPRECATED

This commit is contained in:
Unrud 2018-08-16 07:59:58 +02:00
parent e96410c6e7
commit c7d1936cb6
7 changed files with 32 additions and 107 deletions

View File

@ -449,6 +449,7 @@ class Application:
return response(*NOT_FOUND) return response(*NOT_FOUND)
# Ask authentication backend to check rights # Ask authentication backend to check rights
login = password = ""
external_login = self.Auth.get_external_login(environ) external_login = self.Auth.get_external_login(environ)
authorization = environ.get("HTTP_AUTHORIZATION", "") authorization = environ.get("HTTP_AUTHORIZATION", "")
if external_login: if external_login:
@ -458,10 +459,6 @@ class Application:
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)
else:
# DEPRECATED: use remote_user backend instead
login = environ.get("REMOTE_USER", "")
password = ""
user = self.Auth.login(login, password) or "" if login else "" user = self.Auth.login(login, password) or "" if login else ""
if user and login == user: if user and login == user:
@ -961,7 +958,7 @@ class Application:
new_props = parent_item.get_meta() new_props = parent_item.get_meta()
new_props["tag"] = tag new_props["tag"] = tag
storage.check_and_sanitize_props(new_props) storage.check_and_sanitize_props(new_props)
parent_item.set_meta_all(new_props) parent_item.set_meta(new_props)
new_item = parent_item.upload(href, items[0]) new_item = parent_item.upload(href, items[0])
except ValueError as e: except ValueError as e:
logger.warning( logger.warning(

View File

@ -62,14 +62,13 @@ from importlib import import_module
from radicale.log import logger from radicale.log import logger
INTERNAL_TYPES = ("None", "none", "remote_user", "http_x_remote_user", INTERNAL_TYPES = ("none", "remote_user", "http_x_remote_user", "htpasswd")
"htpasswd")
def load(configuration): def load(configuration):
"""Load the authentication manager chosen in configuration.""" """Load the authentication manager chosen in configuration."""
auth_type = configuration.get("auth", "type") auth_type = configuration.get("auth", "type")
if auth_type in ("None", "none"): # DEPRECATED: use "none" if auth_type == "none":
class_ = NoneAuth class_ = NoneAuth
elif auth_type == "remote_user": elif auth_type == "remote_user":
class_ = RemoteUserAuth class_ = RemoteUserAuth
@ -114,39 +113,12 @@ class BaseAuth:
""" """
user = self.map_login_to_user(login)
if user and self.is_authenticated2(login, user, password):
return user
return ""
def is_authenticated2(self, login, user, password):
"""Validate credentials.
DEPRECATED: use ``login`` instead
"""
return self.is_authenticated(user, password)
def is_authenticated(self, user, password):
"""Validate credentials.
DEPRECATED: use ``login`` instead
"""
raise NotImplementedError raise NotImplementedError
def map_login_to_user(self, login):
"""Map login name to internal user.
DEPRECATED: use ``login`` instead
"""
return login
class NoneAuth(BaseAuth): class NoneAuth(BaseAuth):
def is_authenticated(self, user, password): def login(self, login, password):
return True return login
class Auth(BaseAuth): class Auth(BaseAuth):
@ -239,11 +211,11 @@ class Auth(BaseAuth):
hash_value = hash_value.strip() hash_value = hash_value.strip()
return md5_apr1.verify(password, hash_value) return md5_apr1.verify(password, hash_value)
def is_authenticated(self, user, password): def login(self, login, password):
"""Validate credentials. """Validate credentials.
Iterate through htpasswd credential file until user matches, extract Iterate through htpasswd credential file until login matches, extract
hash (encrypted password) and check hash against user-given password, hash (encrypted password) and check hash against password,
using the method specified in the Radicale config. using the method specified in the Radicale config.
The content of the file is not cached because reading is generally a The content of the file is not cached because reading is generally a
@ -257,20 +229,21 @@ class Auth(BaseAuth):
line = line.rstrip("\n") line = line.rstrip("\n")
if line.lstrip() and not line.lstrip().startswith("#"): if line.lstrip() and not line.lstrip().startswith("#"):
try: try:
login, hash_value = line.split(":", maxsplit=1) hash_login, hash_value = line.split(
":", maxsplit=1)
# 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(login, user) 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 True 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 False return ""
class RemoteUserAuth(NoneAuth): class RemoteUserAuth(NoneAuth):

View File

@ -46,16 +46,16 @@ from importlib import import_module
from radicale import storage from radicale import storage
from radicale.log import logger from radicale.log import logger
INTERNAL_TYPES = ("None", "none", "authenticated", "owner_write", "owner_only", INTERNAL_TYPES = ("none", "authenticated", "owner_write", "owner_only",
"from_file") "from_file")
def load(configuration): def load(configuration):
"""Load the rights manager chosen in configuration.""" """Load the rights manager chosen in configuration."""
rights_type = configuration.get("rights", "type") rights_type = configuration.get("rights", "type")
if configuration.get("auth", "type") in ("None", "none"): # DEPRECATED if configuration.get("auth", "type") == "none":
rights_type = "None" rights_type = "none"
if rights_type in ("None", "none"): # DEPRECATED: use "none" if rights_type == "none":
rights_class = NoneRights rights_class = NoneRights
elif rights_type == "authenticated": elif rights_type == "authenticated":
rights_class = AuthenticatedRights rights_class = AuthenticatedRights

View File

@ -495,16 +495,6 @@ class BaseCollection:
"""Collection is a principal.""" """Collection is a principal."""
return bool(self.path) and "/" not in self.path return bool(self.path) and "/" not in self.path
@owner.setter
def owner(self, value):
# DEPRECATED: Included for compatibility reasons
pass
@is_principal.setter
def is_principal(self, value):
# DEPRECATED: Included for compatibility reasons
pass
@classmethod @classmethod
def discover(cls, path, depth="0"): def discover(cls, path, depth="0"):
"""Discover a list of collections under the given ``path``. """Discover a list of collections under the given ``path``.
@ -596,14 +586,6 @@ class BaseCollection:
raise NotImplementedError raise NotImplementedError
def get_multi(self, hrefs): def get_multi(self, hrefs):
"""Fetch multiple items. Duplicate hrefs must be ignored.
DEPRECATED: use ``get_multi2`` instead
"""
return (self.get(href) for href in set(hrefs))
def get_multi2(self, hrefs):
"""Fetch multiple items. """Fetch multiple items.
Functionally similar to ``get``, but might bring performance benefits Functionally similar to ``get``, but might bring performance benefits
@ -639,14 +621,6 @@ class BaseCollection:
""" """
return ((item, False) for item in self.get_all()) return ((item, False) for item in self.get_all())
def pre_filtered_list(self, filters):
"""List collection items with optional pre filtering.
DEPRECATED: use ``get_all_filtered`` instead
"""
return self.get_all()
def has(self, href): def has(self, href):
"""Check if an item exists by its href. """Check if an item exists by its href.
@ -687,26 +661,10 @@ class BaseCollection:
def set_meta(self, props): def set_meta(self, props):
"""Set metadata values for collection. """Set metadata values for collection.
``props`` a dict with updates for properties. If a value is empty, the
property must be deleted.
DEPRECATED: use ``set_meta_all`` instead
"""
raise NotImplementedError
def set_meta_all(self, props):
"""Set metadata values for collection.
``props`` a dict with values for properties. ``props`` a dict with values for properties.
""" """
delta_props = self.get_meta() raise NotImplementedError
for key in delta_props.keys():
if key not in props:
delta_props[key] = None
delta_props.update(props)
self.set_meta(self, delta_props)
@property @property
def last_modified(self): def last_modified(self):
@ -808,16 +766,11 @@ class Collection(BaseCollection):
lock_path = os.path.join(folder, ".Radicale.lock") lock_path = os.path.join(folder, ".Radicale.lock")
cls._lock = FileBackedRwLock(lock_path) cls._lock = FileBackedRwLock(lock_path)
def __init__(self, path, principal=None, folder=None, def __init__(self, path, filesystem_path=None):
filesystem_path=None): folder = self._get_collection_root_folder()
# DEPRECATED: Remove principal and folder attributes
if folder is None:
folder = self._get_collection_root_folder()
# Path should already be sanitized # Path should already be sanitized
self.path = sanitize_path(path).strip("/") self.path = sanitize_path(path).strip("/")
self._encoding = self.configuration.get("encoding", "stock") self._encoding = self.configuration.get("encoding", "stock")
# DEPRECATED: Use ``self._encoding`` instead
self.encoding = self._encoding
if filesystem_path is None: if filesystem_path is None:
filesystem_path = path_to_filesystem(folder, self.path) filesystem_path = path_to_filesystem(folder, self.path)
self._filesystem_path = filesystem_path self._filesystem_path = filesystem_path
@ -1028,7 +981,7 @@ class Collection(BaseCollection):
tmp_filesystem_path = os.path.join(tmp_dir, "collection") tmp_filesystem_path = os.path.join(tmp_dir, "collection")
os.makedirs(tmp_filesystem_path) os.makedirs(tmp_filesystem_path)
self = cls(sane_path, filesystem_path=tmp_filesystem_path) self = cls(sane_path, filesystem_path=tmp_filesystem_path)
self.set_meta_all(props) self.set_meta(props)
if collection: if collection:
if props.get("tag") == "VCALENDAR": if props.get("tag") == "VCALENDAR":
@ -1475,7 +1428,7 @@ class Collection(BaseCollection):
text=text, item=vobject_item, uid=uid, name=name, text=text, item=vobject_item, uid=uid, name=name,
component_name=tag), (tag, start, end) component_name=tag), (tag, start, end)
def get_multi2(self, hrefs): def get_multi(self, hrefs):
# It's faster to check for file name collissions here, because # It's faster to check for file name collissions here, because
# we only need to call os.listdir once. # we only need to call os.listdir once.
files = None files = None
@ -1575,7 +1528,7 @@ class Collection(BaseCollection):
"%r: %s" % (self.path, e)) from e "%r: %s" % (self.path, e)) from e
return self._meta_cache.get(key) if key else self._meta_cache return self._meta_cache.get(key) if key else self._meta_cache
def set_meta_all(self, props): def set_meta(self, props):
with self._atomic_write(self._props_path, "w") as f: with self._atomic_write(self._props_path, "w") as f:
json.dump(props, f, sort_keys=True) json.dump(props, f, sort_keys=True)

View File

@ -27,5 +27,7 @@ from radicale import auth
class Auth(auth.BaseAuth): class Auth(auth.BaseAuth):
def is_authenticated(self, user, password): def login(self, login, password):
return user == "tmp" if login == "tmp":
return login
return ""

View File

@ -45,13 +45,13 @@ MIMETYPES = {
".xml": "text/xml"} ".xml": "text/xml"}
FALLBACK_MIMETYPE = "application/octet-stream" FALLBACK_MIMETYPE = "application/octet-stream"
INTERNAL_TYPES = ("None", "none", "internal") INTERNAL_TYPES = ("none", "internal")
def load(configuration): def load(configuration):
"""Load the web module chosen in configuration.""" """Load the web module chosen in configuration."""
web_type = configuration.get("web", "type") web_type = configuration.get("web", "type")
if web_type in ("None", "none"): # DEPRECATED: use "none" if web_type == "none":
web_class = NoneWeb web_class = NoneWeb
elif web_type == "internal": elif web_type == "internal":
web_class = Web web_class = Web

View File

@ -1121,7 +1121,7 @@ def proppatch(base_prefix, path, xml_request, collection):
pass pass
_add_propstat_to(response, short_name, 200) _add_propstat_to(response, short_name, 200)
storage.check_and_sanitize_props(new_props) storage.check_and_sanitize_props(new_props)
collection.set_meta_all(new_props) collection.set_meta(new_props)
return multistatus return multistatus
@ -1229,7 +1229,7 @@ def report(base_prefix, path, xml_request, collection):
# Reference is a collection # Reference is a collection
collection_requested = True collection_requested = True
for name, item in collection.get_multi2(get_names()): for name, item in collection.get_multi(get_names()):
if not item: if not item:
uri = "/" + posixpath.join(collection.path, name) uri = "/" + posixpath.join(collection.path, name)
response = _item_response(base_prefix, uri, response = _item_response(base_prefix, uri,