You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

267 lines
6.9 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # License: MIT. See LICENSE
  3. from werkzeug.wrappers import Response
  4. import frappe
  5. import frappe.utils
  6. import frappe.sessions
  7. from frappe.utils import cint
  8. from frappe import _, is_whitelisted
  9. from frappe.utils.response import build_response
  10. from frappe.utils.csvutils import build_csv_response
  11. from frappe.utils.image import optimize_image
  12. from mimetypes import guess_type
  13. from frappe.core.doctype.server_script.server_script_utils import run_server_script_api
  14. ALLOWED_MIMETYPES = ('image/png', 'image/jpeg', 'application/pdf', 'application/msword',
  15. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  16. 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  17. 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet')
  18. def handle():
  19. """handle request"""
  20. cmd = frappe.local.form_dict.cmd
  21. data = None
  22. if cmd!='login':
  23. data = execute_cmd(cmd)
  24. # data can be an empty string or list which are valid responses
  25. if data is not None:
  26. if isinstance(data, Response):
  27. # method returns a response object, pass it on
  28. return data
  29. # add the response to `message` label
  30. frappe.response['message'] = data
  31. return build_response("json")
  32. def execute_cmd(cmd, from_async=False):
  33. """execute a request as python module"""
  34. for hook in frappe.get_hooks("override_whitelisted_methods", {}).get(cmd, []):
  35. # override using the first hook
  36. cmd = hook
  37. break
  38. # via server script
  39. if run_server_script_api(cmd):
  40. return None
  41. try:
  42. method = get_attr(cmd)
  43. except Exception as e:
  44. frappe.throw(_('Failed to get method for command {0} with {1}').format(cmd, e))
  45. if from_async:
  46. method = method.queue
  47. if method != run_doc_method:
  48. is_whitelisted(method)
  49. is_valid_http_method(method)
  50. return frappe.call(method, **frappe.form_dict)
  51. def is_valid_http_method(method):
  52. http_method = frappe.local.request.method
  53. if http_method not in frappe.allowed_http_methods_for_whitelisted_func[method]:
  54. throw_permission_error()
  55. def throw_permission_error():
  56. frappe.throw(_("Not permitted"), frappe.PermissionError)
  57. @frappe.whitelist(allow_guest=True)
  58. def version():
  59. return frappe.__version__
  60. @frappe.whitelist(allow_guest=True)
  61. def logout():
  62. frappe.local.login_manager.logout()
  63. frappe.db.commit()
  64. @frappe.whitelist(allow_guest=True)
  65. def web_logout():
  66. frappe.local.login_manager.logout()
  67. frappe.db.commit()
  68. frappe.respond_as_web_page(_("Logged Out"), _("You have been successfully logged out"),
  69. indicator_color='green')
  70. @frappe.whitelist()
  71. def uploadfile():
  72. ret = None
  73. try:
  74. if frappe.form_dict.get('from_form'):
  75. try:
  76. ret = frappe.get_doc({
  77. "doctype": "File",
  78. "attached_to_name": frappe.form_dict.docname,
  79. "attached_to_doctype": frappe.form_dict.doctype,
  80. "attached_to_field": frappe.form_dict.docfield,
  81. "file_url": frappe.form_dict.file_url,
  82. "file_name": frappe.form_dict.filename,
  83. "is_private": frappe.utils.cint(frappe.form_dict.is_private),
  84. "content": frappe.form_dict.filedata,
  85. "decode": True
  86. })
  87. ret.save()
  88. except frappe.DuplicateEntryError:
  89. # ignore pass
  90. ret = None
  91. frappe.db.rollback()
  92. else:
  93. if frappe.form_dict.get('method'):
  94. method = frappe.get_attr(frappe.form_dict.method)
  95. is_whitelisted(method)
  96. ret = method()
  97. except Exception:
  98. frappe.errprint(frappe.utils.get_traceback())
  99. frappe.response['http_status_code'] = 500
  100. ret = None
  101. return ret
  102. @frappe.whitelist(allow_guest=True)
  103. def upload_file():
  104. user = None
  105. if frappe.session.user == 'Guest':
  106. if frappe.get_system_settings('allow_guests_to_upload_files'):
  107. ignore_permissions = True
  108. else:
  109. return
  110. else:
  111. user = frappe.get_doc("User", frappe.session.user)
  112. ignore_permissions = False
  113. files = frappe.request.files
  114. is_private = frappe.form_dict.is_private
  115. doctype = frappe.form_dict.doctype
  116. docname = frappe.form_dict.docname
  117. fieldname = frappe.form_dict.fieldname
  118. file_url = frappe.form_dict.file_url
  119. folder = frappe.form_dict.folder or 'Home'
  120. method = frappe.form_dict.method
  121. filename = frappe.form_dict.file_name
  122. optimize = frappe.form_dict.optimize
  123. content = None
  124. if 'file' in files:
  125. file = files['file']
  126. content = file.stream.read()
  127. filename = file.filename
  128. content_type = guess_type(filename)[0]
  129. if optimize and content_type.startswith("image/"):
  130. args = {
  131. "content": content,
  132. "content_type": content_type
  133. }
  134. if frappe.form_dict.max_width:
  135. args["max_width"] = int(frappe.form_dict.max_width)
  136. if frappe.form_dict.max_height:
  137. args["max_height"] = int(frappe.form_dict.max_height)
  138. content = optimize_image(**args)
  139. frappe.local.uploaded_file = content
  140. frappe.local.uploaded_filename = filename
  141. if not file_url and (frappe.session.user == "Guest" or (user and not user.has_desk_access())):
  142. filetype = guess_type(filename)[0]
  143. if filetype not in ALLOWED_MIMETYPES:
  144. frappe.throw(_("You can only upload JPG, PNG, PDF, or Microsoft documents."))
  145. if method:
  146. method = frappe.get_attr(method)
  147. is_whitelisted(method)
  148. return method()
  149. else:
  150. ret = frappe.get_doc({
  151. "doctype": "File",
  152. "attached_to_doctype": doctype,
  153. "attached_to_name": docname,
  154. "attached_to_field": fieldname,
  155. "folder": folder,
  156. "file_name": filename,
  157. "file_url": file_url,
  158. "is_private": cint(is_private),
  159. "content": content
  160. })
  161. ret.save(ignore_permissions=ignore_permissions)
  162. return ret
  163. def get_attr(cmd):
  164. """get method object from cmd"""
  165. if '.' in cmd:
  166. method = frappe.get_attr(cmd)
  167. else:
  168. method = globals()[cmd]
  169. frappe.log("method:" + cmd)
  170. return method
  171. @frappe.whitelist(allow_guest=True)
  172. def ping():
  173. return "pong"
  174. def run_doc_method(method, docs=None, dt=None, dn=None, arg=None, args=None):
  175. """run a whitelisted controller method"""
  176. import json
  177. import inspect
  178. if not args:
  179. args = arg or ""
  180. if dt: # not called from a doctype (from a page)
  181. if not dn:
  182. dn = dt # single
  183. doc = frappe.get_doc(dt, dn)
  184. else:
  185. doc = frappe.get_doc(json.loads(docs))
  186. doc._original_modified = doc.modified
  187. doc.check_if_latest()
  188. if not doc or not doc.has_permission("read"):
  189. throw_permission_error()
  190. try:
  191. args = json.loads(args)
  192. except ValueError:
  193. args = args
  194. method_obj = getattr(doc, method)
  195. fn = getattr(method_obj, '__func__', method_obj)
  196. is_whitelisted(fn)
  197. is_valid_http_method(fn)
  198. fnargs = inspect.getfullargspec(method_obj).args
  199. if not fnargs or (len(fnargs)==1 and fnargs[0]=="self"):
  200. response = doc.run_method(method)
  201. elif "args" in fnargs or not isinstance(args, dict):
  202. response = doc.run_method(method, args)
  203. else:
  204. response = doc.run_method(method, **args)
  205. frappe.response.docs.append(doc)
  206. if not response:
  207. return
  208. # build output as csv
  209. if cint(frappe.form_dict.get('as_csv')):
  210. build_csv_response(response, doc.doctype.replace(' ', ''))
  211. return
  212. frappe.response['message'] = response
  213. # for backwards compatibility
  214. runserverobj = run_doc_method