Migrate password hashing away from mysql password()
This is deprecated and needs to be replaced. Use passlib to hash, store, verify and upgrade as necessary. Includes patch to migrate existing passwords in a non-breaking way. Fixes #5195
This commit is contained in:
parent
116ac139cf
commit
e641ae70bd
6 changed files with 283 additions and 27 deletions
|
|
@ -215,7 +215,6 @@ CREATE TABLE `__Auth` (
|
|||
`name` VARCHAR(255) NOT NULL,
|
||||
`fieldname` VARCHAR(140) NOT NULL,
|
||||
`password` VARCHAR(255) NOT NULL,
|
||||
`salt` VARCHAR(140),
|
||||
`encrypted` INT(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`doctype`, `name`, `fieldname`)
|
||||
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
execute:frappe.db.sql("""update `tabPatch Log` set patch=replace(patch, '.4_0.', '.v4_0.')""") #2014-05-12
|
||||
|
||||
frappe.patches.v5_0.convert_to_barracuda_and_utf8mb4
|
||||
execute:frappe.utils.global_search.setup_global_search_table()
|
||||
frappe.patches.v8_0.update_global_search_table
|
||||
|
|
@ -205,4 +205,212 @@ frappe.patches.v10_0.refactor_social_login_keys
|
|||
frappe.patches.v10_0.enable_chat_by_default_within_system_settings
|
||||
frappe.patches.v10_0.remove_custom_field_for_disabled_domain
|
||||
execute:frappe.delete_doc("Page", "chat")
|
||||
|
||||
frappe.patches.v5_0.convert_to_barracuda_and_utf8mb4
|
||||
execute:frappe.utils.global_search.setup_global_search_table()
|
||||
frappe.patches.v8_0.update_global_search_table
|
||||
frappe.patches.v7_0.update_auth
|
||||
frappe.patches.v8_0.drop_in_dialog #2017-09-22
|
||||
frappe.patches.v7_2.remove_in_filter
|
||||
execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2017-09-22
|
||||
execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2018-02-20
|
||||
execute:frappe.reload_doc('core', 'doctype', 'docperm') #2017-03-03
|
||||
execute:frappe.reload_doc('core', 'doctype', 'module_def') #2017-09-22
|
||||
execute:frappe.reload_doc('core', 'doctype', 'version') #2017-04-01
|
||||
execute:frappe.reload_doc('core', 'doctype', 'activity_log')
|
||||
frappe.patches.v7_1.rename_scheduler_log_to_error_log
|
||||
frappe.patches.v6_1.rename_file_data
|
||||
frappe.patches.v7_0.re_route #2016-06-27
|
||||
frappe.patches.v8_0.drop_is_custom_from_docperm
|
||||
frappe.patches.v8_0.update_records_in_global_search #11-05-2017
|
||||
frappe.patches.v8_0.update_published_in_global_search
|
||||
execute:frappe.reload_doc('core', 'doctype', 'custom_docperm')
|
||||
execute:frappe.reload_doc('core', 'doctype', 'deleted_document')
|
||||
execute:frappe.reload_doc('core', 'doctype', 'domain_settings')
|
||||
frappe.patches.v8_0.rename_page_role_to_has_role #2017-03-16
|
||||
frappe.patches.v7_2.setup_custom_perms #2017-01-19
|
||||
frappe.patches.v8_0.set_user_permission_for_page_and_report #2017-03-20
|
||||
execute:frappe.reload_doc('core', 'doctype', 'role') #2017-05-23
|
||||
execute:frappe.reload_doc('core', 'doctype', 'user') #2017-10-27
|
||||
execute:frappe.reload_doc('custom', 'doctype', 'custom_field') #2015-10-19
|
||||
execute:frappe.reload_doc('core', 'doctype', 'page') #2013-13-26
|
||||
execute:frappe.reload_doc('core', 'doctype', 'report') #2014-06-03
|
||||
execute:frappe.reload_doc('core', 'doctype', 'translation') #2016-03-03
|
||||
execute:frappe.reload_doc('email', 'doctype', 'email_alert') #2014-07-15
|
||||
execute:frappe.reload_doc('desk', 'doctype', 'todo') #2014-12-31-1
|
||||
execute:frappe.reload_doc('custom', 'doctype', 'property_setter') #2014-12-31-1
|
||||
execute:frappe.reload_doc('core', 'doctype', 'patch_log') #2016-10-31
|
||||
execute:frappe.reload_doctype("File") # 2015-10-19
|
||||
execute:frappe.reload_doc('core', 'doctype', 'error_snapshot')
|
||||
execute:frappe.clear_cache()
|
||||
frappe.patches.v7_1.rename_scheduler_log_to_error_log
|
||||
frappe.patches.v7_1.sync_language_doctype
|
||||
frappe.patches.v7_0.rename_bulk_email_to_email_queue
|
||||
frappe.patches.v7_1.rename_chinese_language_codes
|
||||
|
||||
execute:frappe.db.sql("alter table `tabSessions` modify `user` varchar(255), engine=InnoDB")
|
||||
execute:frappe.db.sql("delete from `tabDocField` where parent='0'")
|
||||
frappe.patches.v4_0.change_varchar_length
|
||||
frappe.patches.v6_4.reduce_varchar_length
|
||||
frappe.patches.v5_2.change_checks_to_not_null
|
||||
frappe.patches.v6_9.int_float_not_null #2015-11-25
|
||||
frappe.patches.v5_0.v4_to_v5
|
||||
|
||||
frappe.patches.v5_0.remove_shopping_cart_app
|
||||
frappe.patches.v4_0.webnotes_to_frappe
|
||||
execute:frappe.permissions.reset_perms("Module Def")
|
||||
execute:import frappe.installer;frappe.installer.make_site_dirs() #2014-02-19
|
||||
frappe.patches.v4_0.rename_profile_to_user
|
||||
frappe.patches.v4_0.deprecate_control_panel
|
||||
frappe.patches.v4_0.remove_old_parent
|
||||
frappe.patches.v4_0.rename_sitemap_to_route
|
||||
frappe.patches.v4_0.website_sitemap_hierarchy
|
||||
frappe.patches.v4_0.remove_index_sitemap
|
||||
frappe.patches.v4_0.set_website_route_idx
|
||||
frappe.patches.v4_0.add_delete_permission
|
||||
frappe.patches.v4_0.set_todo_checked_as_closed
|
||||
frappe.patches.v4_0.private_backups
|
||||
frappe.patches.v4_0.set_module_in_report
|
||||
frappe.patches.v4_0.update_datetime
|
||||
frappe.patches.v4_0.file_manager_hooks
|
||||
execute:frappe.get_doc("User", "Guest").save()
|
||||
frappe.patches.v4_0.update_custom_field_insert_after
|
||||
frappe.patches.v4_0.deprecate_link_selects
|
||||
frappe.patches.v4_0.set_user_gravatar
|
||||
frappe.patches.v4_0.set_user_permissions
|
||||
frappe.patches.v4_0.create_custom_field_for_owner_match
|
||||
frappe.patches.v4_0.enable_scheduler_in_system_settings
|
||||
execute:frappe.db.sql("update tabReport set apply_user_permissions=1") #2014-06-03
|
||||
frappe.patches.v4_0.replace_deprecated_timezones
|
||||
execute:import frappe.website.render; frappe.website.render.clear_cache("login"); #2014-06-10
|
||||
frappe.patches.v4_0.fix_attach_field_file_url
|
||||
execute:frappe.permissions.reset_perms("User") #2015-03-24
|
||||
execute:frappe.db.sql("""delete from `tabUserRole` where ifnull(parentfield, '')='' or ifnull(`role`, '')=''""") #2014-08-18
|
||||
frappe.patches.v4_0.remove_user_owner_custom_field
|
||||
execute:frappe.delete_doc("DocType", "Website Template")
|
||||
execute:frappe.db.sql("""update `tabProperty Setter` set property_type='Text' where property in ('options', 'default')""") #2014-06-20
|
||||
frappe.patches.v4_1.enable_outgoing_email_settings
|
||||
execute:frappe.db.sql("""update `tabSingles` set `value`=`doctype` where `field`='name'""") #2014-07-04
|
||||
frappe.patches.v4_1.enable_print_as_pdf #2014-06-17
|
||||
execute:frappe.db.sql("""update `tabDocPerm` set email=1 where parent='User' and permlevel=0 and `role`='All' and `read`=1 and apply_user_permissions=1""") #2014-07-15
|
||||
execute:frappe.db.sql("""update `tabPrint Format` set print_format_type='Client' where ifnull(print_format_type, '')=''""") #2014-07-28
|
||||
frappe.patches.v4_1.file_manager_fix
|
||||
frappe.patches.v4_2.print_with_letterhead
|
||||
execute:frappe.delete_doc("DocType", "Control Panel", force=1)
|
||||
execute:frappe.reload_doc('website', 'doctype', 'web_form') #2014-09-04
|
||||
execute:frappe.reload_doc('website', 'doctype', 'web_form_field') #2014-09-04
|
||||
frappe.patches.v4_2.refactor_website_routing
|
||||
frappe.patches.v4_2.set_assign_in_doc
|
||||
frappe.patches.v4_3.remove_allow_on_submit_customization
|
||||
frappe.patches.v5_0.rename_table_fieldnames
|
||||
frappe.patches.v5_0.communication_parent
|
||||
frappe.patches.v5_0.clear_website_group_and_notifications
|
||||
execute:frappe.db.sql("""update tabComment set comment = substr(comment, 6, locate(":", comment)-6) where comment_type in ("Assigned", "Assignment Completed")""")
|
||||
execute:frappe.db.sql("update `tabComment` set comment_type='Comment' where comment_doctype='Blog Post' and ifnull(comment_type, '')=''")
|
||||
frappe.patches.v5_0.update_shared
|
||||
execute:frappe.reload_doc("core", "doctype", "docshare") #2015-07-21
|
||||
frappe.patches.v6_19.comment_feed_communication
|
||||
frappe.patches.v6_16.star_to_like
|
||||
frappe.patches.v5_0.bookmarks_to_stars
|
||||
frappe.patches.v5_0.style_settings_to_website_theme
|
||||
frappe.patches.v5_0.rename_ref_type_fieldnames
|
||||
frappe.patches.v5_0.fix_email_alert
|
||||
frappe.patches.v5_0.fix_null_date_datetime
|
||||
frappe.patches.v5_0.force_sync_website
|
||||
execute:frappe.delete_doc("DocType", "Tag")
|
||||
execute:frappe.db.sql("delete from `tabProperty Setter` where `property` in ('idx', '_idx')")
|
||||
frappe.patches.v5_0.move_scheduler_last_event_to_system_settings
|
||||
execute:frappe.db.sql("update tabUser set new_password='' where ifnull(new_password, '')!=''")
|
||||
frappe.patches.v5_0.fix_text_editor_file_urls
|
||||
frappe.patches.v5_0.modify_session
|
||||
frappe.patches.v5_0.expire_old_scheduler_logs
|
||||
execute:frappe.permissions.reset_perms("DocType")
|
||||
execute:frappe.db.sql("delete from `tabProperty Setter` where `property` = 'idx'")
|
||||
frappe.patches.v6_0.communication_status_and_permission
|
||||
frappe.patches.v6_0.make_task_log_folder
|
||||
frappe.patches.v6_0.document_type_rename
|
||||
frappe.patches.v6_0.fix_ghana_currency
|
||||
frappe.patches.v6_2.ignore_user_permissions_if_missing
|
||||
execute:frappe.db.sql("delete from tabSessions where user is null")
|
||||
frappe.patches.v6_2.rename_backup_manager
|
||||
execute:frappe.delete_doc("DocType", "Backup Manager")
|
||||
execute:frappe.db.sql("""update `tabCommunication` set parenttype=null, parent=null, parentfield=null""") #2015-10-22
|
||||
execute:frappe.permissions.reset_perms("Web Page")
|
||||
frappe.patches.v6_6.user_last_active
|
||||
frappe.patches.v6_6.fix_file_url
|
||||
frappe.patches.v6_11.rename_field_in_email_account
|
||||
frappe.patches.v7_0.create_private_file_folder
|
||||
frappe.patches.v6_15.remove_property_setter_for_previous_field #2015-12-29
|
||||
frappe.patches.v6_15.set_username
|
||||
execute:frappe.permissions.reset_perms("Error Snapshot")
|
||||
frappe.patches.v6_16.feed_doc_owner
|
||||
frappe.patches.v6_21.print_settings_repeat_header_footer
|
||||
frappe.patches.v6_24.set_language_as_code
|
||||
frappe.patches.v6_20x.update_insert_after
|
||||
finally:frappe.patches.v6_24.sync_desktop_icons
|
||||
frappe.patches.v6_20x.set_allow_draft_for_print
|
||||
frappe.patches.v6_20x.remove_roles_from_website_user
|
||||
frappe.patches.v7_0.set_user_fullname
|
||||
frappe.patches.v7_0.desktop_icons_hidden_by_admin_as_blocked
|
||||
frappe.patches.v7_0.add_communication_in_doc
|
||||
frappe.patches.v7_0.update_send_after_in_bulk_email
|
||||
execute:frappe.db.sql('''delete from `tabSingles` where doctype="Email Settings"''') # 2016-06-13
|
||||
execute:frappe.db.sql("delete from `tabWeb Page` where ifnull(template_path, '')!=''")
|
||||
frappe.patches.v7_0.rename_newsletter_list_to_email_group
|
||||
frappe.patches.v7_0.replace_upgrade_link_limit
|
||||
frappe.patches.v7_0.set_email_group
|
||||
frappe.patches.v7_1.setup_integration_services #2016-10-27
|
||||
frappe.patches.v7_1.rename_chinese_language_codes
|
||||
execute:frappe.core.doctype.language.language.update_language_names() # 2017-04-12
|
||||
execute:frappe.db.set_value("Print Settings", "Print Settings", "add_draft_heading", 1)
|
||||
frappe.patches.v7_0.cleanup_list_settings
|
||||
execute:frappe.db.set_default('language', '')
|
||||
frappe.patches.v7_1.refactor_integration_broker
|
||||
frappe.patches.v7_1.set_backup_limit
|
||||
frappe.patches.v7_2.set_doctype_engine
|
||||
frappe.patches.v7_2.merge_knowledge_base
|
||||
frappe.patches.v7_0.update_report_builder_json
|
||||
frappe.patches.v7_2.set_in_standard_filter_property #1
|
||||
frappe.patches.v8_0.drop_unwanted_indexes
|
||||
execute:frappe.db.sql("update tabCommunication set communication_date = creation where time(communication_date) = 0")
|
||||
frappe.patches.v7_2.fix_email_queue_recipient
|
||||
frappe.patches.v7_2.update_feedback_request # 2017-02-27
|
||||
execute:frappe.rename_doc('Country', 'Macedonia, Republic of', 'Macedonia', ignore_if_exists=True)
|
||||
execute:frappe.rename_doc('Country', 'Iran, Islamic Republic of', 'Iran', ignore_if_exists=True)
|
||||
execute:frappe.rename_doc('Country', 'Tanzania, United Republic of', 'Tanzania', ignore_if_exists=True)
|
||||
execute:frappe.rename_doc('Country', 'Syrian Arab Republic', 'Syria', ignore_if_exists=True)
|
||||
frappe.patches.v8_0.rename_listsettings_to_usersettings
|
||||
frappe.patches.v7_2.update_communications
|
||||
frappe.patches.v8_0.deprecate_integration_broker
|
||||
frappe.patches.v8_0.update_gender_and_salutation
|
||||
frappe.patches.v8_0.setup_email_inbox #2017-03-29
|
||||
frappe.patches.v8_0.newsletter_childtable_migrate
|
||||
execute:frappe.db.sql("delete from `tabDesktop Icon` where module_name='Communication'")
|
||||
execute:frappe.db.sql("update `tabDesktop Icon` set type='list' where _doctype='Communication'")
|
||||
frappe.patches.v8_0.fix_non_english_desktop_icons # 2017-04-12
|
||||
frappe.patches.v8_0.set_doctype_values_in_custom_role
|
||||
frappe.patches.v8_0.install_new_build_system_requirements
|
||||
frappe.patches.v8_0.set_currency_field_precision # 2017-05-09
|
||||
frappe.patches.v8_0.rename_print_to_printing
|
||||
frappe.patches.v7_1.disabled_print_settings_for_custom_print_format
|
||||
frappe.patches.v8_0.update_desktop_icons
|
||||
execute:frappe.db.sql('update tabReport set module="Desk" where name="ToDo"')
|
||||
frappe.patches.v8_1.enable_allow_error_traceback_in_system_settings
|
||||
frappe.patches.v8_1.update_format_options_in_auto_email_report
|
||||
frappe.patches.v8_1.delete_custom_docperm_if_doctype_not_exists
|
||||
frappe.patches.v8_5.delete_email_group_member_with_invalid_emails
|
||||
frappe.patches.v8_x.update_user_permission
|
||||
frappe.patches.v8_5.patch_event_colors
|
||||
frappe.patches.v8_10.delete_static_web_page_from_global_search
|
||||
frappe.patches.v9_1.add_sms_sender_name_as_parameters
|
||||
frappe.patches.v9_1.resave_domain_settings
|
||||
frappe.patches.v9_1.revert_domain_settings
|
||||
frappe.patches.v9_1.move_feed_to_activity_log
|
||||
execute:frappe.delete_doc('Page', 'data-import-tool', ignore_missing=True)
|
||||
frappe.patches.v10_0.reload_countries_and_currencies
|
||||
frappe.patches.v10_0.refactor_social_login_keys
|
||||
frappe.patches.v10_0.enable_chat_by_default_within_system_settings
|
||||
frappe.patches.v10_0.remove_custom_field_for_disabled_domain
|
||||
execute:frappe.delete_doc("Page", "chat")
|
||||
frappe.patches.v10_0.migrate_passwords_passlib
|
||||
frappe.patches.v11_0.drop_column_apply_user_permissions
|
||||
|
|
|
|||
21
frappe/patches/v10_0/migrate_passwords_passlib.py
Normal file
21
frappe/patches/v10_0/migrate_passwords_passlib.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import frappe
|
||||
from frappe.utils.password import LegacyPassword
|
||||
|
||||
|
||||
def execute():
|
||||
all_auths = frappe.db.sql("""SELECT `name`, `password`, `salt` FROM `__Auth`
|
||||
WHERE doctype='User' AND `fieldname`='password'""",
|
||||
as_dict=True
|
||||
)
|
||||
|
||||
for auth in all_auths:
|
||||
if auth.salt and auth.salt != "":
|
||||
pwd = LegacyPassword.hash(auth.password, salt=auth.salt.encode('UTF-8'))
|
||||
frappe.db.sql("""UPDATE `__Auth` SET `password`=%(pwd)s, `salt`=NULL
|
||||
WHERE `doctype`='User' AND `fieldname`='password' AND `name`=%(user)s""",
|
||||
{'pwd': pwd, 'user': auth.name}
|
||||
)
|
||||
|
||||
frappe.reload_doctype("User")
|
||||
|
||||
frappe.db.sql_ddl("""ALTER TABLE `__Auth` DROP COLUMN `salt`""")
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import unittest
|
||||
from frappe.utils.password import update_password, check_password
|
||||
from frappe.utils.password import update_password, check_password, passlibctx
|
||||
|
||||
class TestPassword(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
|
@ -52,14 +52,14 @@ class TestPassword(unittest.TestCase):
|
|||
|
||||
update_password(user, new_password)
|
||||
|
||||
auth = frappe.db.sql('''select `password`, `salt` from `__Auth`
|
||||
auth = frappe.db.sql('''select `password` from `__Auth`
|
||||
where doctype='User' and name=%s and fieldname="password"''', user, as_dict=True)[0]
|
||||
|
||||
# is not plain text
|
||||
self.assertTrue(auth.password != new_password)
|
||||
self.assertTrue(auth.salt)
|
||||
|
||||
# stored password = password(plain_text_password + salt)
|
||||
self.assertEqual(frappe.db.sql('select password(concat(%s, %s))', (new_password, auth.salt))[0][0], auth.password)
|
||||
# is valid hashing
|
||||
self.assertTrue(passlibctx.verify(new_password, auth.password))
|
||||
|
||||
self.assertTrue(check_password(user, new_password))
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,41 @@
|
|||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import string
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cstr, encode
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
from passlib.hash import pbkdf2_sha256, mysql41
|
||||
from passlib.registry import register_crypt_handler
|
||||
from passlib.context import CryptContext
|
||||
|
||||
|
||||
class LegacyPassword(pbkdf2_sha256):
|
||||
name = "frappe_legacy"
|
||||
ident = "$frappel$"
|
||||
|
||||
def _calc_checksum(self, secret):
|
||||
# check if this is a mysql hash
|
||||
# it is possible that we will generate a false positive if the users password happens to be 40 hex chars proceeded
|
||||
# by an * char, but this seems highly unlikely
|
||||
if not (secret[0] == "*" and len(secret) == 41 and all(c in string.hexdigits for c in secret[1:])):
|
||||
secret = mysql41.hash(secret + self.salt)
|
||||
return super(LegacyPassword, self)._calc_checksum(secret)
|
||||
|
||||
|
||||
register_crypt_handler(LegacyPassword, force=True)
|
||||
passlibctx = CryptContext(
|
||||
schemes=[
|
||||
"pbkdf2_sha256",
|
||||
"argon2",
|
||||
"frappe_legacy",
|
||||
],
|
||||
deprecated=[
|
||||
"frappe_legacy",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def get_decrypted_password(doctype, name, fieldname='password', raise_exception=True):
|
||||
auth = frappe.db.sql('''select `password` from `__Auth`
|
||||
|
|
@ -24,27 +55,24 @@ def set_encrypted_password(doctype, name, pwd, fieldname='password'):
|
|||
on duplicate key update `password`=%(pwd)s, encrypted=1""",
|
||||
{ 'doctype': doctype, 'name': name, 'fieldname': fieldname, 'pwd': encrypt(pwd) })
|
||||
|
||||
def check_password(user, pwd, doctype='User', fieldname='password'):
|
||||
def check_password(auth, pwd, doctype='User', fieldname='password'):
|
||||
'''Checks if user and password are correct, else raises frappe.AuthenticationError'''
|
||||
|
||||
auth = frappe.db.sql("""select name, `password`, salt from `__Auth`
|
||||
where doctype=%(doctype)s and name=%(name)s and fieldname=%(fieldname)s and encrypted=0
|
||||
and (
|
||||
(salt is null and `password`=password(%(pwd)s))
|
||||
or `password`=password(concat(%(pwd)s, salt))
|
||||
)""",{ 'doctype': doctype, 'name': user, 'fieldname': fieldname, 'pwd': pwd }, as_dict=True)
|
||||
auth = frappe.db.sql("""select name, `password` from `__Auth`
|
||||
where doctype=%(doctype)s and name=%(name)s and fieldname=%(fieldname)s and encrypted=0""",
|
||||
{'doctype': doctype, 'name': auth, 'fieldname': fieldname},
|
||||
as_dict=True
|
||||
)
|
||||
|
||||
if not auth:
|
||||
raise frappe.AuthenticationError('Incorrect User or Password')
|
||||
|
||||
salt = auth[0].salt
|
||||
if not salt:
|
||||
# sets salt and updates password
|
||||
update_password(user, pwd, doctype, fieldname)
|
||||
if not auth or not passlibctx.verify(pwd, auth[0].password):
|
||||
raise frappe.AuthenticationError(_('Incorrect User or Password'))
|
||||
|
||||
# lettercase agnostic
|
||||
user = auth[0].name
|
||||
|
||||
if not passlibctx.needs_update(auth[0].password):
|
||||
update_password(user, pwd, doctype, fieldname)
|
||||
|
||||
return user
|
||||
|
||||
def update_password(user, pwd, doctype='User', fieldname='password', logout_all_sessions=False):
|
||||
|
|
@ -57,12 +85,12 @@ def update_password(user, pwd, doctype='User', fieldname='password', logout_all_
|
|||
:param fieldname: fieldname (in given doctype) (for encryption)
|
||||
:param logout_all_session: delete all other session
|
||||
'''
|
||||
salt = frappe.generate_hash()
|
||||
frappe.db.sql("""insert into __Auth (doctype, name, fieldname, `password`, salt, encrypted)
|
||||
values (%(doctype)s, %(name)s, %(fieldname)s, password(concat(%(pwd)s, %(salt)s)), %(salt)s, 0)
|
||||
hashPwd = passlibctx.hash(pwd)
|
||||
frappe.db.sql("""insert into __Auth (doctype, name, fieldname, `password`, encrypted)
|
||||
values (%(doctype)s, %(name)s, %(fieldname)s, %(pwd)s, 0)
|
||||
on duplicate key update
|
||||
`password`=password(concat(%(pwd)s, %(salt)s)), salt=%(salt)s, encrypted=0""",
|
||||
{ 'doctype': doctype, 'name': user, 'fieldname': fieldname, 'pwd': pwd, 'salt': salt })
|
||||
`password`=%(pwd)s, encrypted=0""",
|
||||
{'doctype': doctype, 'name': user, 'fieldname': fieldname, 'pwd': hashPwd})
|
||||
|
||||
# clear all the sessions except current
|
||||
if logout_all_sessions:
|
||||
|
|
@ -95,7 +123,6 @@ def create_auth_table():
|
|||
`name` VARCHAR(255) NOT NULL,
|
||||
`fieldname` VARCHAR(140) NOT NULL,
|
||||
`password` VARCHAR(255) NOT NULL,
|
||||
`salt` VARCHAR(140),
|
||||
`encrypted` INT(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`doctype`, `name`, `fieldname`)
|
||||
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci""")
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ googlemaps
|
|||
mycli
|
||||
braintree
|
||||
future
|
||||
passlib
|
||||
google-api-python-client
|
||||
google-auth
|
||||
google-auth-httplib2
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue