summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--passlib/tests/test_utils_handlers.py37
-rw-r--r--passlib/utils/handlers.py61
2 files changed, 91 insertions, 7 deletions
diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py
index 7e4193c..3342570 100644
--- a/passlib/tests/test_utils_handlers.py
+++ b/passlib/tests/test_utils_handlers.py
@@ -10,7 +10,7 @@ from logging import getLogger
import warnings
#site
#pkg
-from passlib.hash import ldap_md5
+from passlib.hash import ldap_md5, sha256_crypt
from passlib.registry import _unload_handler_name as unload_handler_name, \
register_crypt_handler, get_crypt_handler
from passlib.utils import rng, getrandstr, handlers as uh, bytes, b, \
@@ -234,7 +234,7 @@ class SkeletonTest(TestCase):
self.assertTrue(d1.has_backend())
d1.set_backend('a')
self.assertEqual(obj.calc_checksum('s'), 'a')
-
+
#test unknown backend
self.assertRaises(ValueError, d1.set_backend, 'c')
self.assertRaises(ValueError, d1.has_backend, 'c')
@@ -330,6 +330,11 @@ class PrefixWrapperTest(TestCase):
d1 = uh.PrefixWrapper("d1", "ldap_md5", "{XXX}", "{MD5}")
self.assertEqual(d1.name, "d1")
self.assertIs(d1.setting_kwds, ldap_md5.setting_kwds)
+ self.assertFalse('max_rounds' in dir(d1))
+
+ d2 = uh.PrefixWrapper("d2", "sha256_crypt", "{XXX}")
+ self.assertIs(d2.setting_kwds, sha256_crypt.setting_kwds)
+ self.assertTrue('max_rounds' in dir(d2))
def test_11_wrapped_methods(self):
d1 = uh.PrefixWrapper("d1", "ldap_md5", "{XXX}", "{MD5}")
@@ -355,6 +360,34 @@ class PrefixWrapperTest(TestCase):
self.assertRaises(ValueError, d1.verify, "password", lph)
self.assertTrue(d1.verify("password", dph))
+ def test_12_ident(self):
+ # test ident is proxied
+ h = uh.PrefixWrapper("h2", "ldap_md5", "{XXX}")
+ self.assertEqual(h.ident, u"{XXX}{MD5}")
+ self.assertIs(h.ident_values, None)
+
+ # test orig_prefix disabled ident proxy
+ h = uh.PrefixWrapper("h1", "ldap_md5", "{XXX}", "{MD5}")
+ self.assertIs(h.ident, None)
+ self.assertIs(h.ident_values, None)
+
+ # test custom ident overrides default
+ h = uh.PrefixWrapper("h3", "ldap_md5", "{XXX}", ident="{X")
+ self.assertEqual(h.ident, u"{X")
+ self.assertIs(h.ident_values, None)
+
+ # test custom ident must match
+ h = uh.PrefixWrapper("h3", "ldap_md5", "{XXX}", ident="{XXX}A")
+ self.assertRaises(ValueError, uh.PrefixWrapper, "h3", "ldap_md5",
+ "{XXX}", ident="{XY")
+ self.assertRaises(ValueError, uh.PrefixWrapper, "h3", "ldap_md5",
+ "{XXX}", ident="{XXXX")
+
+ # test ident_values is proxied
+ h = uh.PrefixWrapper("h4", "bcrypt", "{XXX}")
+ self.assertIs(h.ident, None)
+ self.assertEqual(h.ident_values, [ u"{XXX}$2$", u"{XXX}$2a$" ])
+
#=========================================================
#sample algorithms - these serve as known quantities
# to test the unittests themselves, as well as other
diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py
index e555421..e372f85 100644
--- a/passlib/utils/handlers.py
+++ b/passlib/utils/handlers.py
@@ -1156,7 +1156,8 @@ class PrefixWrapper(object):
:param lazy: if True and wrapped handler is specified by name, don't look it up until needed.
"""
- def __init__(self, name, wrapped, prefix=u'', orig_prefix=u'', lazy=False, doc=None):
+ def __init__(self, name, wrapped, prefix=u'', orig_prefix=u'', lazy=False,
+ doc=None, ident=None):
self.name = name
if isinstance(prefix, bytes):
prefix = prefix.decode("ascii")
@@ -1174,6 +1175,13 @@ class PrefixWrapper(object):
if not lazy:
self._get_wrapped()
+ if ident is not None:
+ if isinstance(ident, bytes):
+ ident = ident.decode("ascii")
+ if ident[:len(prefix)] != prefix[:len(ident)]:
+ raise ValueError("ident agree with prefix")
+ self._ident = ident
+
_wrapped_name = None
_wrapped_handler = None
@@ -1192,9 +1200,42 @@ class PrefixWrapper(object):
wrapped = property(_get_wrapped)
- ##@property
- ##def ident(self):
- ## return self._prefix
+ _ident = False
+
+ @property
+ def ident(self):
+ value = self._ident
+ if value is False:
+ value = None
+ # XXX: how will this interact with orig_prefix ?
+ # not exposing attrs for now if orig_prefix is set.
+ if not self.orig_prefix:
+ wrapped = self.wrapped
+ ident = getattr(wrapped, "ident", None)
+ if ident is not None:
+ value = self._wrap_hash(ident)
+ self._ident = value
+ return value
+
+ _ident_values = False
+ @property
+ def ident_values(self):
+ value = self._ident_values
+ if value is False:
+ value = None
+ # XXX: how will this interact with orig_prefix ?
+ # not exposing attrs for now if orig_prefix is set.
+ if not self.orig_prefix:
+ wrapped = self.wrapped
+ idents = getattr(wrapped, "ident_values", None)
+ if idents:
+ value = [ self._wrap_hash(ident) for ident in idents ]
+ ##else:
+ ## ident = self.ident
+ ## if ident is not None:
+ ## value = [ident]
+ self._ident_values = value
+ return value
#attrs that should be proxied
_proxy_attrs = (
@@ -1208,10 +1249,20 @@ class PrefixWrapper(object):
if self.prefix:
args.append("prefix=%r" % self.prefix)
if self.orig_prefix:
- args.append("orig_prefix=%r", self.orig_prefix)
+ args.append("orig_prefix=%r" % self.orig_prefix)
args = ", ".join(args)
return 'PrefixWrapper(%r, %s)' % (self.name, args)
+ def __dir__(self):
+ attrs = set(dir(self.__class__))
+ attrs.update(self.__dict__)
+ wrapped = self.wrapped
+ attrs.update(
+ attr for attr in self._proxy_attrs
+ if hasattr(wrapped, attr)
+ )
+ return list(attrs)
+
def __getattr__(self, attr):
"proxy most attributes from wrapped class (eg rounds, salt size, etc)"
if attr in self._proxy_attrs: