25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

152 lines
4.5 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import json
  5. import frappe
  6. import frappe.handler
  7. import frappe.client
  8. from frappe.utils.response import build_response
  9. from frappe import _
  10. from six.moves.urllib.parse import urlparse, urlencode
  11. def handle():
  12. """
  13. Handler for `/api` methods
  14. ### Examples:
  15. `/api/method/{methodname}` will call a whitelisted method
  16. `/api/resource/{doctype}` will query a table
  17. examples:
  18. - `?fields=["name", "owner"]`
  19. - `?filters=[["Task", "name", "like", "%005"]]`
  20. - `?limit_start=0`
  21. - `?limit_page_length=20`
  22. `/api/resource/{doctype}/{name}` will point to a resource
  23. `GET` will return doclist
  24. `POST` will insert
  25. `PUT` will update
  26. `DELETE` will delete
  27. `/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method
  28. """
  29. validate_oauth()
  30. parts = frappe.request.path[1:].split("/",3)
  31. call = doctype = name = None
  32. if len(parts) > 1:
  33. call = parts[1]
  34. if len(parts) > 2:
  35. doctype = parts[2]
  36. if len(parts) > 3:
  37. name = parts[3]
  38. if call=="method":
  39. frappe.local.form_dict.cmd = doctype
  40. return frappe.handler.handle()
  41. elif call=="resource":
  42. if "run_method" in frappe.local.form_dict:
  43. method = frappe.local.form_dict.pop("run_method")
  44. doc = frappe.get_doc(doctype, name)
  45. doc.is_whitelisted(method)
  46. if frappe.local.request.method=="GET":
  47. if not doc.has_permission("read"):
  48. frappe.throw(_("Not permitted"), frappe.PermissionError)
  49. frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)})
  50. if frappe.local.request.method=="POST":
  51. if not doc.has_permission("write"):
  52. frappe.throw(_("Not permitted"), frappe.PermissionError)
  53. frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)})
  54. frappe.db.commit()
  55. else:
  56. if name:
  57. if frappe.local.request.method=="GET":
  58. doc = frappe.get_doc(doctype, name)
  59. if not doc.has_permission("read"):
  60. raise frappe.PermissionError
  61. frappe.local.response.update({"data": doc})
  62. if frappe.local.request.method=="PUT":
  63. data = json.loads(frappe.local.form_dict.data)
  64. doc = frappe.get_doc(doctype, name)
  65. if "flags" in data:
  66. del data["flags"]
  67. # Not checking permissions here because it's checked in doc.save
  68. doc.update(data)
  69. frappe.local.response.update({
  70. "data": doc.save().as_dict()
  71. })
  72. frappe.db.commit()
  73. if frappe.local.request.method=="DELETE":
  74. # Not checking permissions here because it's checked in delete_doc
  75. frappe.delete_doc(doctype, name, ignore_missing=False)
  76. frappe.local.response.http_status_code = 202
  77. frappe.local.response.message = "ok"
  78. frappe.db.commit()
  79. elif doctype:
  80. if frappe.local.request.method=="GET":
  81. if frappe.local.form_dict.get('fields'):
  82. frappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields'])
  83. frappe.local.form_dict.setdefault('limit_page_length', 20)
  84. frappe.local.response.update({
  85. "data": frappe.call(frappe.client.get_list,
  86. doctype, **frappe.local.form_dict)})
  87. if frappe.local.request.method=="POST":
  88. data = json.loads(frappe.local.form_dict.data)
  89. data.update({
  90. "doctype": doctype
  91. })
  92. frappe.local.response.update({
  93. "data": frappe.get_doc(data).insert().as_dict()
  94. })
  95. frappe.db.commit()
  96. else:
  97. raise frappe.DoesNotExistError
  98. else:
  99. raise frappe.DoesNotExistError
  100. return build_response("json")
  101. def validate_oauth():
  102. from frappe.oauth import get_url_delimiter
  103. form_dict = frappe.local.form_dict
  104. authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None
  105. if authorization_header and authorization_header[0].lower() == "bearer":
  106. from frappe.integrations.oauth2 import get_oauth_server
  107. token = authorization_header[1]
  108. r = frappe.request
  109. parsed_url = urlparse(r.url)
  110. access_token = { "access_token": token}
  111. uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
  112. http_method = r.method
  113. body = r.get_data()
  114. headers = r.headers
  115. required_scopes = frappe.db.get_value("OAuth Bearer Token", token, "scopes").split(get_url_delimiter())
  116. valid, oauthlib_request = get_oauth_server().verify_request(uri, http_method, body, headers, required_scopes)
  117. if valid:
  118. frappe.set_user(frappe.db.get_value("OAuth Bearer Token", token, "user"))
  119. frappe.local.form_dict = form_dict