We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
bug(API): TypeError, cannot create document 

```bash
curl -X POST https://my.erpnext.com/api/resource/Lead \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==' \
  -H 'Content-Type: application/json' \
  -d '{"lead_name": "Jon Doe"}'
```

Returns

```json
{"exc":"[\"Traceback (most recent call last):\\n  File \\\"/home/frappe/frappe-bench/apps/frappe/frappe/app.py\\\", line 60, in application\\n    response = frappe.api.handle()\\n  File \\\"/home/frappe/frappe-bench/apps/frappe/frappe/api.py\\\", line 116, in handle\\n    data = json.loads(frappe.local.form_dict.data)\\n  File \\\"/usr/lib64/python2.7/json/__init__.py\\\", line 338, in loads\\n    return _default_decoder.decode(s)\\n  File \\\"/usr/lib64/python2.7/json/decoder.py\\\", line 366, in decode\\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\\nTypeError: expected string or buffer\\n\"]"}
```

Cleaned up stack trace:

```
Traceback (most recent call last):
File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 60, in application
	response = frappe.api.handle()
File "/home/frappe/frappe-bench/apps/frappe/frappe/api.py", line 116, in handle
	data = json.loads(frappe.local.form_dict.data)
File "/usr/lib64/python2.7/json/__init__.py", line 338, in loads
	return _default_decoder.decode(s)
File "/usr/lib64/python2.7/json/decoder.py", line 366, in decode
	obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: expected string or buffer
```

This seems to apply to any DocType – it's not possible to create documents this way.

