diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index de0c1e0e1c..b04af7bc7d 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -792,7 +792,7 @@ class BaseDocument(object): def _save_passwords(self): """Save password field values in __Auth table""" - from frappe.utils.password import set_encrypted_password + from frappe.utils.password import set_encrypted_password, remove_encrypted_password if self.flags.ignore_save_passwords is True: return @@ -800,6 +800,10 @@ class BaseDocument(object): for df in self.meta.get('fields', {'fieldtype': ('=', 'Password')}): if self.flags.ignore_save_passwords and df.fieldname in self.flags.ignore_save_passwords: continue new_password = self.get(df.fieldname) + + if not new_password: + remove_encrypted_password(self.doctype, self.name, df.fieldname) + if new_password and not self.is_dummy_password(new_password): # is not a dummy password like '*****' set_encrypted_password(self.doctype, self.name, new_password, df.fieldname) diff --git a/frappe/tests/test_password.py b/frappe/tests/test_password.py index 157fcc7b28..98141072e2 100644 --- a/frappe/tests/test_password.py +++ b/frappe/tests/test_password.py @@ -94,6 +94,17 @@ class TestPassword(unittest.TestCase): self.assertTrue(not get_password_list(doc)) + def test_password_unset(self): + doc = self.make_email_account() + + doc.password = 'asdf' + doc.save() + self.assertEqual(doc.get_password(raise_exception=False), 'asdf') + + doc.password = '' + doc.save() + self.assertEqual(doc.get_password(raise_exception=False), None) + def get_password_list(doc): return frappe.db.sql("""SELECT `password` diff --git a/frappe/utils/password.py b/frappe/utils/password.py index 6a63fc39d7..fbed3cd8e7 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -65,6 +65,13 @@ def set_encrypted_password(doctype, name, pwd, fieldname='password'): raise e +def remove_encrypted_password(doctype, name, fieldname='password'): + frappe.db.sql( + 'DELETE FROM `__Auth` WHERE doctype = %s and name = %s and fieldname = %s', + values=[doctype, name, fieldname] + ) + + def check_password(user, pwd, doctype='User', fieldname='password', delete_tracker_cache=True): '''Checks if user and password are correct, else raises frappe.AuthenticationError'''