|
- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
- # License: MIT. See LICENSE
-
- from werkzeug.wrappers import Response
-
- import frappe
- import frappe.utils
- import frappe.sessions
- from frappe.utils import cint
- from frappe import _, is_whitelisted
- from frappe.utils.response import build_response
- from frappe.utils.csvutils import build_csv_response
- from frappe.utils.image import optimize_image
- from mimetypes import guess_type
- from frappe.core.doctype.server_script.server_script_utils import run_server_script_api
-
-
- ALLOWED_MIMETYPES = ('image/png', 'image/jpeg', 'application/pdf', 'application/msword',
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
- 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
- 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet')
-
-
- def handle():
- """handle request"""
-
- cmd = frappe.local.form_dict.cmd
- data = None
-
- if cmd!='login':
- data = execute_cmd(cmd)
-
- # data can be an empty string or list which are valid responses
- if data is not None:
- if isinstance(data, Response):
- # method returns a response object, pass it on
- return data
-
- # add the response to `message` label
- frappe.response['message'] = data
-
- return build_response("json")
-
- 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 is_valid_http_method(method):
- http_method = frappe.local.request.method
-
- if http_method not in frappe.allowed_http_methods_for_whitelisted_func[method]:
- throw_permission_error()
-
- def throw_permission_error():
- frappe.throw(_("Not permitted"), frappe.PermissionError)
-
- @frappe.whitelist(allow_guest=True)
- def version():
- return frappe.__version__
-
- @frappe.whitelist(allow_guest=True)
- def logout():
- frappe.local.login_manager.logout()
- frappe.db.commit()
-
- @frappe.whitelist(allow_guest=True)
- def web_logout():
- frappe.local.login_manager.logout()
- frappe.db.commit()
- frappe.respond_as_web_page(_("Logged Out"), _("You have been successfully logged out"),
- indicator_color='green')
-
- @frappe.whitelist()
- 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
-
- @frappe.whitelist(allow_guest=True)
- 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
-
-
- def get_attr(cmd):
- """get method object from cmd"""
- if '.' in cmd:
- method = frappe.get_attr(cmd)
- else:
- method = globals()[cmd]
- frappe.log("method:" + cmd)
- return method
-
- @frappe.whitelist(allow_guest=True)
- def ping():
- return "pong"
-
-
- def run_doc_method(method, docs=None, dt=None, dn=None, arg=None, args=None):
- """run a whitelisted controller method"""
- import json
- import inspect
-
- 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:
- doc = frappe.get_doc(json.loads(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
-
- # for backwards compatibility
- runserverobj = run_doc_method
|