@netchampfaris may [this](https://github.com/frappe/frappe/commit/f63ad574e580360996807931f9c9cfa363385c3d#diff-d65e8dff7122e8822cd2009d1ef1a963) be the cause?

### Versions
ERPNext: v12.0.6 (version-12)
Frappe Framework: v12.0.6 (version-12)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `frappe/api.py`
Content:
```
1 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2 # MIT License. See license.txt
3 from __future__ import unicode_literals
4 
5 import json
6 import frappe
7 import frappe.handler
8 import frappe.client
9 from frappe.utils.response import build_response
10 from frappe import _
11 from six.moves.urllib.parse import urlparse, urlencode
12 import base64
13 
14 def handle():
15 	"""
16 	Handler for `/api` methods
17 
18 	### Examples:
19 
20 	`/api/method/{methodname}` will call a whitelisted method
21 
22 	`/api/resource/{doctype}` will query a table
23 		examples:
24 		- `?fields=["name", "owner"]`
25 		- `?filters=[["Task", "name", "like", "%005"]]`
26 		- `?limit_start=0`
27 		- `?limit_page_length=20`
28 
29 	`/api/resource/{doctype}/{name}` will point to a resource
30 		`GET` will return doclist
31 		`POST` will insert
32 		`PUT` will update
33 		`DELETE` will delete
34 
35 	`/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method
36 	"""
37 
38 	validate_oauth()
39 	validate_auth_via_api_keys()
40 
41 	parts = frappe.request.path[1:].split("/",3)
42 	call = doctype = name = None
43 
44 	if len(parts) > 1:
45 		call = parts[1]
46 
47 	if len(parts) > 2:
48 		doctype = parts[2]
49 
50 	if len(parts) > 3:
51 		name = parts[3]
52 
53 	if call=="method":
54 		frappe.local.form_dict.cmd = doctype
55 		return frappe.handler.handle()
56 
57 	elif call=="resource":
58 		if "run_method" in frappe.local.form_dict:
59 			method = frappe.local.form_dict.pop("run_method")
60 			doc = frappe.get_doc(doctype, name)
61 			doc.is_whitelisted(method)
62 
63 			if frappe.local.request.method=="GET":
64 				if not doc.has_permission("read"):
65 					frappe.throw(_("Not permitted"), frappe.PermissionError)
66 				frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)})
67 
68 			if frappe.local.request.method=="POST":
69 				if not doc.has_permission("write"):
70 					frappe.throw(_("Not permitted"), frappe.PermissionError)
71 
72 				frappe.local.response.update({"data": doc.run_method(method, **frappe.local.form_dict)})
73 				frappe.db.commit()
74 
75 		else:
76 			if name:
77 				if frappe.local.request.method=="GET":
78 					doc = frappe.get_doc(doctype, name)
79 					if not doc.has_permission("read"):
80 						raise frappe.PermissionError
81 					frappe.local.response.update({"data": doc})
82 
83 				if frappe.local.request.method=="PUT":
84 					data = json.loads(frappe.local.form_dict.data)
85 					doc = frappe.get_doc(doctype, name)
86 
87 					if "flags" in data:
88 						del data["flags"]
89 
90 					# Not checking permissions here because it's checked in doc.save
91 					doc.update(data)
92 
93 					frappe.local.response.update({
94 						"data": doc.save().as_dict()
95 					})
96 					frappe.db.commit()
97 
98 				if frappe.local.request.method=="DELETE":
99 					# Not checking permissions here because it's checked in delete_doc
100 					frappe.delete_doc(doctype, name, ignore_missing=False)
101 					frappe.local.response.http_status_code = 202
102 					frappe.local.response.message = "ok"
103 					frappe.db.commit()
104 
105 
106 			elif doctype:
107 				if frappe.local.request.method=="GET":
108 					if frappe.local.form_dict.get('fields'):
109 						frappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields'])
110 					frappe.local.form_dict.setdefault('limit_page_length', 20)
111 					frappe.local.response.update({
112 						"data":  frappe.call(frappe.client.get_list,
113 							doctype, **frappe.local.form_dict)})
114 
115 				if frappe.local.request.method=="POST":
116 					data = json.loads(frappe.local.form_dict.data)
117 					data.update({
118 						"doctype": doctype
119 					})
120 					frappe.local.response.update({
121 						"data": frappe.get_doc(data).insert().as_dict()
122 					})
123 					frappe.db.commit()
124 			else:
125 				raise frappe.DoesNotExistError
126 
127 	else:
128 		raise frappe.DoesNotExistError
129 
130 	return build_response("json")
131 
132 def validate_oauth():
133 	from frappe.oauth import get_url_delimiter
134 	form_dict = frappe.local.form_dict
135 	authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None
136 	if authorization_header and authorization_header[0].lower() == "bearer":
137 		from frappe.integrations.oauth2 import get_oauth_server
138 		token = authorization_header[1]
139 		r = frappe.request
140 		parsed_url = urlparse(r.url)
141 		access_token = { "access_token": token}
142 		uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
143 		http_method = r.method
144 		body = r.get_data()
145 		headers = r.headers
146 
147 		required_scopes = frappe.db.get_value("OAuth Bearer Token", token, "scopes").split(get_url_delimiter())
148 
149 		valid, oauthlib_request = get_oauth_server().verify_request(uri, http_method, body, headers, required_scopes)
150 
151 		if valid:
152 			frappe.set_user(frappe.db.get_value("OAuth Bearer Token", token, "user"))
153 			frappe.local.form_dict = form_dict
154 
155 
156 def validate_auth_via_api_keys():
157 	"""
158 	authentication using api key and api secret
159 
160 	set user
161 	"""
162 	try:
163 		authorization_header = frappe.get_request_header("Authorization", None).split(" ") if frappe.get_request_header("Authorization") else None
164 		if authorization_header and authorization_header[0] == 'Basic':
165 			token = frappe.safe_decode(base64.b64decode(authorization_header[1])).split(":")
166 			validate_api_key_secret(token[0], token[1])
167 		elif authorization_header and authorization_header[0] == 'token':
168 			token = authorization_header[1].split(":")
169 			validate_api_key_secret(token[0], token[1])
170 	except Exception as e:
171 		raise e
172 
173 def validate_api_key_secret(api_key, api_secret):
174 	user = frappe.db.get_value(
175 		doctype="User",
176 		filters={"api_key": api_key},
177 		fieldname=['name']
178 	)
179 	form_dict = frappe.local.form_dict
180 	user_secret = frappe.utils.password.get_decrypted_password ("User", user, fieldname='api_secret')
181 	if api_secret == user_secret:
182 		frappe.set_user(user)
183 		frappe.local.form_dict = form_dict
184
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/frappe/api.py b/frappe/api.py
--- a/frappe/api.py
+++ b/frappe/api.py
@@ -113,7 +113,10 @@
 							doctype, **frappe.local.form_dict)})
 
 				if frappe.local.request.method=="POST":
-					data = json.loads(frappe.local.form_dict.data)
+					if frappe.local.form_dict.data is None:
+						data = json.loads(frappe.local.request.get_data())
+					else:
+						data = json.loads(frappe.local.form_dict.data)
 					data.update({
 						"doctype": doctype
 					})

{"golden_diff": "diff --git a/frappe/api.py b/frappe/api.py\n--- a/frappe/api.py\n+++ b/frappe/api.py\n@@ -113,7 +113,10 @@\n \t\t\t\t\t\t\tdoctype, **frappe.local.form_dict)})\n \n \t\t\t\tif frappe.local.request.method==\"POST\":\n-\t\t\t\t\tdata = json.loads(frappe.local.form_dict.data)\n+\t\t\t\t\tif frappe.local.form_dict.data is None:\n+\t\t\t\t\t\tdata = json.loads(frappe.local.request.get_data())\n+\t\t\t\t\telse:\n+\t\t\t\t\t\tdata = json.loads(frappe.local.form_dict.data)\n \t\t\t\t\tdata.update({\n \t\t\t\t\t\t\"doctype\": doctype\n \t\t\t\t\t})\n", "issue": "bug(API): TypeError, cannot create document \n\r\n```bash\r\ncurl -X POST https://my.erpnext.com/api/resource/Lead \\\r\n  -H 'Accept: application/json' \\\r\n  -H 'Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==' \\\r\n  -H 'Content-Type: application/json' \\\r\n  -d '{\"lead_name\": \"Jon Doe\"}'\r\n```\r\n\r\nReturns\r\n\r\n```json\r\n{\"exc\":\"[\\\"Traceback (most recent call last):\\\\n  File \\\\\\\"/home/frappe/frappe-bench/apps/frappe/frappe/app.py\\\\\\\", line 60, in application\\\\n    response = frappe.api.handle()\\\\n  File \\\\\\\"/home/frappe/frappe-bench/apps/frappe/frappe/api.py\\\\\\\", line 116, in handle\\\\n    data = json.loads(frappe.local.form_dict.data)\\\\n  File \\\\\\\"/usr/lib64/python2.7/json/__init__.py\\\\\\\", line 338, in loads\\\\n    return _default_decoder.decode(s)\\\\n  File \\\\\\\"/usr/lib64/python2.7/json/decoder.py\\\\\\\", line 366, in decode\\\\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\\\\nTypeError: expected string or buffer\\\\n\\\"]\"}\r\n```\r\n\r\nCleaned up stack trace:\r\n\r\n```\r\nTraceback (most recent call last):\r\nFile \"/home/frappe/frappe-bench/apps/frappe/frappe/app.py\", line 60, in application\r\n\tresponse = frappe.api.handle()\r\nFile \"/home/frappe/frappe-bench/apps/frappe/frappe/api.py\", line 116, in handle\r\n\tdata = json.loads(frappe.local.form_dict.data)\r\nFile \"/usr/lib64/python2.7/json/__init__.py\", line 338, in loads\r\n\treturn _default_decoder.decode(s)\r\nFile \"/usr/lib64/python2.7/json/decoder.py\", line 366, in decode\r\n\tobj, end = self.raw_decode(s, idx=_w(s, 0).end())\r\nTypeError: expected string or buffer\r\n```\r\n\r\nThis seems to apply to any DocType \u2013 it's not possible to create documents this way.\r\n\r\n@netchampfaris may [this](https://github.com/frappe/frappe/commit/f63ad574e580360996807931f9c9cfa363385c3d#diff-d65e8dff7122e8822cd2009d1ef1a963) be the cause?\r\n\r\n### Versions\r\nERPNext: v12.0.6 (version-12)\r\nFrappe Framework: v12.0.6 (version-12)\n", "before_files": [{"content": "# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors\n# MIT License. See license.txt\nfrom __future__ import unicode_literals\n\nimport json\nimport frappe\nimport frappe.handler\nimport frappe.client\nfrom frappe.utils.response import build_response\nfrom frappe import _\nfrom six.moves.urllib.parse import urlparse, urlencode\nimport base64\n\ndef handle():\n\t\"\"\"\n\tHandler for `/api` methods\n\n\t### Examples:\n\n\t`/api/method/{methodname}` will call a whitelisted method\n\n\t`/api/resource/{doctype}` will query a table\n\t\texamples:\n\t\t- `?fields=[\"name\", \"owner\"]`\n\t\t- `?filters=[[\"Task\", \"name\", \"like\", \"%005\"]]`\n\t\t- `?limit_start=0`\n\t\t- `?limit_page_length=20`\n\n\t`/api/resource/{doctype}/{name}` will point to a resource\n\t\t`GET` will return doclist\n\t\t`POST` will insert\n\t\t`PUT` will update\n\t\t`DELETE` will delete\n\n\t`/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method\n\t\"\"\"\n\n\tvalidate_oauth()\n\tvalidate_auth_via_api_keys()\n\n\tparts = frappe.request.path[1:].split(\"/\",3)\n\tcall = doctype = name = None\n\n\tif len(parts) > 1:\n\t\tcall = parts[1]\n\n\tif len(parts) > 2:\n\t\tdoctype = parts[2]\n\n\tif len(parts) > 3:\n\t\tname = parts[3]\n\n\tif call==\"method\":\n\t\tfrappe.local.form_dict.cmd = doctype\n\t\treturn frappe.handler.handle()\n\n\telif call==\"resource\":\n\t\tif \"run_method\" in frappe.local.form_dict:\n\t\t\tmethod = frappe.local.form_dict.pop(\"run_method\")\n\t\t\tdoc = frappe.get_doc(doctype, name)\n\t\t\tdoc.is_whitelisted(method)\n\n\t\t\tif frappe.local.request.method==\"GET\":\n\t\t\t\tif not doc.has_permission(\"read\"):\n\t\t\t\t\tfrappe.throw(_(\"Not permitted\"), frappe.PermissionError)\n\t\t\t\tfrappe.local.response.update({\"data\": doc.run_method(method, **frappe.local.form_dict)})\n\n\t\t\tif frappe.local.request.method==\"POST\":\n\t\t\t\tif not doc.has_permission(\"write\"):\n\t\t\t\t\tfrappe.throw(_(\"Not permitted\"), frappe.PermissionError)\n\n\t\t\t\tfrappe.local.response.update({\"data\": doc.run_method(method, **frappe.local.form_dict)})\n\t\t\t\tfrappe.db.commit()\n\n\t\telse:\n\t\t\tif name:\n\t\t\t\tif frappe.local.request.method==\"GET\":\n\t\t\t\t\tdoc = frappe.get_doc(doctype, name)\n\t\t\t\t\tif not doc.has_permission(\"read\"):\n\t\t\t\t\t\traise frappe.PermissionError\n\t\t\t\t\tfrappe.local.response.update({\"data\": doc})\n\n\t\t\t\tif frappe.local.request.method==\"PUT\":\n\t\t\t\t\tdata = json.loads(frappe.local.form_dict.data)\n\t\t\t\t\tdoc = frappe.get_doc(doctype, name)\n\n\t\t\t\t\tif \"flags\" in data:\n\t\t\t\t\t\tdel data[\"flags\"]\n\n\t\t\t\t\t# Not checking permissions here because it's checked in doc.save\n\t\t\t\t\tdoc.update(data)\n\n\t\t\t\t\tfrappe.local.response.update({\n\t\t\t\t\t\t\"data\": doc.save().as_dict()\n\t\t\t\t\t})\n\t\t\t\t\tfrappe.db.commit()\n\n\t\t\t\tif frappe.local.request.method==\"DELETE\":\n\t\t\t\t\t# Not checking permissions here because it's checked in delete_doc\n\t\t\t\t\tfrappe.delete_doc(doctype, name, ignore_missing=False)\n\t\t\t\t\tfrappe.local.response.http_status_code = 202\n\t\t\t\t\tfrappe.local.response.message = \"ok\"\n\t\t\t\t\tfrappe.db.commit()\n\n\n\t\t\telif doctype:\n\t\t\t\tif frappe.local.request.method==\"GET\":\n\t\t\t\t\tif frappe.local.form_dict.get('fields'):\n\t\t\t\t\t\tfrappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields'])\n\t\t\t\t\tfrappe.local.form_dict.setdefault('limit_page_length', 20)\n\t\t\t\t\tfrappe.local.response.update({\n\t\t\t\t\t\t\"data\":  frappe.call(frappe.client.get_list,\n\t\t\t\t\t\t\tdoctype, **frappe.local.form_dict)})\n\n\t\t\t\tif frappe.local.request.method==\"POST\":\n\t\t\t\t\tdata = json.loads(frappe.local.form_dict.data)\n\t\t\t\t\tdata.update({\n\t\t\t\t\t\t\"doctype\": doctype\n\t\t\t\t\t})\n\t\t\t\t\tfrappe.local.response.update({\n\t\t\t\t\t\t\"data\": frappe.get_doc(data).insert().as_dict()\n\t\t\t\t\t})\n\t\t\t\t\tfrappe.db.commit()\n\t\t\telse:\n\t\t\t\traise frappe.DoesNotExistError\n\n\telse:\n\t\traise frappe.DoesNotExistError\n\n\treturn build_response(\"json\")\n\ndef validate_oauth():\n\tfrom frappe.oauth import get_url_delimiter\n\tform_dict = frappe.local.form_dict\n\tauthorization_header = frappe.get_request_header(\"Authorization\").split(\" \") if frappe.get_request_header(\"Authorization\") else None\n\tif authorization_header and authorization_header[0].lower() == \"bearer\":\n\t\tfrom frappe.integrations.oauth2 import get_oauth_server\n\t\ttoken = authorization_header[1]\n\t\tr = frappe.request\n\t\tparsed_url = urlparse(r.url)\n\t\taccess_token = { \"access_token\": token}\n\t\turi = parsed_url.scheme + \"://\" + parsed_url.netloc + parsed_url.path + \"?\" + urlencode(access_token)\n\t\thttp_method = r.method\n\t\tbody = r.get_data()\n\t\theaders = r.headers\n\n\t\trequired_scopes = frappe.db.get_value(\"OAuth Bearer Token\", token, \"scopes\").split(get_url_delimiter())\n\n\t\tvalid, oauthlib_request = get_oauth_server().verify_request(uri, http_method, body, headers, required_scopes)\n\n\t\tif valid:\n\t\t\tfrappe.set_user(frappe.db.get_value(\"OAuth Bearer Token\", token, \"user\"))\n\t\t\tfrappe.local.form_dict = form_dict\n\n\ndef validate_auth_via_api_keys():\n\t\"\"\"\n\tauthentication using api key and api secret\n\n\tset user\n\t\"\"\"\n\ttry:\n\t\tauthorization_header = frappe.get_request_header(\"Authorization\", None).split(\" \") if frappe.get_request_header(\"Authorization\") else None\n\t\tif authorization_header and authorization_header[0] == 'Basic':\n\t\t\ttoken = frappe.safe_decode(base64.b64decode(authorization_header[1])).split(\":\")\n\t\t\tvalidate_api_key_secret(token[0], token[1])\n\t\telif authorization_header and authorization_header[0] == 'token':\n\t\t\ttoken = authorization_header[1].split(\":\")\n\t\t\tvalidate_api_key_secret(token[0], token[1])\n\texcept Exception as e:\n\t\traise e\n\ndef validate_api_key_secret(api_key, api_secret):\n\tuser = frappe.db.get_value(\n\t\tdoctype=\"User\",\n\t\tfilters={\"api_key\": api_key},\n\t\tfieldname=['name']\n\t)\n\tform_dict = frappe.local.form_dict\n\tuser_secret = frappe.utils.password.get_decrypted_password (\"User\", user, fieldname='api_secret')\n\tif api_secret == user_secret:\n\t\tfrappe.set_user(user)\n\t\tfrappe.local.form_dict = form_dict\n", "path": "frappe/api.py"}], "after_files": [{"content": "# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors\n# MIT License. See license.txt\nfrom __future__ import unicode_literals\n\nimport json\nimport frappe\nimport frappe.handler\nimport frappe.client\nfrom frappe.utils.response import build_response\nfrom frappe import _\nfrom six.moves.urllib.parse import urlparse, urlencode\nimport base64\n\ndef handle():\n\t\"\"\"\n\tHandler for `/api` methods\n\n\t### Examples:\n\n\t`/api/method/{methodname}` will call a whitelisted method\n\n\t`/api/resource/{doctype}` will query a table\n\t\texamples:\n\t\t- `?fields=[\"name\", \"owner\"]`\n\t\t- `?filters=[[\"Task\", \"name\", \"like\", \"%005\"]]`\n\t\t- `?limit_start=0`\n\t\t- `?limit_page_length=20`\n\n\t`/api/resource/{doctype}/{name}` will point to a resource\n\t\t`GET` will return doclist\n\t\t`POST` will insert\n\t\t`PUT` will update\n\t\t`DELETE` will delete\n\n\t`/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method\n\t\"\"\"\n\n\tvalidate_oauth()\n\tvalidate_auth_via_api_keys()\n\n\tparts = frappe.request.path[1:].split(\"/\",3)\n\tcall = doctype = name = None\n\n\tif len(parts) > 1:\n\t\tcall = parts[1]\n\n\tif len(parts) > 2:\n\t\tdoctype = parts[2]\n\n\tif len(parts) > 3:\n\t\tname = parts[3]\n\n\tif call==\"method\":\n\t\tfrappe.local.form_dict.cmd = doctype\n\t\treturn frappe.handler.handle()\n\n\telif call==\"resource\":\n\t\tif \"run_method\" in frappe.local.form_dict:\n\t\t\tmethod = frappe.local.form_dict.pop(\"run_method\")\n\t\t\tdoc = frappe.get_doc(doctype, name)\n\t\t\tdoc.is_whitelisted(method)\n\n\t\t\tif frappe.local.request.method==\"GET\":\n\t\t\t\tif not doc.has_permission(\"read\"):\n\t\t\t\t\tfrappe.throw(_(\"Not permitted\"), frappe.PermissionError)\n\t\t\t\tfrappe.local.response.update({\"data\": doc.run_method(method, **frappe.local.form_dict)})\n\n\t\t\tif frappe.local.request.method==\"POST\":\n\t\t\t\tif not doc.has_permission(\"write\"):\n\t\t\t\t\tfrappe.throw(_(\"Not permitted\"), frappe.PermissionError)\n\n\t\t\t\tfrappe.local.response.update({\"data\": doc.run_method(method, **frappe.local.form_dict)})\n\t\t\t\tfrappe.db.commit()\n\n\t\telse:\n\t\t\tif name:\n\t\t\t\tif frappe.local.request.method==\"GET\":\n\t\t\t\t\tdoc = frappe.get_doc(doctype, name)\n\t\t\t\t\tif not doc.has_permission(\"read\"):\n\t\t\t\t\t\traise frappe.PermissionError\n\t\t\t\t\tfrappe.local.response.update({\"data\": doc})\n\n\t\t\t\tif frappe.local.request.method==\"PUT\":\n\t\t\t\t\tdata = json.loads(frappe.local.form_dict.data)\n\t\t\t\t\tdoc = frappe.get_doc(doctype, name)\n\n\t\t\t\t\tif \"flags\" in data:\n\t\t\t\t\t\tdel data[\"flags\"]\n\n\t\t\t\t\t# Not checking permissions here because it's checked in doc.save\n\t\t\t\t\tdoc.update(data)\n\n\t\t\t\t\tfrappe.local.response.update({\n\t\t\t\t\t\t\"data\": doc.save().as_dict()\n\t\t\t\t\t})\n\t\t\t\t\tfrappe.db.commit()\n\n\t\t\t\tif frappe.local.request.method==\"DELETE\":\n\t\t\t\t\t# Not checking permissions here because it's checked in delete_doc\n\t\t\t\t\tfrappe.delete_doc(doctype, name, ignore_missing=False)\n\t\t\t\t\tfrappe.local.response.http_status_code = 202\n\t\t\t\t\tfrappe.local.response.message = \"ok\"\n\t\t\t\t\tfrappe.db.commit()\n\n\n\t\t\telif doctype:\n\t\t\t\tif frappe.local.request.method==\"GET\":\n\t\t\t\t\tif frappe.local.form_dict.get('fields'):\n\t\t\t\t\t\tfrappe.local.form_dict['fields'] = json.loads(frappe.local.form_dict['fields'])\n\t\t\t\t\tfrappe.local.form_dict.setdefault('limit_page_length', 20)\n\t\t\t\t\tfrappe.local.response.update({\n\t\t\t\t\t\t\"data\":  frappe.call(frappe.client.get_list,\n\t\t\t\t\t\t\tdoctype, **frappe.local.form_dict)})\n\n\t\t\t\tif frappe.local.request.method==\"POST\":\n\t\t\t\t\tif frappe.local.form_dict.data is None:\n\t\t\t\t\t\tdata = json.loads(frappe.local.request.get_data())\n\t\t\t\t\telse:\n\t\t\t\t\t\tdata = json.loads(frappe.local.form_dict.data)\n\t\t\t\t\tdata.update({\n\t\t\t\t\t\t\"doctype\": doctype\n\t\t\t\t\t})\n\t\t\t\t\tfrappe.local.response.update({\n\t\t\t\t\t\t\"data\": frappe.get_doc(data).insert().as_dict()\n\t\t\t\t\t})\n\t\t\t\t\tfrappe.db.commit()\n\t\t\telse:\n\t\t\t\traise frappe.DoesNotExistError\n\n\telse:\n\t\traise frappe.DoesNotExistError\n\n\treturn build_response(\"json\")\n\ndef validate_oauth():\n\tfrom frappe.oauth import get_url_delimiter\n\tform_dict = frappe.local.form_dict\n\tauthorization_header = frappe.get_request_header(\"Authorization\").split(\" \") if frappe.get_request_header(\"Authorization\") else None\n\tif authorization_header and authorization_header[0].lower() == \"bearer\":\n\t\tfrom frappe.integrations.oauth2 import get_oauth_server\n\t\ttoken = authorization_header[1]\n\t\tr = frappe.request\n\t\tparsed_url = urlparse(r.url)\n\t\taccess_token = { \"access_token\": token}\n\t\turi = parsed_url.scheme + \"://\" + parsed_url.netloc + parsed_url.path + \"?\" + urlencode(access_token)\n\t\thttp_method = r.method\n\t\tbody = r.get_data()\n\t\theaders = r.headers\n\n\t\trequired_scopes = frappe.db.get_value(\"OAuth Bearer Token\", token, \"scopes\").split(get_url_delimiter())\n\n\t\tvalid, oauthlib_request = get_oauth_server().verify_request(uri, http_method, body, headers, required_scopes)\n\n\t\tif valid:\n\t\t\tfrappe.set_user(frappe.db.get_value(\"OAuth Bearer Token\", token, \"user\"))\n\t\t\tfrappe.local.form_dict = form_dict\n\n\ndef validate_auth_via_api_keys():\n\t\"\"\"\n\tauthentication using api key and api secret\n\n\tset user\n\t\"\"\"\n\ttry:\n\t\tauthorization_header = frappe.get_request_header(\"Authorization\", None).split(\" \") if frappe.get_request_header(\"Authorization\") else None\n\t\tif authorization_header and authorization_header[0] == 'Basic':\n\t\t\ttoken = frappe.safe_decode(base64.b64decode(authorization_header[1])).split(\":\")\n\t\t\tvalidate_api_key_secret(token[0], token[1])\n\t\telif authorization_header and authorization_header[0] == 'token':\n\t\t\ttoken = authorization_header[1].split(\":\")\n\t\t\tvalidate_api_key_secret(token[0], token[1])\n\texcept Exception as e:\n\t\traise e\n\ndef validate_api_key_secret(api_key, api_secret):\n\tuser = frappe.db.get_value(\n\t\tdoctype=\"User\",\n\t\tfilters={\"api_key\": api_key},\n\t\tfieldname=['name']\n\t)\n\tform_dict = frappe.local.form_dict\n\tuser_secret = frappe.utils.password.get_decrypted_password (\"User\", user, fieldname='api_secret')\n\tif api_secret == user_secret:\n\t\tfrappe.set_user(user)\n\t\tfrappe.local.form_dict = form_dict\n", "path": "frappe/api.py"}]}