The license.txt file has been replaced with LICENSE for quite a while now. INAL but it didn't seem accurate to say "hey, checkout license.txt although there's no such file". Apart from this, there were inconsistencies in the headers altogether...this change brings consistency.
266 lines
6.9 KiB
Python
Executable file
266 lines
6.9 KiB
Python
Executable file
# 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
|