Browse Source

Include datetime object in return field

* Fix no fields returned by passing ID if no field is specified
pull/345/head
drpsyko101 9 months ago
parent
commit
d9611724c2
  1. 292
      rest_api_odoo/controllers/main.py

292
rest_api_odoo/controllers/main.py

@ -22,6 +22,8 @@
import json
import logging
from datetime import datetime
from odoo import http
from odoo.http import request, Response
from ast import literal_eval
@ -37,195 +39,259 @@ class RestApi(http.Controller):
"""This function is used to authenticate the api-key when sending a
request"""
user_id = request.env['res.users'].search([('api_key', '=', api_key)])
user_id = request.env["res.users"].search([("api_key", "=", api_key)])
if api_key is not None and user_id:
return True
return Response(json.dumps({"message": "Authorized"}), status=200)
elif not user_id:
return Response(json.dumps({'message': 'Invalid API Key'}), status=401)
return Response(json.dumps({'message': 'No API Key Provided'}), status=400)
return Response(json.dumps({"message": "Invalid API Key"}), status=401)
return Response(json.dumps({"message": "No API Key Provided"}), status=400)
def simplest_type(self, input):
"""Try cast input into native Python class, otherwise return as string"""
try:
return literal_eval(input)
except:
if input == 'true':
except Exception:
# Handle lowercase booleans
if input == "true":
return True
if input == 'false':
if input == "false":
return False
return input
def sanitize_records(self, records):
"""Sanitize records for response"""
for record in records:
for key, value in record.items():
# Manually convert datetime fields to string format
if isinstance(value, datetime):
record[key] = value.isoformat()
return records
def generate_response(self, method, **query):
"""This function is used to generate the response based on the type
of request and the parameters given"""
model = query.pop('model')
option = request.env['connection.api'].search(
[('model_id', '=', model)], limit=1)
model = query.pop("model")
option = request.env["connection.api"].search(
[("model_id", "=", model)], limit=1
)
model_name = option.model_id.model
model_display_name = option.model_id.name
data = {}
try:
data = json.loads(request.httprequest.data)
except:
pass
except Exception:
data = {}
fields = []
if data:
for field in data['fields']:
for field in data["fields"]:
fields.append(field)
if '*' in fields:
# Return records' ID by default if not specified
if not fields:
fields.append("id")
# Get all model's fields if wildcard is used
if "*" in fields:
fields = []
record_fields = request.env[
str(model_name)].fields_get([], attributes=['type'])
record_fields = request.env[str(model_name)].fields_get(
[], attributes=["type"]
)
for field, value in record_fields.items():
value_type = value.get('type')
if not (value_type == 'binary' or value_type == 'datetime'):
value_type = value.get("type")
if not (value_type == "binary"):
fields.append(field)
if not option:
return Response(json.dumps({'message': f'No Record Created for the model. Please contact your admininstrator to enable {method} method for {model_display_name} record.'}), status=403)
try:
if method == 'GET':
if not fields:
fields.append('id')
return Response(
json.dumps(
{
"message": f"No Record Created for the model. Please contact your admininstrator to enable {method} method for {model_display_name} record."
}
),
status=403,
)
if method == "GET":
if not option.is_get:
return Response(
json.dumps({'message': f'Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record.'}),
status=405)
else:
json.dumps(
{
"message": f"Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record."
}
),
status=405,
)
domains = []
for key, value in query.items():
domains.append((key, '=', self.simplest_type(value)))
partner_records = request.env[
str(model_name)].search_read(
domain=domains,
fields=fields
domains.append((key, "=", self.simplest_type(value)))
partner_records = request.env[str(model_name)].search_read(
domain=domains, fields=fields
)
return Response(
json.dumps({
'records': partner_records
})
json.dumps({"records": self.sanitize_records(partner_records)})
)
if method == 'POST':
if method == "POST":
if not option.is_post:
return Response(
json.dumps({'message': f'Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record.'}),
status=405)
if not data or 'values' not in data:
return Response(json.dumps({'message': 'No Data Provided'}), status=403)
json.dumps(
{
"message": f"Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record."
}
),
status=405,
)
if not data or "values" not in data:
return Response(json.dumps({"message": "No Data Provided"}), status=403)
try:
data = json.loads(request.httprequest.data)
new_resource = request.env[str(model_name)].create(
data['values'])
partner_records = request.env[
str(model_name)].search_read(
domain=[('id', '=', new_resource.id)],
fields=fields
)
return Response(json.dumps({'new_record': partner_records}), status=201)
except:
return Response(json.dumps({'message': 'Invalid JSON Data'}), status=403)
if method == 'PUT':
new_resource = request.env[str(model_name)].create(data["values"])
partner_records = request.env[str(model_name)].search_read(
domain=[("id", "=", new_resource.id)], fields=fields
)
return Response(
json.dumps({"new_record": self.sanitize_records(partner_records)}),
status=201,
)
except Exception:
return Response(
json.dumps({"message": "Invalid JSON Data"}), status=403
)
if method == "PUT":
if not option.is_put:
return Response(
json.dumps({'message': f'Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record.'}),
status=405)
json.dumps(
{
"message": f"Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record."
}
),
status=405,
)
if not 'id' in query:
return Response(json.dumps({'message': 'No ID Provided'}), status=403)
if not data or 'values' not in data:
return Response(json.dumps({'message': 'No Data Provided'}), status=403)
if "id" not in query:
return Response(json.dumps({"message": "No ID Provided"}), status=403)
if not data or "values" not in data:
return Response(json.dumps({"message": "No Data Provided"}), status=403)
resource = request.env[str(model_name)].browse(
int(query.get('id')))
resource_id = str(query.get("id"))
resource = request.env[str(model_name)].browse(int(resource_id))
if not resource.exists():
return Response(json.dumps({'message': 'Resource not found'}), status=404)
return Response(
json.dumps({"message": "Resource not found"}), status=404
)
try:
data = json.loads(request.httprequest.data)
resource.write(data['values'])
partner_records = request.env[
str(model_name)].search_read(
domain=[('id', '=', resource.id)],
fields=fields
resource.write(data["values"])
partner_records = request.env[str(model_name)].search_read(
domain=[("id", "=", resource.id)], fields=fields
)
return Response(
json.dumps(
{"updated_record": self.sanitize_records(partner_records)}
)
)
return Response(json.dumps({'updated_record': partner_records}))
except:
return Response(json.dumps({'message': 'Invalid JSON value(s) passed'}), status=403)
if method == 'DELETE':
except Exception:
return Response(
json.dumps({"message": "Invalid JSON value(s) passed"}),
status=403,
)
if method == "DELETE":
if not option.is_delete:
return Response(
json.dumps({'message': f'Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record.'}),
status=405)
json.dumps(
{
"message": f"Method not allowed. Please contact your admininstrator to enable {method} method for {model_display_name} record."
}
),
status=405,
)
if not 'id' in query:
return Response(json.dumps({'message': 'No ID Provided'}), status=403)
if "id" not in query:
return Response(json.dumps({"message": "No ID Provided"}), status=403)
resource = request.env[str(model_name)].browse(
int(query.get('id')))
resource_id = str(query.get("id"))
resource = request.env[str(model_name)].browse(int(resource_id))
if not resource.exists():
return Response(json.dumps({'message': 'Resource not found'}), status=404)
else:
return Response(
json.dumps({"message": "Resource not found"}), status=404
)
records = request.env[
str(model_name)].search_read(
domain=[('id', '=', resource.id)],
fields=fields
partner_records = request.env[str(model_name)].search_read(
domain=[("id", "=", resource.id)], fields=fields
)
resource.unlink()
return Response(json.dumps({'message': 'Resource deleted', 'data': records}), status=202)
except:
return Response(json.dumps({'message': 'Internal Server Error'}), status=500)
return Response(
json.dumps(
{
"message": "Resource deleted",
"data": self.sanitize_records(partner_records),
}
),
status=202,
)
@http.route(['/send_request'], type='http',
auth='none',
methods=['GET', 'POST', 'PUT', 'DELETE'], csrf=False)
# If not using any method above, simply return an error
return Response(json.dumps({"message": "Method not allowed"}), status=405)
@http.route(
["/send_request"],
type="http",
auth="none",
methods=["GET", "POST", "PUT", "DELETE"],
csrf=False,
)
def fetch_data(self, **kw):
"""This controller will be called when sending a request to the
specified url, and it will authenticate the api-key and then will
generate the result"""
http_method = request.httprequest.method
api_key = request.httprequest.headers.get('api-key')
api_key = request.httprequest.headers.get("api-key")
auth_api = self.auth_api_key(api_key)
model = kw.pop('model')
username = request.httprequest.headers.get('login')
password = request.httprequest.headers.get('password')
request.session.authenticate(request.session.db, username,
password)
model_id = request.env['ir.model'].search(
[('model', '=', model)])
model = kw.pop("model")
username = request.httprequest.headers.get("login")
password = request.httprequest.headers.get("password")
request.session.authenticate(request.session.db, username, password)
model_id = request.env["ir.model"].search([("model", "=", model)])
if not model_id:
return Response(json.dumps(
{'message': 'Invalid model, check spelling or maybe the related module is not installed'}),
status=403)
return Response(
json.dumps(
{
"message": "Invalid model, check spelling or maybe the related module is not installed"
}
),
status=403,
)
if auth_api == True:
if auth_api.status_code == 200:
result = self.generate_response(http_method, model=model_id.id, **kw)
return result
else:
return auth_api
@http.route(['/odoo_connect'], type="http", auth="none", csrf=False,
methods=['GET'])
@http.route(
["/odoo_connect"], type="http", auth="none", csrf=False, methods=["GET"]
)
def odoo_connect(self, **kw):
"""This is the controller which initializes the api transaction by
generating the api-key for specific user and database"""
username = request.httprequest.headers.get('login')
password = request.httprequest.headers.get('password')
db = request.httprequest.headers.get('db')
username = request.httprequest.headers.get("login")
password = request.httprequest.headers.get("password")
db = request.httprequest.headers.get("db")
try:
request.session.update(http.get_default_session(), db=db)
auth = request.session.authenticate(request.session.db, username,
password)
user = request.env['res.users'].browse(auth)
auth = request.session.authenticate(request.session.db, username, password)
user = request.env["res.users"].browse(auth)
api_key = request.env.user.generate_api(username)
datas = json.dumps({"Status": "auth successful",
"User": user.name,
"api-key": api_key})
return request.make_response(data=datas)
except:
return Response(json.dumps({'message': 'wrong login credentials'}), status=401)
datas = json.dumps(
{"Status": "auth successful", "User": user.name, "api-key": api_key}
)
return Response(datas, status=200)
except Exception:
return Response(
json.dumps({"message": "wrong login credentials"}), status=401
)

Loading…
Cancel
Save