diff --git a/frappe/__init__.py b/frappe/__init__.py index 573076f391..8624e8df2b 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ if sys.version[0] == '2': reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '11.1.28' +__version__ = '11.1.29' __title__ = "Frappe Framework" local = Local() @@ -187,15 +187,20 @@ def connect(site=None, db_name=None): local.db = Database(user=db_name or local.conf.db_name) set_user("Administrator") -def connect_read_only(): +def connect_replica(): from frappe.database import Database + user = local.conf.db_name + password = local.conf.db_password - local.read_only_db = Database(local.conf.slave_host, local.conf.slave_db_name, - local.conf.slave_db_password) + if local.conf.different_credentials_for_replica: + user = local.conf.replica_db_name + password = local.conf.replica_db_password + + local.replica_db = Database(host=local.conf.replica_host, user=user, password=password) # swap db connections - local.master_db = local.db - local.db = local.read_only_db + local.primary_db = local.db + local.db = local.replica_db def get_site_config(sites_path=None, site_path=None): """Returns `site_config.json` combined with `sites/common_site_config.json`. @@ -495,16 +500,17 @@ def whitelist(allow_guest=False, xss_safe=False): def read_only(): def innfn(fn): def wrapper_fn(*args, **kwargs): - if conf.use_slave_for_read_only: - connect_read_only() + if conf.read_from_replica: + connect_replica() + try: retval = fn(*args, **get_newargs(fn, kwargs)) except: raise finally: - if local and hasattr(local, 'master_db'): + if local and hasattr(local, 'primary_db'): local.db.close() - local.db = local.master_db + local.db = local.primary_db return retval return wrapper_fn diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 38d292e9b4..6523b0b1e5 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -152,3 +152,11 @@ def filter_dynamic_link_doctypes(doctype, txt, searchfield, start, page_len, fil valid_doctypes = [[doctype] for doctype in valid_doctypes] return valid_doctypes + +def set_link_title(doc): + if not doc.links: + return + for link in doc.links: + if not link.link_title: + linked_doc = frappe.get_doc(link.link_doctype, link.link_name) + link.link_title = linked_doc.get("title_field") or linked_doc.get("name") diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index bfd63d2f80..0d8eb661f3 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -15,6 +15,7 @@ from frappe.model.naming import make_autoname from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links from six import iteritems, string_types from past.builtins import cmp +from frappe.contacts.address_and_contact import set_link_title import functools @@ -39,6 +40,7 @@ class Address(Document): def validate(self): self.link_address() self.validate_reference() + set_link_title(self) deduplicate_dynamic_links(self) def link_address(self): diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index e1117be4d7..8c1d0b4ac4 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -10,6 +10,7 @@ from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_li from six import iteritems from past.builtins import cmp from frappe.model.naming import append_number_if_name_exists +from frappe.contacts.address_and_contact import set_link_title import functools @@ -31,6 +32,7 @@ class Contact(Document): if self.email_id: self.email_id = self.email_id.strip() self.set_user() + set_link_title(self) if self.email_id and not self.image: self.image = has_gravatar(self.email_id) diff --git a/frappe/core/doctype/prepared_report/prepared_report.py b/frappe/core/doctype/prepared_report/prepared_report.py index cc087ae784..e83a73d1ec 100644 --- a/frappe/core/doctype/prepared_report/prepared_report.py +++ b/frappe/core/doctype/prepared_report/prepared_report.py @@ -51,14 +51,14 @@ def run_background(prepared_report): instance.status = "Completed" instance.columns = json.dumps(result["columns"]) instance.report_end_time = frappe.utils.now() - instance.save() + instance.save(ignore_permissions=True) except Exception: frappe.log_error(frappe.get_traceback()) instance = frappe.get_doc("Prepared Report", prepared_report) instance.status = "Error" instance.error_message = frappe.get_traceback() - instance.save() + instance.save(ignore_permissions=True) frappe.publish_realtime( 'report_generated', diff --git a/frappe/desk/doctype/auto_repeat/auto_repeat.py b/frappe/desk/doctype/auto_repeat/auto_repeat.py index c2d04e4fce..8a90b011d8 100644 --- a/frappe/desk/doctype/auto_repeat/auto_repeat.py +++ b/frappe/desk/doctype/auto_repeat/auto_repeat.py @@ -34,9 +34,15 @@ class AutoRepeat(Document): validate_template(self.message or "") def before_submit(self): + start_date_copy = self.start_date + today_copy = add_days(today(), -1) + + if start_date_copy <= today_copy: + start_date_copy = today_copy + if not self.next_schedule_date: self.next_schedule_date = get_next_schedule_date( - self.start_date, self.frequency, self.repeat_on_day) + start_date_copy, self.frequency, self.repeat_on_day) def on_submit(self): self.update_auto_repeat_id() @@ -116,14 +122,15 @@ class AutoRepeat(Document): days = 60 if self.frequency in ['Daily', 'Weekly'] else 365 end_date_copy = add_days(today_copy, days) + start_date_copy = get_next_schedule_date(start_date_copy, self.frequency, self.repeat_on_day) while (getdate(start_date_copy) < getdate(end_date_copy)): - start_date_copy = get_next_schedule_date(start_date_copy, self.frequency, self.repeat_on_day) row = { "reference_document" : self.reference_document, "frequency" : self.frequency, "next_scheduled_date" : start_date_copy } schedule_details.append(row) + start_date_copy = get_next_schedule_date(start_date_copy, self.frequency, self.repeat_on_day) return schedule_details diff --git a/frappe/desk/doctype/auto_repeat/test_auto_repeat.py b/frappe/desk/doctype/auto_repeat/test_auto_repeat.py index 19cf039759..cf8ff610d5 100644 --- a/frappe/desk/doctype/auto_repeat/test_auto_repeat.py +++ b/frappe/desk/doctype/auto_repeat/test_auto_repeat.py @@ -8,7 +8,7 @@ import unittest import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field from frappe.desk.doctype.auto_repeat.auto_repeat import get_auto_repeat_entries, create_repeated_entries, disable_auto_repeat -from frappe.utils import today, add_days, getdate +from frappe.utils import today, add_days, getdate, add_months def add_custom_fields(): @@ -44,8 +44,8 @@ class TestAutoRepeat(unittest.TestCase): self.assertEqual(todo.get('description'), new_todo.get('description')) def test_monthly_auto_repeat(self): - start_date = '2018-01-01' - end_date = '2018-12-31' + start_date = today() + end_date = add_months(start_date, 12) todo = frappe.get_doc( dict(doctype='ToDo', description='test recurring todo', assigned_by='Administrator')).insert() @@ -103,7 +103,7 @@ def make_auto_repeat(**args): 'reference_document': args.reference_document or frappe.db.get_value('ToDo', {'docstatus': 1}, 'name'), 'frequency': args.frequency or 'Daily', 'start_date': args.start_date or add_days(today(), -1), - 'end_date': args.end_date or add_days(today(), 1), + 'end_date': args.end_date or add_days(today(), 2), 'submit_on_creation': args.submit_on_creation or 0, 'notify_by_email': args.notify or 0, 'recipients': args.recipients or "", diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index 0b4f1eb853..f697211ac3 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -253,7 +253,7 @@ def get_report_list(module, is_standard="No"): out.append({ "type": "report", "doctype": r.ref_doctype, - "is_query_report": 1 if r.report_type in ("Query Report", "Script Report") else 0, + "is_query_report": 1 if r.report_type in ("Query Report", "Script Report", "Custom Report") else 0, "label": _(r.name), "name": r.name }) diff --git a/frappe/geo/country_info.json b/frappe/geo/country_info.json index a3f039ca17..9656d62b5d 100644 --- a/frappe/geo/country_info.json +++ b/frappe/geo/country_info.json @@ -2329,6 +2329,7 @@ }, "Suriname": { "code": "sr", + "currency": "SRD", "currency_fraction": "Cent", "currency_fraction_units": 100, "currency_symbol": "$", diff --git a/frappe/integrations/doctype/ldap_settings/ldap_settings.json b/frappe/integrations/doctype/ldap_settings/ldap_settings.json index 6eb44a2db8..aa43b2e9d0 100644 --- a/frappe/integrations/doctype/ldap_settings/ldap_settings.json +++ b/frappe/integrations/doctype/ldap_settings/ldap_settings.json @@ -1,317 +1,363 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2016-09-22 04:16:48.829658", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "System", - "editable_grid": 1, + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2016-09-22 04:16:48.829658", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "System", + "editable_grid": 1, "fields": [ { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enabled", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Enabled", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ldap_server_url", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "LDAP Server Url", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "organizational_unit", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Organizational Unit", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_dn", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Base Distinguished Name (DN)", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "password", - "fieldtype": "Password", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Password for Base DN", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ldap_search_string", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "LDAP Search String", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ldap_first_name_field", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "LDAP First Name Field", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ldap_email_field", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "LDAP Email Field", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ldap_username_field", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "LDAP Username Field", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, + "fieldname": "enabled", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Enabled", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "ldap_server_url", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "LDAP Server Url", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "organizational_unit", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Organizational Unit", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "base_dn", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Base Distinguished Name (DN)", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "password", + "fieldtype": "Password", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Password for Base DN", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "section_break_5", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "ldap_search_string", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "LDAP Search String", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "ldap_first_name_field", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "LDAP First Name Field", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "ldap_email_field", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "LDAP Email Field", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "ldap_username_field", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "LDAP Username Field", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, "fieldname": "ldap_security", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "LDAP Security", "length": 0, "no_copy": 0, @@ -325,22 +371,28 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "default": "Off", "description": "", + "fetch_if_empty": 0, "fieldname": "ssl_tls_mode", "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "SSL/TLS Mode", "length": 0, "no_copy": 0, @@ -355,21 +407,27 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "default": "No", + "fetch_if_empty": 0, "fieldname": "require_trusted_certificate", "fieldtype": "Select", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Require Trusted Certificate", "length": 0, "no_copy": 0, @@ -384,53 +442,153 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "local_private_key_file", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Path to private Key File", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "local_server_certificate_file", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Path to Server Certificate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "local_ca_certs_file", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Path to CA Certs File", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 1, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2019-01-30 11:02:41.011412", - "modified_by": "Administrator", - "module": "Integrations", - "name": "LDAP Settings", - "name_case": "", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 1, + "is_submittable": 0, + "issingle": 1, + "istable": 0, + "max_attachments": 0, + "modified": "2019-04-29 10:56:42.322696", + "modified_by": "Administrator", + "module": "Integrations", + "name": "LDAP Settings", + "name_case": "", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 0, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 } - ], - "quick_entry": 0, - "read_only": 1, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 + ], + "quick_entry": 0, + "read_only": 1, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/frappe/integrations/doctype/ldap_settings/ldap_settings.py b/frappe/integrations/doctype/ldap_settings/ldap_settings.py index e12a6fce05..0a4d871be8 100644 --- a/frappe/integrations/doctype/ldap_settings/ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/ldap_settings.py @@ -5,56 +5,90 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import cstr from frappe.model.document import Document + class LDAPSettings(Document): def validate(self): if not self.flags.ignore_mandatory: - self.validate_ldap_credentails() + if self.ldap_search_string.endswith("={0}"): + if self.enabled: + connect_to_ldap(server_url=self.ldap_server_url, + base_dn=self.base_dn, + password=self.get_password(raise_exception=False), + ssl_tls_mode=self.ssl_tls_mode, + trusted_cert=self.require_trusted_certificate, + private_key_file=self.local_private_key_file, + server_cert_file=self.local_server_certificate_file, + ca_certs_file=self.local_ca_certs_file) + else: + frappe.throw(_("LDAP Search String needs to end with a placeholder, eg sAMAccountName={0}")) - def validate_ldap_credentails(self): - try: - import ldap - conn = ldap.initialize(self.ldap_server_url) - try: - if self.ssl_tls_mode == 'StartTLS': - conn.set_option(ldap.OPT_X_TLS_DEMAND, True) - if self.require_trusted_certificate == 'Yes': - conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND) - conn.start_tls_s() - except: - frappe.throw(_("StartTLS is not supported")) - conn.simple_bind_s(self.base_dn, self.get_password(raise_exception=False)) - except ImportError: - msg = """ -
- {{_("Seems ldap is not installed on system.
Guidelines to install ldap dependancies and python package")}}, - {{_("Click here")}}, -
- """ - frappe.throw(msg, title=_("LDAP Not Installed")) +def get_ldap_client_settings(): + #return the settings to be used on the client side. + result = { + "enabled": False + } + settings = frappe.get_doc("LDAP Settings") - except ldap.LDAPError: - conn.unbind_s() - frappe.throw(_("Incorrect UserId or Password")) + if settings and settings.enabled: + result["enabled"] = True + result["method"] = "frappe.integrations.doctype.ldap_settings.ldap_settings.login" + return result -def get_ldap_settings(): + +def connect_to_ldap(server_url, + base_dn, + password, + ssl_tls_mode, + trusted_cert, + private_key_file, + server_cert_file, + ca_certs_file): try: - settings = frappe.get_doc("LDAP Settings") + import ldap3 + import ssl + + if trusted_cert == 'Yes': + tls_configuration = ldap3.Tls(validate=ssl.CERT_REQUIRED, + version=ssl.PROTOCOL_TLSv1) + else: + tls_configuration = ldap3.Tls(validate=ssl.CERT_NONE, + version=ssl.PROTOCOL_TLSv1) + + if private_key_file: + tls_configuration.private_key_file = private_key_file + if server_cert_file: + tls_configuration.certificate_file = server_cert_file + if ca_certs_file: + tls_configuration.ca_certs_file = ca_certs_file + + server = ldap3.Server(host=server_url, + tls=tls_configuration) + bind_type = ldap3.AUTO_BIND_TLS_BEFORE_BIND if ssl_tls_mode == "StartTLS" else True + + conn = ldap3.Connection(server=server, + user=base_dn, + password=password, + auto_bind=bind_type, + read_only=True, + raise_exceptions=True) + + return conn + + except ImportError: + msg = _("Please Install the ldap3 library via pip to use ldap functionality.") + frappe.throw(msg, title=_("LDAP Not Installed")) + except ldap3.core.exceptions.LDAPInvalidCredentialsResult: + frappe.throw(_("Invalid Credentials")) + except Exception as ex: + frappe.throw(_(str(ex))) - settings.update({ - "method": "frappe.integrations.doctype.ldap_settings.ldap_settings.login" - }) - return settings - except Exception: - # this will return blank settings - return frappe._dict() @frappe.whitelist(allow_guest=True) def login(): - #### LDAP LOGIN LOGIC ##### + # LDAP LOGIN LOGIC args = frappe.form_dict user = authenticate_ldap_user(frappe.as_unicode(args.usr), frappe.as_unicode(args.pwd)) @@ -64,64 +98,57 @@ def login(): # because of a GET request! frappe.db.commit() -def authenticate_ldap_user(user=None, password=None): - dn = None + +def authenticate_ldap_user(user=None, + password=None): + params = {} - settings = get_ldap_settings() + settings = frappe.get_doc("LDAP Settings") + if settings and settings.enabled: + conn = connect_to_ldap(server_url=settings.ldap_server_url, + base_dn=settings.base_dn, + password=settings.get_password(raise_exception=False), + ssl_tls_mode=settings.ssl_tls_mode, + trusted_cert=settings.require_trusted_certificate, + private_key_file=settings.local_private_key_file, + server_cert_file=settings.local_server_certificate_file, + ca_certs_file=settings.local_ca_certs_file) - try: - import ldap - except: - msg = """ -
- {{_("Seems ldap is not installed on system.")}}
- {{_("Click here")}}, - {{_("Guidelines to install ldap dependancies and python")}} -
- """ - frappe.throw(msg, title=_("LDAP Not Installed")) + user_filter = settings.ldap_search_string.format(user) + conn.search(search_base=settings.organizational_unit, + search_filter="({0})".format(user_filter), + attributes=[settings.ldap_email_field, + settings.ldap_username_field, + settings.ldap_first_name_field]) - conn = ldap.initialize(settings.ldap_server_url) - - try: - try: - # set TLS settings for secure connection - if settings.ssl_tls_mode == 'StartTLS': - conn.set_option(ldap.OPT_X_TLS_DEMAND, True) - if settings.require_trusted_certificate == 'Yes': - conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND) - conn.start_tls_s() - except: - frappe.throw(_("StartTLS is not supported")) - - # simple_bind_s is synchronous binding to server, it takes two param DN and password - conn.simple_bind_s(settings.base_dn, settings.get_password(raise_exception=False)) - - #search for surnames beginning with a - #available options for how deep a search you want. - #LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL,LDAP_SCOPE_SUBTREE, - result = conn.search_s(settings.organizational_unit, ldap.SCOPE_SUBTREE, - settings.ldap_search_string.format(user)) - - for dn, r in result: - dn = cstr(dn) - params["email"] = cstr(r[settings.ldap_email_field][0]) - params["username"] = cstr(r[settings.ldap_username_field][0]) - params["first_name"] = cstr(r[settings.ldap_first_name_field][0]) - - if dn: - conn.simple_bind_s(dn, frappe.as_unicode(password)) + if len(conn.entries) > 0 and conn.entries[0]: + user = conn.entries[0] + params["email"] = str(user[settings.ldap_email_field]) + params["username"] = str(user[settings.ldap_username_field]) + params["first_name"] = str(user[settings.ldap_first_name_field]) + connect_to_ldap(server_url=settings.ldap_server_url, + base_dn=user.entry_dn, + password=frappe.as_unicode(password), + ssl_tls_mode=settings.ssl_tls_mode, + trusted_cert=settings.require_trusted_certificate, + private_key_file=settings.local_private_key_file, + server_cert_file=settings.local_server_certificate_file, + ca_certs_file=settings.local_ca_certs_file + ) return create_user(params) else: frappe.throw(_("Not a valid LDAP user")) + else: + frappe.throw(_("LDAP is not enabled.")) - except ldap.LDAPError: - conn.unbind_s() - frappe.throw(_("Incorrect UserId or Password")) def create_user(params): if frappe.db.exists("User", params["email"]): - return frappe.get_doc("User", params["email"]) + user = frappe.get_doc("User", params["email"]) + user.first_name = params["first_name"] + user.username = params["username"] + user.save(ignore_permissions=True) + return user else: params.update({ @@ -135,6 +162,5 @@ def create_user(params): }) user = frappe.get_doc(params).insert(ignore_permissions=True) - frappe.db.commit() return user diff --git a/frappe/patches/v11_0/create_contact_for_user.py b/frappe/patches/v11_0/create_contact_for_user.py index d5e9c87e8b..c91caf9189 100644 --- a/frappe/patches/v11_0/create_contact_for_user.py +++ b/frappe/patches/v11_0/create_contact_for_user.py @@ -6,6 +6,7 @@ import re def execute(): """ Create Contact for each User if not present """ frappe.reload_doc('contacts', 'doctype', 'contact') + frappe.reload_doc('core', 'doctype', 'dynamic_link') users = frappe.get_all('User', filters={"name": ('not in', 'Administrator, Guest')}, fields=["*"]) for user in users: diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index 86a99c970f..458f3efa6d 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -167,13 +167,12 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ } if(!me.df.only_select) { - if(frappe.model.can_create(doctype) - && me.df.fieldtype !== "Dynamic Link") { + if(frappe.model.can_create(doctype)) { // new item r.results.push({ label: "" + " " - + __("Create a new {0}", [__(me.df.options)]) + + __("Create a new {0}", [__(me.get_options())]) + "", value: "create_new__link_option", action: me.new_doc diff --git a/frappe/public/js/frappe/form/multi_select_dialog.js b/frappe/public/js/frappe/form/multi_select_dialog.js index 609cd8be80..3438c59a1f 100644 --- a/frappe/public/js/frappe/form/multi_select_dialog.js +++ b/frappe/public/js/frappe/form/multi_select_dialog.js @@ -19,6 +19,7 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ let me = this; this.page_length = 20; + this.start = 0; let fields = [ { @@ -55,7 +56,12 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ }, { fieldtype: "Section Break" }, { fieldtype: "HTML", fieldname: "results_area" }, - { fieldtype: "Button", fieldname: "make_new", label: __("Make a new " + me.doctype) } + { fieldtype: "Button", fieldname: "more_btn", label: __("More"), + click: function(){ + me.start += 20; + me.get_results(); + } + } ]); let doctype_plural = !this.doctype.endsWith('y') ? this.doctype + 's' @@ -65,25 +71,30 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ title: __("Select {0}", [(this.doctype=='[Select]') ? __("value") : __(doctype_plural)]), fields: fields, primary_action_label: __("Get Items"), + secondary_action_label: __("Make {0}", [me.doctype]), primary_action: function() { me.action(me.get_checked_values(), me.args); + }, + secondary_action: function(e) { + // If user wants to close the modal + if (e) { + frappe.route_options = {}; + + Object.keys(me.setters).forEach(function(setter) { + frappe.route_options[setter] = me.dialog.fields_dict[setter].get_value() || undefined; + }); + + frappe.new_doc(me.doctype, true); + } } }); this.$parent = $(this.dialog.body); this.$wrapper = this.dialog.fields_dict.results_area.$wrapper.append(`
`); - this.$results = this.$wrapper.find('.results'); - this.$make_new_btn = this.dialog.fields_dict.make_new.$wrapper; - this.$placeholder = $(`
- - -

No ${this.doctype} found

- -
-
`); + this.$results = this.$wrapper.find('.results'); + this.$results.append(this.make_list_row()); this.args = {}; @@ -94,6 +105,7 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ bind_events: function() { let me = this; + this.$results.on('click', '.list-item-container', function (e) { if (!$(e.target).is(':checkbox') && !$(e.target).is('a')) { $(this).find(':checkbox').trigger('click'); @@ -119,14 +131,6 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ me.get_results(); }, 300)); }); - - this.$parent.on('click', '.btn[data-fieldname="make_new"]', (e) => { - frappe.route_options = {}; - Object.keys(this.setters).forEach(function(setter) { - frappe.route_options[setter] = me.dialog.fields_dict[setter].get_value() || undefined; - }); - frappe.new_doc(this.doctype, true); - }); }, get_checked_values: function() { @@ -170,23 +174,21 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ render_result_list: function(results, more = 0) { var me = this; - this.$results.empty(); - if(results.length === 0) { - this.$make_new_btn.addClass('hide'); - this.$results.append(me.$placeholder); - return; - } - this.$make_new_btn.removeClass('hide'); - this.$results.append(this.make_list_row()); + var more_btn = me.dialog.fields_dict.more_btn.$wrapper; + if(results.length === 0) { + this.$results.empty(); + more_btn.hide(); + return; + } else { + more_btn.show(); + } + results.forEach((result) => { me.$results.append(me.make_list_row(result)); - }) - if (more) { - let message = __("Only {0} entries shown. Please filter for more specific results.", [this.page_length]); - me.$results.append($(`
${message}
`)); - } + }); + + this.$results.animate({scrollTop: me.$results.prop('scrollHeight')}, 500); }, get_results: function() { @@ -208,6 +210,7 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ txt: me.dialog.fields_dict["search_term"].get_value(), filters: filters, filter_fields: Object.keys(me.setters).concat([me.date_field]), + start: this.start, page_length: this.page_length + 1, query: this.get_query ? this.get_query().query : '', as_dict: 1 @@ -219,8 +222,8 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ args: args, callback: function(r) { let results = [], more = 0; - if(r.values.length) { - if(r.values.length > me.page_length){ + if (r.values.length) { + if (r.values.length > me.page_length) { r.values.pop(); more = 1; } @@ -241,7 +244,9 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ }); // Preselect oldest entry - results[0].checked = 1 + if (me.start < 1) { + results[0].checked = 1; + } } me.render_result_list(results, more); } diff --git a/frappe/public/js/frappe/views/reports/print_grid.html b/frappe/public/js/frappe/views/reports/print_grid.html index 12854e74f3..e99600c2e6 100644 --- a/frappe/public/js/frappe/views/reports/print_grid.html +++ b/frappe/public/js/frappe/views/reports/print_grid.html @@ -31,15 +31,17 @@ {% var value = col.fieldname ? row[col.fieldname] : row[col.id]; %} - {{ - col.formatter - ? col.formatter(row._index, col._index, value, col, row, true) - : col.format - ? col.format(value, row, col, data) - : col.docfield - ? frappe.format(value, col.docfield) - : value - }} + + {{ + col.formatter + ? col.formatter(row._index, col._index, value, col, row, true) + : col.format + ? col.format(value, row, col, data) + : col.docfield + ? frappe.format(value, col.docfield) + : value + }} + {% endif %} {% endfor %} diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index edebb11a43..938fe915c9 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -999,9 +999,11 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { change: () => { let doctype = d.get_value('doctype'); frappe.model.with_doctype(doctype, () => { - let fields = frappe.meta.get_docfields(doctype) + let options = frappe.meta.get_docfields(doctype) + .filter(frappe.model.is_value_type) .map(df => ({ label: df.label, value: df.fieldname })); - d.set_df_property('field', 'options', fields); + + d.set_df_property('field', 'options', options); }); } diff --git a/frappe/templates/includes/login/login.js b/frappe/templates/includes/login/login.js index dd0f57eb4c..992051bc45 100644 --- a/frappe/templates/includes/login/login.js +++ b/frappe/templates/includes/login/login.js @@ -66,7 +66,7 @@ login.bind_events = function() { } }); - {% if ldap_settings %} + {% if ldap_settings.enabled %} $(".btn-ldap-login").on("click", function(){ var args = {}; args.cmd = "{{ ldap_settings.method }}"; diff --git a/frappe/www/login.py b/frappe/www/login.py index c2f83e45c3..793b57d28a 100644 --- a/frappe/www/login.py +++ b/frappe/www/login.py @@ -8,7 +8,7 @@ from frappe.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_v import json from frappe import _ from frappe.auth import LoginManager -from frappe.integrations.doctype.ldap_settings.ldap_settings import get_ldap_settings +from frappe.integrations.doctype.ldap_settings.ldap_settings import get_ldap_client_settings from frappe.utils.password import get_decrypted_password from frappe.utils.html_utils import get_icon_html @@ -38,8 +38,7 @@ def get_context(context): "icon": icon }) context["social_login"] = True - - ldap_settings = get_ldap_settings() + ldap_settings = get_ldap_client_settings() context["ldap_settings"] = ldap_settings login_name_placeholder = [_("Email address")]