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 server_script = get_server_script_map().get("_api", {}).get(cmd) if server_script: return run_server_script(server_script) 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 uploadfile(): ret = None try: if frappe.form_dict.get("from_form"): try: ret = frappe.get_doc( { "doctype": "File", "attached_to_name": frappe.form_dict.docname, "attached_to_doctype": frappe.form_dict.doctype, "attached_to_field": frappe.form_dict.docfield, "file_url": frappe.form_dict.file_url, "file_name": frappe.form_dict.filename, "is_private": frappe.utils.cint(frappe.form_dict.is_private), "content": frappe.form_dict.filedata, "decode": True, } ) ret.save() except frappe.DuplicateEntryError: # ignore pass ret = None frappe.db.rollback() else: if frappe.form_dict.get("method"): method = frappe.get_attr(frappe.form_dict.method) is_whitelisted(method) ret = method() except Exception: frappe.errprint(frappe.utils.get_traceback()) frappe.response["http_status_code"] = 500 ret = None return ret
def upload_file(): user = None if frappe.session.user == "Guest": if frappe.get_system_settings("allow_guests_to_upload_files"): ignore_permissions = True else: return else: user = frappe.get_doc("User", frappe.session.user) ignore_permissions = False files = frappe.request.files is_private = frappe.form_dict.is_private doctype = frappe.form_dict.doctype docname = frappe.form_dict.docname fieldname = frappe.form_dict.fieldname file_url = frappe.form_dict.file_url folder = frappe.form_dict.folder or "Home" method = frappe.form_dict.method filename = frappe.form_dict.file_name content = None if "file" in files: file = files["file"] content = file.stream.read() filename = file.filename frappe.local.uploaded_file = content frappe.local.uploaded_filename = filename if not file_url and (frappe.session.user == "Guest" or (user and not user.has_desk_access())): import mimetypes filetype = mimetypes.guess_type(filename)[0] if filetype not in ALLOWED_MIMETYPES: frappe.throw(_("You can only upload JPG, PNG, PDF, TXT or Microsoft documents.")) if method: method = frappe.get_attr(method) is_whitelisted(method) return method() else: ret = frappe.get_doc( { "doctype": "File", "attached_to_doctype": doctype, "attached_to_name": docname, "attached_to_field": fieldname, "folder": folder, "file_name": filename, "file_url": file_url, "is_private": cint(is_private), "content": content, } ) ret.save(ignore_permissions=ignore_permissions) return ret
def run_doc_method(method, docs=None, dt=None, dn=None, arg=None, args=None): """run a whitelisted controller method""" import inspect import json if not args: args = arg or "" if dt: # not called from a doctype (from a page) if not dn: dn = dt # single doc = frappe.get_doc(dt, dn) else: if isinstance(docs, str): docs = json.loads(docs) doc = frappe.get_doc(docs) doc._original_modified = doc.modified doc.check_if_latest() if not doc or not doc.has_permission("read"): throw_permission_error() try: args = json.loads(args) except ValueError: args = args method_obj = getattr(doc, method) fn = getattr(method_obj, "__func__", method_obj) is_whitelisted(fn) is_valid_http_method(fn) fnargs = inspect.getfullargspec(method_obj).args if not fnargs or (len(fnargs) == 1 and fnargs[0] == "self"): response = doc.run_method(method) elif "args" in fnargs or not isinstance(args, dict): response = doc.run_method(method, args) else: response = doc.run_method(method, **args) frappe.response.docs.append(doc) if not response: return # build output as csv if cint(frappe.form_dict.get("as_csv")): build_csv_response(response, _(doc.doctype).replace(" ", "")) return frappe.response["message"] = response
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(_('Invalid Method')) 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 search_widget( doctype, txt, query=None, searchfield=None, start=0, page_length=20, filters=None, filter_fields=None, as_dict=False, reference_doctype=None, ignore_user_permissions=False, ): start = cint(start) 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 try: is_whitelisted(frappe.get_attr(query)) frappe.response["values"] = frappe.call( query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict ) except frappe.exceptions.PermissionError 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 except Exception as e: raise e 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 = [] translated_search_doctypes = frappe.get_hooks("translated_search_doctypes") # 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 translated_search_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("%", "").replace("@", "")), doctype=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) # 2 is the index of _relevance column order_by = "_relevance, {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype) ptype = "select" if frappe.only_has_select_perm(doctype) else "read" ignore_permissions = ( True if doctype == "DocType" else (cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype)) ) if doctype in translated_search_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, strict=False, ) if doctype in translated_search_doctypes: # Filtering the values array so that query is included in very element values = ( v for v in values if re.search(f"{re.escape(txt)}.*", _(v.name if as_dict else v[0]), re.IGNORECASE) ) # Sorting the values array so that relevant results always come first # This will first bring elements on top in which query is a prefix of element # Then it will bring the rest of the elements and sort them in lexicographical order values = sorted(values, key=lambda x: relevance_sorter(x, txt, as_dict)) # 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 is_whitelisted(self, method_name): method = getattr(self, method_name, None) if not method: raise NotFound("Method {0} not found".format(method_name)) is_whitelisted(getattr(method, '__func__', method))
def upload_file(): user = None if frappe.session.user == 'Guest': if frappe.get_system_settings('allow_guests_to_upload_files'): ignore_permissions = True else: return else: user = frappe.get_doc("User", frappe.session.user) ignore_permissions = False files = frappe.request.files is_private = frappe.form_dict.is_private doctype = frappe.form_dict.doctype docname = frappe.form_dict.docname fieldname = frappe.form_dict.fieldname file_url = frappe.form_dict.file_url folder = frappe.form_dict.folder or 'Home' method = frappe.form_dict.method filename = frappe.form_dict.file_name optimize = frappe.form_dict.optimize content = None if 'file' in files: file = files['file'] content = file.stream.read() filename = file.filename content_type = guess_type(filename)[0] if optimize and content_type.startswith("image/"): args = {"content": content, "content_type": content_type} if frappe.form_dict.max_width: args["max_width"] = int(frappe.form_dict.max_width) if frappe.form_dict.max_height: args["max_height"] = int(frappe.form_dict.max_height) content = optimize_image(**args) frappe.local.uploaded_file = content frappe.local.uploaded_filename = filename if not file_url and (frappe.session.user == "Guest" or (user and not user.has_desk_access())): filetype = guess_type(filename)[0] if filetype not in ALLOWED_MIMETYPES: frappe.throw( _("You can only upload JPG, PNG, PDF, or Microsoft documents.") ) if method: method = frappe.get_attr(method) is_whitelisted(method) return method() else: ret = frappe.get_doc({ "doctype": "File", "attached_to_doctype": doctype, "attached_to_name": docname, "attached_to_field": fieldname, "folder": folder, "file_name": filename, "file_url": file_url, "is_private": cint(is_private), "content": content }) ret.save(ignore_permissions=ignore_permissions) return ret