def run_custom_method(doctype, name, custom_method): """cmd=run_custom_method&doctype={doctype}&name={name}&custom_method={custom_method}""" doc = frappe.get_doc(doctype, name) if getattr(doc, custom_method, frappe._dict()).is_whitelisted: frappe.call(getattr(doc, custom_method), **frappe.local.form_dict) else: frappe.throw(_("Not permitted"), frappe.PermissionError)
def execute(self, filters=None): # TODO - Fix would be needed to not trigger multiple same reports for the one rendered on the Dashboard. # Also, Filters need to be streamlined. Processing happens on the front end. if self.data_source == 'Method': return frappe.call(self.method) if self.data_source == 'Report': report = get_report_doc(self.report) qry_filters = frappe._dict() if filters: filters = json.loads(filters) for fil in self.filter: for gt_fl in filters.keys(): if gt_fl == fil.filter_data_slice: qry_filters.update( {fil.mapped_filter_field: filters[gt_fl]}) if report.report_type == 'Report Builder': print(report.report_type) report_json = json.loads(report.json) report_fields = [rf[0] for rf in report_json.get('fields')] #frappe.local.form_dict.update(frappe._dict( vargs = frappe._dict(doctype=report.ref_doctype, fields=report_fields, filters=qry_filters or []) return compress(execute(**vargs), args=vargs) return generate_report_result(report=report, filters=qry_filters or []) return None
def execute_cmd(cmd): try: manage_user() method = get_attr(cmd) # check if method is whitelisted if frappe.session['user'] == 'Guest' and (method not in frappe.guest_methods): return get_response(message="Not Allowed", args={"http_status_code": 403}) elif not method in frappe.whitelisted: return get_response(message="Not Allowed", args={"http_status_code": 403}) else: args = get_json_request(frappe.local.form_dict.args) result = frappe.call(method, args) if result: if isinstance(result, dict): return get_response(message="Success", status_code=1, args=result) else: return get_response(message="Success", status_code=1) else: return get_response( message="Error occured, Please contact administrator") except Exception, e: raise e
def execute_cmd(cmd, from_async=False): """execute a request as python module""" for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []): # override using the first hook cmd = hook break # via server script if run_server_script_api(cmd): return None try: method = get_attr(cmd) except Exception as e: if frappe.local.conf.developer_mode: raise e else: frappe.respond_as_web_page(title='Invalid Method', html='Method not found', indicator_color='red', http_status_code=404) return if from_async: method = method.queue is_whitelisted(method) is_valid_http_method(method) return frappe.call(method, **frappe.form_dict)
def execute_cmd(cmd, from_async=False): """execute a request as python module""" for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []): # override using the first hook cmd = hook break # via server script if run_server_script_api(cmd): return None try: method = get_attr(cmd) except Exception as e: frappe.throw( _('Failed to get method for command {0} with {1}').format(cmd, e)) if from_async: method = method.queue if method != run_doc_method: is_whitelisted(method) is_valid_http_method(method) return frappe.call(method, **frappe.form_dict)
def call_custom_workflow_actions(doc, action): doc.last_workflow_action = action if custom_workflow_actions_map.get(doc.doctype).get(action): doc = frappe.call(custom_workflow_actions_map.get( doc.doctype).get(action), doc=doc) return doc
def has_controller_permissions(doc, ptype, user=None): if not user: user = frappe.session.user for method in frappe.get_hooks("has_permission").get(doc.doctype, []): if not frappe.call(frappe.get_attr(method), doc=doc, ptype=ptype, user=user): return False return True
def call(method, args=()): if args and isinstance(args, list) and isinstance(args[-1], dict): kwargs = args.pop() elif args and isinstance(args, dict): kwargs = args args = [] else: kwargs = {} return json.loads(frappe.as_json(frappe.call(method, *args, **kwargs)))
def get_permission_query_conditions(self): condition_methods = frappe.get_hooks("permission_query_conditions", {}).get(self.doctype, []) if condition_methods: conditions = [] for method in condition_methods: c = frappe.call(frappe.get_attr(method), self.user) if c: conditions.append(c) return " and ".join(conditions) if conditions else None
def get_context(context): """This is a controller extension for erpnext.templates.pages.cart""" context["no_cache"] = 1 settings = frappe.db.get("Awc Settings") awc_session = get_awc_session() context["countries"] = [ x for x in frappe.get_list( "Country", fields=["country_name", "name"], ignore_permissions=1) ] default_country = frappe.get_value("System Settings", "System Settings", "country") default_country_doc = next( (x for x in context["countries"] if x.name == default_country), None) if frappe.session.user != "Guest": context["addresses"] = frappe.get_all("Address", filters={ "customer": get_current_customer().name, "disabled": False }, fields="*") country_idx = context["countries"].index(default_country_doc) context["countries"].pop(country_idx) context["countries"] = [default_country_doc] + context["countries"] context["shipping_rate_api"] = frappe.get_hooks("shipping_rate_api")[0] context["selected_customer"] = awc_session.get("selected_customer") # remove? shipping is essential here anyways context.shipping_enabled = 1 if settings.awc_shipping_enabled else 0 # flag to display login form context.is_logged = awc.is_logged_in() login.apply_context(context) if context.is_logged: # load gateway provider into context gateway_provider = frappe.get_hooks('awc_gateway_form_provider') if gateway_provider and len(gateway_provider) > 0: context['gateway_provider'] = frappe.call( gateway_provider[0], context=dict(use_address_same_as=1, address_same_as_label="Same as Shipping Address", address_same_as_source="#awc-shipping-form")) awc.reset_shipping() return context
def login_user(): try: cmd = frappe.local.form_dict.cmd method = get_attr(cmd) ret = frappe.call(method, **frappe.form_dict) return ret except Exception, e: http_status_code = getattr(e, "status_code", 500) message = getattr(e, "message", 500) report_error(http_status_code,message)
def enqueue(method, queue='default', timeout=None, event=None, is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs): ''' Enqueue method to be executed using a background worker :param method: method string or method object :param queue: should be either long, default or short :param timeout: should be set according to the functions :param event: this is passed to enable clearing of jobs from queues :param is_async: if is_async=False, the method is executed immediately, else via a worker :param job_name: can be used to name an enqueue call, which can be used to prevent duplicate calls :param now: if now=True, the method is executed via frappe.call :param kwargs: keyword arguments to be passed to the method ''' # To handle older implementations if 'async' in kwargs: is_async = True del kwargs['async'] if now or frappe.flags.in_migrate: return frappe.call(method, **kwargs) q = get_queue(queue, is_async=is_async) if not timeout: timeout = queue_timeout.get(queue) or 300 queue_args = { "site": frappe.local.site, "user": frappe.session.user, "method": method, "event": event, "job_name": job_name or cstr(method), "is_async": is_async, "kwargs": kwargs } if enqueue_after_commit: if not frappe.flags.enqueue_after_commit: frappe.flags.enqueue_after_commit = [] frappe.flags.enqueue_after_commit.append({ "queue": queue, "is_async": is_async, "timeout": timeout, "queue_args": queue_args }) return frappe.flags.enqueue_after_commit else: return q.enqueue_call(execute_job, timeout=timeout, kwargs=queue_args)
def login_user(): try: cmd = frappe.local.form_dict.cmd method = get_attr(cmd) ret = frappe.call(method, **frappe.form_dict) return ret except Exception, e: http_status_code = getattr(e, "status_code", 500) message = getattr(e, "message", 500) report_error(http_status_code, message)
def has_controller_permissions(doc): if doc.get("__islocal"): doc = frappe.get_doc(doc) else: doc = frappe.get_doc(doc.doctype, doc.name) for method in frappe.get_hooks("has_permission:" + doc.doctype): if not frappe.call(frappe.get_attr(method), doc=doc): return False return True
def api_get_shipping_rates(items, address): hooks = frappe.get_hooks("awc_shipping_api") or {} result = [] for fn in hooks.get("get_rates", []): rates = frappe.call(fn, items=items, address=address) if isinstance(rates, list): result += rates elif isinstance(rates, tuple): result += list(rates) else: result += [rates] return rates
def wrapper(*args, **kwargs): # Do not apply rate limits if method is not opted to check if methods != 'ALL' and frappe.request.method.upper( ) not in methods: return frappe.call(fun, **frappe.form_dict) _limit = limit() if callable(limit) else limit identity = frappe.form_dict[key] cache_key = f"rl:{frappe.form_dict.cmd}:{identity}" value = frappe.cache().get_value(cache_key, expires=True) or 0 if not value: frappe.cache().set_value(cache_key, 0, expires_in_sec=seconds) value = frappe.cache().incrby(cache_key, 1) if value > _limit: frappe.throw( _("You hit the rate limit because of too many requests. Please try after sometime." )) return frappe.call(fun, **frappe.form_dict)
def has_consumer_access(consumer, update_log): """Checks if consumer has completely satisfied all the conditions on the doc""" if isinstance(consumer, str): consumer = frappe.get_doc('Event Consumer', consumer) if not frappe.db.exists(update_log.ref_doctype, update_log.docname): # Delete Log # Check if the last Update Log of this document was read by this consumer last_update_log = frappe.get_all('Event Update Log', filters={ 'ref_doctype': update_log.ref_doctype, 'docname': update_log.docname, 'creation': ['<', update_log.creation] }, order_by='creation desc', limit_page_length=1) if not len(last_update_log): return False last_update_log = frappe.get_doc('Event Update Log', last_update_log[0].name) return len([ x for x in last_update_log.consumers if x.consumer == consumer.name ]) doc = frappe.get_doc(update_log.ref_doctype, update_log.docname) try: for dt_entry in consumer.consumer_doctypes: if dt_entry.ref_doctype != update_log.ref_doctype: continue if not dt_entry.condition: return True condition: str = dt_entry.condition if condition.startswith('cmd:'): cmd = condition.split('cmd:')[1].strip() args = { 'consumer': consumer, 'doc': doc, 'update_log': update_log } return frappe.call(cmd, **args) else: return frappe.safe_eval(condition, frappe._dict(doc=doc)) except Exception as e: frappe.log_error(title='has_consumer_access error', message=e) return False
def call(fn, *args, **kwargs): """ Pass a doctype or a series of doctypes to get the count of docs in them Parameters: fn: frappe function to be called Returns: based on the function you call: output of the function you call Example: via terminal: bench --site erpnext.local execute frappe.utils.call --args '''["frappe.get_all", "Activity Log"]''' --kwargs '''{"fields": ["user", "creation", "full_name"], "filters":{"Operation": "Login", "Status": "Success"}, "limit": "10"}''' """ return json.loads(frappe.as_json(frappe.call(fn, *args, **kwargs)))
def has_controller_permissions(doc, ptype, user=None): """Returns controller permissions if defined. None if not defined""" if not user: user = frappe.session.user methods = frappe.get_hooks("has_permission").get(doc.doctype, []) if not methods: return None for method in methods: if not frappe.call(frappe.get_attr(method), doc=doc, ptype=ptype, user=user): return False return True
def has_controller_permissions(doc, ptype, user=None): """Returns controller permissions if defined. None if not defined""" if not user: user = frappe.session.user methods = frappe.get_hooks("has_permission").get(doc.doctype, []) if not methods: return None for method in methods: if not frappe.call( frappe.get_attr(method), doc=doc, ptype=ptype, user=user): return False return True
def call_awc_sync_hook(awc_session, quotation): awc = awc_session.get("cart") hooks = frappe.get_hooks("awc_sync_prepare") or [] if hooks: for awc_item in awc["items"]: quotation_item = None if quotation and awc_item.get("id"): quotation_item = next((itm for itm in quotation.get("items", []) if itm.get("name") == awc_item.get("id")), None) for method in hooks: frappe.call(method, awc_item=awc_item, quotation_item=quotation_item, quotation=quotation, awc_session=awc_session) hooks = frappe.get_hooks("awc_sync_with_quotation") or [] if hooks: for awc_item in awc["items"]: quotation_item = None if quotation and awc_item.get("id"): quotation_item = next((itm for itm in quotation.get("items", []) if itm.get("name") == awc_item.get("id")), None) for method in hooks: frappe.call(method, awc_item=awc_item, quotation_item=quotation_item, quotation=quotation, awc_session=awc_session)
def enqueue(method, queue='default', timeout=None, event=None, is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs): ''' Enqueue method to be executed using a background worker :param method: method string or method object :param queue: should be either long, default or short :param timeout: should be set according to the functions :param event: this is passed to enable clearing of jobs from queues :param is_async: if is_async=False, the method is executed immediately, else via a worker :param job_name: can be used to name an enqueue call, which can be used to prevent duplicate calls :param now: if now=True, the method is executed via frappe.call :param kwargs: keyword arguments to be passed to the method ''' # To handle older implementations if 'async' in kwargs: is_async = True del kwargs['async'] if now or frappe.flags.in_migrate: return frappe.call(method, **kwargs) q = get_queue(queue, is_async=is_async) if not timeout: timeout = queue_timeout.get(queue) or 300 queue_args = { "site": frappe.local.site, "user": frappe.session.user, "method": method, "event": event, "job_name": job_name or cstr(method), "is_async": is_async, "kwargs": kwargs } if enqueue_after_commit: if not frappe.flags.enqueue_after_commit: frappe.flags.enqueue_after_commit = [] frappe.flags.enqueue_after_commit.append({ "queue": queue, "is_async": is_async, "timeout": timeout, "queue_args":queue_args }) return frappe.flags.enqueue_after_commit else: return q.enqueue_call(execute_job, timeout=timeout, kwargs=queue_args)
def get_report(data): if not data: frappe.throw(_("There is no data for this Report.")) if isinstance(data, basestring): data = json.loads(unquote(data)) if data.get("origin") == "local": list_data = frappe.call(report_polling, data) if not list_data: frappe.throw("Your report was not found!. Please try again.") data = list_data[0] pformat = data.get("pformat") fileName, content, report_name = _get_report(data) return make_pdf(fileName, content, pformat, report_name, reqId=data.get("requestId"))
def get_awc_item_custom_data(name): """Returns a dictionary of custom key/values in the awc item""" if isinstance(name, str) or isinstance(name, unicode): awc_item = frappe.get_doc("AWC Item", name) else: awc_item = name custom_data = {} for custom in awc_item.get("custom_data"): custom_data[custom.key] = custom.value hooks = frappe.get_hooks("awc_item_custom_data") or [] if hooks: for method in hooks: result = frappe.call(method, custom_data) return custom_data
def execute_cmd(cmd, from_async=False): """execute a request as python module""" for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []): # override using the first hook cmd = hook break method = get_attr(cmd) if from_async: method = method.queue is_whitelisted(method) ret = frappe.call(method, **frappe.form_dict) # returns with a message if ret: frappe.response['message'] = ret
def test_validate_and_sanitize_search_inputs(self): # should raise error if searchfield is injectable self.assertRaises( frappe.DataError, get_data, *("User", "Random", "select * from tabSessions) --", "1", "10", dict())) # page_len and start should be converted to int self.assertListEqual( get_data("User", "Random", "email", "name or (select * from tabSessions)", "10", dict()), ["User", "Random", "email", 0, 10, {}], ) self.assertListEqual( get_data("User", "Random", "email", page_len="2", start="10", filters=dict()), ["User", "Random", "email", 10, 2, {}], ) # DocType can be passed as None which should be accepted self.assertListEqual( get_data(None, "Random", "email", "2", "10", dict()), [None, "Random", "email", 2, 10, {}]) # return empty string if passed doctype is invalid self.assertListEqual( get_data("Random DocType", "Random", "email", "2", "10", dict()), []) # should not fail if function is called via frappe.call with extra arguments args = ("Random DocType", "Random", "email", "2", "10", dict()) kwargs = {"as_dict": False} self.assertListEqual( frappe.call("frappe.tests.test_search.get_data", *args, **kwargs), []) # should not fail if query has @ symbol in it search_link("User", "user@random", searchfield="name") self.assertListEqual(frappe.response["results"], [])
def has_consumer_access(consumer, update_log): """Checks if consumer has completely satisfied all the conditions on the doc""" if isinstance(consumer, str): consumer = frappe.get_doc("Event Consumer", consumer) if not frappe.db.exists(update_log.ref_doctype, update_log.docname): # Delete Log # Check if the last Update Log of this document was read by this consumer last_update_log = frappe.get_all( "Event Update Log", filters={ "ref_doctype": update_log.ref_doctype, "docname": update_log.docname, "creation": ["<", update_log.creation], }, order_by="creation desc", limit_page_length=1, ) if not len(last_update_log): return False last_update_log = frappe.get_doc("Event Update Log", last_update_log[0].name) return len([x for x in last_update_log.consumers if x.consumer == consumer.name]) doc = frappe.get_doc(update_log.ref_doctype, update_log.docname) try: for dt_entry in consumer.consumer_doctypes: if dt_entry.ref_doctype != update_log.ref_doctype: continue if not dt_entry.condition: return True condition: str = dt_entry.condition if condition.startswith("cmd:"): cmd = condition.split("cmd:")[1].strip() args = {"consumer": consumer, "doc": doc, "update_log": update_log} return frappe.call(cmd, **args) else: return frappe.safe_eval(condition, frappe._dict(doc=doc)) except Exception as e: frappe.log_error(title="has_consumer_access error", message=e) return False
def execute_cmd(cmd): """execute a request as python module""" method = get_attr(cmd) # check if whitelisted if frappe.session['user'] == 'Guest': if (method not in frappe.guest_methods): frappe.msgprint(_("Not permitted")) raise frappe.PermissionError('Not Allowed, %s' % str(method)) else: if not method in frappe.whitelisted: frappe.msgprint(_("Not permitted")) raise frappe.PermissionError('Not Allowed, %s' % str(method)) ret = frappe.call(method, **frappe.form_dict) # returns with a message if ret: frappe.response['message'] = ret
def has_controller_permissions(doc, ptype, user=None): """Returns controller permissions if defined. None if not defined""" if not user: user = frappe.session.user methods = frappe.get_hooks("has_permission").get(doc.doctype, []) if not methods: return None for method in reversed(methods): controller_permission = frappe.call(frappe.get_attr(method), doc=doc, ptype=ptype, user=user) if controller_permission is not None: return controller_permission # controller permissions could not decide on True or False return None
def get_permission_query_conditions(self): conditions = [] condition_methods = frappe.get_hooks("permission_query_conditions", {}).get(self.doctype, []) if condition_methods: for method in condition_methods: c = frappe.call(frappe.get_attr(method), self.user) if c: conditions.append(c) permision_script_name = get_server_script_map().get( "permission_query", {}).get(self.doctype) if permision_script_name: script = frappe.get_doc("Server Script", permision_script_name) condition = script.get_permission_query_conditions(self.user) if condition: conditions.append(condition) return " and ".join(conditions) if conditions else ""
def execute_web_serices(): data = frappe.db.sql('''SELECT * FROM `tabScheduler Task` WHERE task_status = "Not Completed" ORDER BY creation ASC limit 5''', as_dict=1) if data: try: tasks = [] for task_data in data: method = get_attr(task_data.method_name) result = frappe.call(method, task_data.request_data) tasks.append("'%s'"%(task_data.name)) except Exception, e: # raise e print "finally",e finally:
def execute_cmd(cmd, from_async=False): """execute a request as python module""" for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []): # override using the first hook cmd = hook break try: method = get_attr(cmd) except: frappe.respond_as_web_page(title='Invalid Method', html='Method not found', indicator_color='red', http_status_code=404) return if from_async: method = method.queue is_whitelisted(method) return frappe.call(method, **frappe.form_dict)
def test_validate_and_sanitize_search_inputs(self): # should raise error if searchfield is injectable self.assertRaises( frappe.DataError, get_data, *('User', 'Random', 'select * from tabSessions) --', '1', '10', dict())) # page_len and start should be converted to int self.assertListEqual( get_data('User', 'Random', 'email', 'name or (select * from tabSessions)', '10', dict()), ['User', 'Random', 'email', 0, 10, {}]) self.assertListEqual( get_data('User', 'Random', 'email', page_len='2', start='10', filters=dict()), ['User', 'Random', 'email', 10, 2, {}]) # DocType can be passed as None which should be accepted self.assertListEqual( get_data(None, 'Random', 'email', '2', '10', dict()), [None, 'Random', 'email', 2, 10, {}]) # return empty string if passed doctype is invalid self.assertListEqual( get_data("Random DocType", 'Random', 'email', '2', '10', dict()), []) # should not fail if function is called via frappe.call with extra arguments args = ("Random DocType", 'Random', 'email', '2', '10', dict()) kwargs = {'as_dict': False} self.assertListEqual( frappe.call('frappe.tests.test_search.get_data', *args, **kwargs), []) # should not fail if query has @ symbol in it search_link('User', 'user@random', searchfield='name') self.assertListEqual(frappe.response['results'], [])
def has_consumer_access(consumer, update_log): """Checks if consumer has completely satisfied all the conditions on the doc""" if isinstance(consumer, str): consumer = frappe.get_doc('Event Consumer', consumer) if not frappe.db.exists(update_log.ref_doctype, update_log.docname): # Delete Log # Check if the last Update Log of this document was read by this consumer last_update_log = frappe.get_all( 'Event Update Log', filters={ 'ref_doctype': update_log.ref_doctype, 'docname': update_log.docname, 'creation': ['<', update_log.creation] }, order_by="creation desc", limit_page_length=1 ) if not len(last_update_log): return False last_update_log = frappe.get_doc( "Event Update Log", last_update_log[0].name) return len([x for x in last_update_log.consumers if x.consumer == consumer.name]) doc = frappe.get_doc(update_log.ref_doctype, update_log.docname) for dt_entry in consumer.consumer_doctypes: if dt_entry.ref_doctype != update_log.ref_doctype: continue if not dt_entry.condition: return True condition: str = dt_entry.condition if condition.startswith("cmd:"): return frappe.call(frappe.get_attr(condition.split("cmd:")[1].strip()), consumer=consumer, update_log=update_log) else: return frappe.safe_eval(condition.eval, frappe._dict(doc=doc)) return False
def execute_cmd(cmd): try: manage_user() method = get_attr(cmd) # check if method is whitelisted if frappe.session['user'] == 'Guest' and (method not in frappe.guest_methods): return get_response(message="Not Allowed", args={"http_status_code":403}) elif not method in frappe.whitelisted: return get_response(message="Not Allowed", args={"http_status_code":403}) else: args = get_json_request(frappe.local.form_dict.args) result = frappe.call(method, args) if result: if isinstance(result, dict): return get_response(message="Success", status_code=1, args=result) else: return get_response(message="Success", status_code=1) else: return get_response(message="Error occured, Please contact administrator") except Exception, e: raise e
def reset_website_customer(): settings = get_shopping_cart_settings() #flag order_for feature as disabled if stopped by the sales team user frappe.session.data.order_for['enabled'] = False customer_name = frappe.session.data.order_for.get("customer_name") if frappe.session.data.order_for.get("customer_name"): del frappe.session.data.order_for["customer_name"] if frappe.session.data.order_for.get("customer_primary_contact_name"): del frappe.session.data.order_for["customer_primary_contact_name"] if settings.get("stop_order_for_behavior") == "Reload": url = "Reload" if settings.get("stop_order_for_behavior" ) == "Back to Customer Record" and customer_name: url = "/desk#Form/Customer/{}".format(customer_name) else: url = settings.get("stop_order_for_url", "") or "Reload" # Hook: Allows overriding the routing url after a user resets the website customer # # Signature: # override_stop_order_for_url(url) # # Args: # url: The current route # # Returns: # Hook expects a string or None to override the route hooks = frappe.get_hooks("override_stop_order_for_url") or [] for method in hooks: url = frappe.call(method, url=url) or url if not url: url = "Reload" return url
def execute_cmd(cmd): """execute a request as python module""" method = get_attr(cmd) # check if whitelisted if frappe.session['user'] == 'Guest': if (method not in frappe.guest_methods): frappe.msgprint(_("Not permitted")) raise frappe.PermissionError('Not Allowed, %s' % str(method)) else: if not method in frappe.whitelisted: frappe.msgprint(_("Not permitted")) raise frappe.PermissionError('Not Allowed, %s' % str(method)) ret = frappe.call(method, **frappe.form_dict) # returns with a message if ret: frappe.response['message'] = ret # update session if "session_obj" in frappe.local: frappe.local.session_obj.update()
def execute_cmd(cmd): """execute a request as python module""" for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []): # override using the first hook cmd = hook break method = get_attr(cmd) # check if whitelisted if frappe.session['user'] == 'Guest': if (method not in frappe.guest_methods): frappe.msgprint(_("Not permitted")) raise frappe.PermissionError('Not Allowed, %s' % str(method)) else: if not method in frappe.whitelisted: frappe.msgprint(_("Not permitted")) raise frappe.PermissionError('Not Allowed, %s' % str(method)) ret = frappe.call(method, **frappe.form_dict) # returns with a message if ret: frappe.response['message'] = ret
def search_widget(doctype, txt, query=None, searchfield=None, start=0, page_length=10, filters=None, filter_fields=None, as_dict=False, reference_doctype=None, ignore_user_permissions=False): if isinstance(filters, string_types): filters = json.loads(filters) if searchfield: sanitize_searchfield(searchfield) if not searchfield: searchfield = "name" standard_queries = frappe.get_hooks().standard_queries or {} if query and query.split()[0].lower()!="select": # by method frappe.response["values"] = frappe.call(query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict) elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype][0], searchfield, start, page_length, filters) else: meta = frappe.get_meta(doctype) if query: frappe.throw(_("This query style is discontinued")) # custom query # frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters==None: filters = [] or_filters = [] # build from doctype if txt: search_fields = ["name"] if meta.title_field: search_fields.append(meta.title_field) if meta.search_fields: search_fields.extend(meta.get_search_fields()) for f in search_fields: fmeta = meta.get_field(f.strip()) if (doctype not in UNTRANSLATED_DOCTYPES) and (f == "name" or (fmeta and fmeta.fieldtype in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"])): or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)]) if meta.get("fields", {"fieldname":"enabled", "fieldtype":"Check"}): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", {"fieldname":"disabled", "fieldtype":"Check"}): filters.append([doctype, "disabled", "!=", 1]) # format a list of fields combining search fields and filter fields fields = get_std_fields_list(meta, searchfield or "name") if filter_fields: fields = list(set(fields + json.loads(filter_fields))) formatted_fields = ['`tab%s`.`%s`' % (meta.name, f.strip()) for f in fields] # find relevance as location of search term from the beginning of string `name`. used for sorting results. formatted_fields.append("""locate("{_txt}", `tab{doctype}`.`name`) as `_relevance`""".format( _txt=frappe.db.escape((txt or "").replace("%", "")), doctype=frappe.db.escape(doctype))) # In order_by, `idx` gets second priority, because it stores link count from frappe.model.db_query import get_order_by order_by_based_on_meta = get_order_by(doctype, meta) order_by = "if(_relevance, _relevance, 99999), {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype) ignore_permissions = True if doctype == "DocType" else (cint(ignore_user_permissions) and has_permission(doctype)) if doctype in UNTRANSLATED_DOCTYPES: page_length = None values = frappe.get_list(doctype, filters=filters, fields=formatted_fields, or_filters=or_filters, limit_start=start, limit_page_length=page_length, order_by=order_by, ignore_permissions=ignore_permissions, reference_doctype=reference_doctype, as_list=not as_dict) if doctype in UNTRANSLATED_DOCTYPES: values = tuple([v for v in list(values) if re.search(txt+".*", (_(v.name) if as_dict else _(v[0])), re.IGNORECASE)]) # remove _relevance from results if as_dict: for r in values: r.pop("_relevance") frappe.response["values"] = values else: frappe.response["values"] = [r[:-1] for r in values]
def execute_cmd(cmd, async=False): """execute a request as python module""" method = get_attr(cmd) try: #check if whitelisted if frappe.session['user'] == 'Guest': if (method not in frappe.guest_methods): return report_error(403,"Not Allowed") else: if not method in frappe.whitelisted: return report_error(403,"Not Allowed") ret = frappe.call(method, **frappe.form_dict) if isinstance(ret,dict): for key in ret: frappe.response[key] = ret[key] else: frappe.response["data"] = ret frappe.response["code"] = 200 except Exception, e: http_status_code = getattr(e, "status_code", 500) message = getattr(e, "message", 500) report_error(http_status_code,message) else: pass
def search_widget(doctype, txt, query=None, searchfield=None, start=0, page_len=10, filters=None, as_dict=False): if isinstance(filters, basestring): import json filters = json.loads(filters) meta = frappe.get_meta(doctype) if not searchfield: searchfield = "name" standard_queries = frappe.get_hooks().standard_queries or {} if query and query.split()[0].lower()!="select": # by method frappe.response["values"] = frappe.call(query, doctype, txt, searchfield, start, page_len, filters, as_dict=as_dict) elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype][0], searchfield, start, page_len, filters) else: if query: frappe.throw("This query style is discontinued") # custom query # frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters==None: filters = [] or_filters = [] # build from doctype if txt: search_fields = ["name"] if meta.title_field: search_fields.append(meta.title_field) if meta.search_fields: search_fields.extend(meta.get_search_fields()) for f in search_fields: fmeta = meta.get_field(f.strip()) if f == "name" or (fmeta and fmeta.fieldtype in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"]): or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)]) if meta.get("fields", {"fieldname":"enabled", "fieldtype":"Check"}): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", {"fieldname":"disabled", "fieldtype":"Check"}): filters.append([doctype, "disabled", "!=", 1]) fields = get_std_fields_list(meta, searchfield or "name") # find relevance as location of search term from the beginning of string `name`. used for sorting results. fields.append("""locate("{_txt}", `tab{doctype}`.`name`) as `_relevance`""".format( _txt=frappe.db.escape((txt or "").replace("%", "")), doctype=frappe.db.escape(doctype))) values = frappe.get_list(doctype, filters=filters, fields=fields, or_filters = or_filters, limit_start = start, limit_page_length=page_len, order_by="if(_relevance, _relevance, 99999), idx desc, modified desc".format(doctype), ignore_permissions = True if doctype == "DocType" else False, # for dynamic links as_list=not as_dict) # remove _relevance from results frappe.response["values"] = [r[:-1] for r in values]
def handle(): """ Handler for `/api` methods ### Examples: `/api/method/{methodname}` will call a whitelisted method `/api/resource/{doctype}` will query a table examples: - `?fields=["name", "owner"]` - `?filters=[["Task", "name", "like", "%005"]]` - `?limit_start=0` - `?limit_page_length=20` `/api/resource/{doctype}/{name}` will point to a resource `GET` will return doclist `POST` will insert `PUT` will update `DELETE` will delete `/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method """ form_dict = frappe.local.form_dict authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None if authorization_header and authorization_header[0].lower() == "bearer": token = authorization_header[1] r = frappe.request parsed_url = urlparse(r.url) access_token = { "access_token": token} uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token) http_method = r.method body = r.get_data() headers = r.headers required_scopes = frappe.db.get_value("OAuth Bearer Token", token, "scopes").split(";") valid, oauthlib_request = oauth_server.verify_request(uri, http_method, body, headers, required_scopes) if valid: frappe.set_user(frappe.db.get_value("OAuth Bearer Token", token, "user")) frappe.local.form_dict = form_dict parts = frappe.request.path[1:].split("/",3) call = doctype = name = None if len(parts) > 1: call = parts[1] if len(parts) > 2: doctype = parts[2] if len(parts) > 3: name = parts[3] if call=="method": frappe.local.form_dict.cmd = doctype return frappe.handler.handle() elif call=="resource": if "run_method" in frappe.local.form_dict: method = frappe.local.form_dict.pop("run_method") doc = frappe.get_doc(doctype, name) doc.is_whitelisted(method) if frappe.local.request.method=="GET": if not doc.has_permission("read"): frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)}) if frappe.local.request.method=="POST": if not doc.has_permission("write"): frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)}) frappe.db.commit() else: if name: if frappe.local.request.method=="GET": doc = frappe.get_doc(doctype, name) if not doc.has_permission("read"): raise frappe.PermissionError frappe.local.response.update({"data": doc}) if frappe.local.request.method=="PUT": data = json.loads(frappe.local.form_dict.data) doc = frappe.get_doc(doctype, name) if "flags" in data: del data["flags"] # Not checking permissions here because it's checked in doc.save doc.update(data) frappe.local.response.update({ "data": doc.save().as_dict() }) frappe.db.commit() if frappe.local.request.method=="DELETE": # Not checking permissions here because it's checked in delete_doc frappe.delete_doc(doctype, name) frappe.local.response.http_status_code = 202 frappe.local.response.message = "ok" frappe.db.commit() elif doctype: if frappe.local.request.method=="GET": if frappe.local.form_dict.get('fields'): frappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields']) frappe.local.form_dict.setdefault('limit_page_length', 20) frappe.local.response.update({ "data": frappe.call(frappe.client.get_list, doctype, **frappe.local.form_dict)}) if frappe.local.request.method=="POST": data = json.loads(frappe.local.form_dict.data) data.update({ "doctype": doctype }) frappe.local.response.update({ "data": frappe.get_doc(data).insert().as_dict() }) frappe.db.commit() else: raise frappe.DoesNotExistError else: raise frappe.DoesNotExistError return build_response("json")
def enqueue(method, queue='default', timeout=300, event=None, async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs): ''' Enqueue method to be executed using a background worker :param method: method string or method object :param queue: should be either long, default or short :param timeout: should be set according to the functions :param event: this is passed to enable clearing of jobs from queues :param async: if async=False, the method is executed immediately, else via a worker :param job_name: can be used to name an enqueue call, which can be used to prevent duplicate calls :param now: if now=True, the method is executed via frappe.call :param kwargs: keyword arguments to be passed to the method ''' if now or frappe.flags.in_migrate: return frappe.call(method, **kwargs) q = get_queue(queue, async=async) if not timeout: timeout = queue_timeout.get(queue) or 300 queue_args = { "site": frappe.local.site, "user": frappe.session.user, "method": method, "event": event, "job_name": job_name or cstr(method), "async": async, "kwargs": kwargs } if enqueue_after_commit: if not frappe.flags.enqueue_after_commit:
def handle(): """ Handler for `/api` methods ### Examples: `/api/method/{methodname}` will call a whitelisted method `/api/resource/{doctype}` will query a table examples: - `?fields=["name", "owner"]` - `?filters=[["Task", "name", "like", "%005"]]` - `?limit_start=0` - `?limit_page_length=20` `/api/resource/{doctype}/{name}` will point to a resource `GET` will return doclist `POST` will insert `PUT` will update `DELETE` will delete `/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method """ validate_oauth() parts = frappe.request.path[1:].split("/",3) call = doctype = name = None if len(parts) > 1: call = parts[1] if len(parts) > 2: doctype = parts[2] if len(parts) > 3: name = parts[3] if call=="method": frappe.local.form_dict.cmd = doctype return frappe.handler.handle() elif call=="resource": if "run_method" in frappe.local.form_dict: method = frappe.local.form_dict.pop("run_method") doc = frappe.get_doc(doctype, name) doc.is_whitelisted(method) if frappe.local.request.method=="GET": if not doc.has_permission("read"): frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)}) if frappe.local.request.method=="POST": if not doc.has_permission("write"): frappe.throw(_("Not permitted"), frappe.PermissionError) frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)}) frappe.db.commit() else: if name: if frappe.local.request.method=="GET": doc = frappe.get_doc(doctype, name) if not doc.has_permission("read"): raise frappe.PermissionError frappe.local.response.update({"data": doc}) if frappe.local.request.method=="PUT": data = json.loads(frappe.local.form_dict.data) doc = frappe.get_doc(doctype, name) if "flags" in data: del data["flags"] # Not checking permissions here because it's checked in doc.save doc.update(data) frappe.local.response.update({ "data": doc.save().as_dict() }) frappe.db.commit() if frappe.local.request.method=="DELETE": # Not checking permissions here because it's checked in delete_doc frappe.delete_doc(doctype, name) frappe.local.response.http_status_code = 202 frappe.local.response.message = "ok" frappe.db.commit() elif doctype: if frappe.local.request.method=="GET": if frappe.local.form_dict.get('fields'): frappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields']) frappe.local.form_dict.setdefault('limit_page_length', 20) frappe.local.response.update({ "data": frappe.call(frappe.client.get_list, doctype, **frappe.local.form_dict)}) if frappe.local.request.method=="POST": data = json.loads(frappe.local.form_dict.data) data.update({ "doctype": doctype }) frappe.local.response.update({ "data": frappe.get_doc(data).insert().as_dict() }) frappe.db.commit() else: raise frappe.DoesNotExistError else: raise frappe.DoesNotExistError return build_response("json")
def run_trigger(self, event='on_login'): for method in frappe.get_hooks().get(event, []): frappe.call(frappe.get_attr(method), login_manager=self)
def has_controller_permissions(doc): for method in frappe.get_hooks("has_permission").get(doc.doctype, []): if not frappe.call(frappe.get_attr(method), doc=doc): return False return True
def handle(): """ /api/method/{methodname} will call a whitelisted method /api/resource/{doctype} will query a table examples: ?fields=["name", "owner"] ?filters=[["Task", "name", "like", "%005"]] ?limit_start=0 ?limit_page_length=20 /api/resource/{doctype}/{name} will point to a resource GET will return doclist POST will insert PUT will update DELETE will delete /api/resource/{doctype}/{name}?run_method={method} will run a whitelisted controller method """ parts = frappe.request.path[1:].split("/",3) call = doctype = name = None if len(parts) > 1: call = parts[1] if len(parts) > 2: doctype = parts[2] if len(parts) > 3: name = parts[3] if call=="method": frappe.local.form_dict.cmd = doctype return frappe.handler.handle() elif call=="resource": if "run_method" in frappe.local.form_dict: method = frappe.local.form_dict.pop("run_method") doc = frappe.get_doc(doctype, name) doc.is_whitelisted(method) if frappe.local.request.method=="GET": if not doc.has_permission("read"): frappe.throw(_("Not permitted"), frappe.PermissionError) doc.run_method(method, **frappe.local.form_dict) if frappe.local.request.method=="POST": if not doc.has_permission("write"): frappe.throw(_("Not permitted"), frappe.PermissionError) doc.run_method(method, **frappe.local.form_dict) frappe.db.commit() else: if name: if frappe.local.request.method=="GET": doc = frappe.get_doc(doctype, name) if not doc.has_permission("read"): raise frappe.PermissionError frappe.local.response.update({"data": doc}) if frappe.local.request.method=="PUT": data = json.loads(frappe.local.form_dict.data) doc = frappe.get_doc(doctype, name) # Not checking permissions here because it's checked in doc.save doc.update(data) frappe.local.response.update({ "data": doc.save().as_dict() }) frappe.db.commit() if frappe.local.request.method=="DELETE": # Not checking permissions here because it's checked in delete_doc frappe.delete_doc(doctype, name) frappe.local.response.http_status_code = 202 frappe.local.response.message = "ok" frappe.db.commit() elif doctype: if frappe.local.request.method=="GET": if frappe.local.form_dict.get('fields'): frappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields']) frappe.local.response.update({ "data": frappe.call(frappe.widgets.reportview.execute, doctype, **frappe.local.form_dict)}) if frappe.local.request.method=="POST": data = json.loads(frappe.local.form_dict.data) data.update({ "doctype": doctype }) frappe.local.response.update({ "data": frappe.get_doc(data).insert().as_dict() }) frappe.db.commit() else: raise frappe.DoesNotExistError else: raise frappe.DoesNotExistError return build_response("json")