remove everything marked as DEPRECATED
This commit is contained in:
parent
e96410c6e7
commit
c7d1936cb6
@ -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(
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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 ""
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user