def test_05_set_password(self): "test monkeypatched User.set_password()" user = FakeUser() # patch to use simple context utils.set_django_password_context(simple_context) self.assert_patched(context=simple_context) # sanity check self.assertEqual(user.password, '') self.assertIs(user.saved_password, None) if has_django1: self.assertTrue(user.has_usable_password()) # set password user.set_password(sample1) self.assertTrue(user.check_password(sample1)) self.assertEquals(simple_context.identify(user.password), "md5_crypt") self.assertIs(user.saved_password, None) #check unusable password user.set_password(None) if has_django1: self.assertFalse(user.has_usable_password()) self.assertIs(user.saved_password, None)
def test_03_check_password(self): "test monkeypatched User.check_password()" # NOTE: using FakeUser so we can test .save() user = FakeUser() # patch to use simple context utils.set_django_password_context(simple_context) self.assert_patched(context=simple_context) # test that blank hash is never accepted self.assertEqual(user.password, '') self.assertIs(user.saved_password, None) self.assertFalse(user.check_password('x')) # check correct secrets pass, and wrong ones fail user.password = sample1_md5 self.assertTrue(user.check_password(sample1)) self.assertFalse(user.check_password('x')) self.assertFalse(user.check_password(None)) # none of that should have triggered update of password self.assertEqual(user.password, sample1_md5) self.assertIs(user.saved_password, None) #check unusable password if has_django1: user.set_unusable_password() self.assertFalse(user.has_usable_password()) self.assertFalse(user.check_password(None)) self.assertFalse(user.check_password('')) self.assertFalse(user.check_password(sample1))
def test_04_check_password_migration(self): "test User.check_password() hash migration" # NOTE: using FakeUser so we can test .save() user = FakeUser() # patch to use simple context utils.set_django_password_context(simple_context) self.assert_patched(context=simple_context) # set things up with a password that needs migration user.password = sample1_des self.assertEqual(user.password, sample1_des) self.assertIs(user.saved_password, None) # run check with bad password... # shouldn't have migrated self.assertFalse(user.check_password('x')) self.assertFalse(user.check_password(None)) self.assertEqual(user.password, sample1_des) self.assertIs(user.saved_password, None) # run check with correct password... # should have migrated to md5 and called save() self.assertTrue(user.check_password(sample1)) self.assertTrue(user.password.startswith("$1$")) self.assertEqual(user.saved_password, user.password) # check resave doesn't happen user.saved_password = None self.assertTrue(user.check_password(sample1)) self.assertIs(user.saved_password, None)
def setUp(self): #remove django patch utils.set_django_password_context(None) #ensure django settings are empty update_settings( PASSLIB_CONTEXT=Undef, PASSLIB_GET_CATEGORY=Undef, ) #unload module so it's re-run sys.modules.pop("passlib.ext.django.models", None)
def test_02_models_check_password(self): "test monkeypatched models.check_password()" # patch to use simple context utils.set_django_password_context(simple_context) self.assert_patched(context=simple_context) # check correct hashes pass self.assertTrue(dam.check_password(sample1, sample1_des)) self.assertTrue(dam.check_password(sample1, sample1_md5)) # check bad password fail w/ false self.assertFalse(dam.check_password('x', sample1_des)) self.assertFalse(dam.check_password('x', sample1_md5)) # and other hashes fail w/ error self.assertRaises(ValueError, dam.check_password, sample1, sample1_sha1) self.assertRaises(ValueError, dam.check_password, sample1, None)
def patch(): #get config ctx = getattr(settings, "PASSLIB_CONTEXT", "passlib-default") catfunc = getattr(settings, "PASSLIB_GET_CATEGORY", get_category) #parse & validate input value if not ctx: # remove any patching that was already set, just in case. set_django_password_context(None) return if ctx == "passlib-default": ctx = DEFAULT_CTX if isinstance(ctx, (unicode, bytes)): ctx = CryptPolicy.from_string(ctx) if isinstance(ctx, CryptPolicy): ctx = CryptContext(policy=ctx) if not is_crypt_context(ctx): raise TypeError("django settings.PASSLIB_CONTEXT must be CryptContext instance or config string: %r" % (ctx,)) #monkeypatch django.contrib.auth.models:User set_django_password_context(ctx, get_category=catfunc)
def test_07_get_category(self): "test set_django_password_context's get_category parameter" # test patch uses default get_category utils.set_django_password_context(category_context) self.assertEquals(get_cc_rounds(), 1000) self.assertEquals(get_cc_rounds(is_staff=True), 2000) self.assertEquals(get_cc_rounds(is_superuser=True), 3000) # test patch uses explicit get_category def get_category(user): return user.first_name or None utils.set_django_password_context(category_context, get_category) self.assertEquals(get_cc_rounds(), 1000) self.assertEquals(get_cc_rounds(first_name='other'), 1000) self.assertEquals(get_cc_rounds(first_name='staff'), 2000) self.assertEquals(get_cc_rounds(first_name='superuser'), 3000) # test patch can disable get_category utils.set_django_password_context(category_context, None) self.assertEquals(get_cc_rounds(), 1000) self.assertEquals(get_cc_rounds(first_name='other'), 1000) self.assertEquals(get_cc_rounds(first_name='staff', is_staff=True), 1000) self.assertEquals( get_cc_rounds(first_name='superuser', is_superuser=True), 1000)
def test_00_patch_control(self): "test set_django_password_context patch/unpatch" #check context=None has no effect utils.set_django_password_context(None) self.assert_unpatched() #patch to use stock django context utils.set_django_password_context(django_context) self.assert_patched(context=django_context) #try to remove patch utils.set_django_password_context(None) self.assert_unpatched() #patch to use stock django context again utils.set_django_password_context(django_context) self.assert_patched(context=django_context) #try to remove patch again utils.set_django_password_context(None) self.assert_unpatched()
def patch(): #get config ctx = getattr(settings, "PASSLIB_CONTEXT", "passlib-default") catfunc = getattr(settings, "PASSLIB_GET_CATEGORY", get_category) #parse & validate input value if not ctx: # remove any patching that was already set, just in case. set_django_password_context(None) return if ctx == "passlib-default": ctx = DEFAULT_CTX if isinstance(ctx, (unicode, bytes)): ctx = CryptPolicy.from_string(ctx) if isinstance(ctx, CryptPolicy): ctx = CryptContext(policy=ctx) if not is_crypt_context(ctx): raise TypeError( "django settings.PASSLIB_CONTEXT must be CryptContext instance or config string: %r" % (ctx, )) #monkeypatch django.contrib.auth.models:User set_django_password_context(ctx, get_category=catfunc)
def test_01_patch_control_detection(self): "test set_django_password_context detection of foreign monkeypatches" def dummy(): pass with catch_warnings(record=True) as wlog: warnings.simplefilter("always") #patch to use stock django context utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 0) #mess with User.set_password, make sure it's detected dam.User.set_password = dummy utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 1) self.assertWarningMatches( wlog.pop(), message_re="^another library has patched.*User\.set_password$") #mess with user.check_password, make sure it's detected dam.User.check_password = dummy utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 1) self.assertWarningMatches( wlog.pop(), message_re="^another library has patched.*User\.check_password$" ) #mess with user.check_password, make sure it's detected dam.check_password = dummy utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 1) self.assertWarningMatches( wlog.pop(), message_re= "^another library has patched.*models:check_password$")
def test_01_patch_control_detection(self): "test set_django_password_context detection of foreign monkeypatches" def dummy(): pass with catch_warnings(record=True) as wlog: warnings.simplefilter("always") #patch to use stock django context utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 0) #mess with User.set_password, make sure it's detected dam.User.set_password = dummy utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 1) self.assertWarningMatches(wlog.pop(), message_re="^another library has patched.*User\.set_password$") #mess with user.check_password, make sure it's detected dam.User.check_password = dummy utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 1) self.assertWarningMatches(wlog.pop(), message_re="^another library has patched.*User\.check_password$") #mess with user.check_password, make sure it's detected dam.check_password = dummy utils.set_django_password_context(django_context) self.assert_patched(context=django_context) self.assertEquals(len(wlog), 1) self.assertWarningMatches(wlog.pop(), message_re="^another library has patched.*models:check_password$")
def test_07_get_category(self): "test set_django_password_context's get_category parameter" # test patch uses default get_category utils.set_django_password_context(category_context) self.assertEquals(get_cc_rounds(), 1000) self.assertEquals(get_cc_rounds(is_staff=True), 2000) self.assertEquals(get_cc_rounds(is_superuser=True), 3000) # test patch uses explicit get_category def get_category(user): return user.first_name or None utils.set_django_password_context(category_context, get_category) self.assertEquals(get_cc_rounds(), 1000) self.assertEquals(get_cc_rounds(first_name='other'), 1000) self.assertEquals(get_cc_rounds(first_name='staff'), 2000) self.assertEquals(get_cc_rounds(first_name='superuser'), 3000) # test patch can disable get_category utils.set_django_password_context(category_context, None) self.assertEquals(get_cc_rounds(), 1000) self.assertEquals(get_cc_rounds(first_name='other'), 1000) self.assertEquals(get_cc_rounds(first_name='staff', is_staff=True), 1000) self.assertEquals(get_cc_rounds(first_name='superuser', is_superuser=True), 1000)
def tearDown(self): #reset to baseline, and verify utils.set_django_password_context(None) self.assert_unpatched()
def tearDown(self): #remove django patch utils.set_django_password_context(None)