diff --git a/rest_api_odoo/controllers/main.py b/rest_api_odoo/controllers/main.py index 37169cd3b..20b057bc6 100644 --- a/rest_api_odoo/controllers/main.py +++ b/rest_api_odoo/controllers/main.py @@ -23,7 +23,8 @@ import json import logging from odoo import http -from odoo.http import request +from odoo.http import request, Response +from ast import literal_eval _logger = logging.getLogger(__name__) @@ -38,80 +39,83 @@ class RestApi(http.Controller): user_id = request.env['res.users'].search([('api_key', '=', api_key)]) if api_key is not None and user_id: - response = True + return True elif not user_id: - response = ('

Invalid API Key ' - '!

') - else: - response = ("

No API Key Provided " - "!

") - - return response + 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': + return True + if input == 'false': + return False + return input - def generate_response(self, method, model, rec_id): + 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_name = option.model_id.model + model_display_name = option.model_id.name - if method != 'DELETE': + data = {} + try: data = json.loads(request.httprequest.data) - else: - data = {} + except: + pass + fields = [] if data: for field in data['fields']: fields.append(field) - if not fields and method != 'DELETE': - return ("

No fields selected for the model" - "

") + if '*' in fields: + fields = [] + 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'): + fields.append(field) if not option: - return ("

No Record Created for the model" - "

") + 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': - fields = [] - for field in data['fields']: - fields.append(field) + if not fields: + fields.append('id') if not option.is_get: - return ("

Method Not Allowed" - "

") + 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: - datas = [] - if rec_id != 0: - partner_records = request.env[ - str(model_name)].search_read( - domain=[('id', '=', rec_id)], - fields=fields - ) - data = json.dumps({ - 'records': partner_records - }) - datas.append(data) - return request.make_response(data=datas) - else: - partner_records = request.env[ - str(model_name)].search_read( - domain=[], - fields=fields - ) - data = json.dumps({ + 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 + ) + return Response( + json.dumps({ 'records': partner_records }) - datas.append(data) - return request.make_response(data=datas) - except: - return ("

Invalid JSON Data" - "

") - if method == 'POST': - if not option.is_post: - return ("

Method Not Allowed" - "

") - else: + ) + 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) + try: data = json.loads(request.httprequest.data) - datas = [] new_resource = request.env[str(model_name)].create( data['values']) partner_records = request.env[ @@ -119,71 +123,61 @@ class RestApi(http.Controller): domain=[('id', '=', new_resource.id)], fields=fields ) - new_data = json.dumps({'New resource': partner_records, }) - datas.append(new_data) - return request.make_response(data=datas) + return Response(json.dumps({'new_record': partner_records}), status=201) except: - return ("

Invalid JSON Data" - "

") - if method == 'PUT': - if not option.is_put: - return ("

Method Not Allowed" - "

") - else: - if rec_id == 0: - return ("

No ID Provided" - "

") - else: - resource = request.env[str(model_name)].browse( - int(rec_id)) - if not resource.exists(): - return ("

Resource not found" - "

") - else: - try: - datas = [] - 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 - ) - new_data = json.dumps( - {'Updated resource': partner_records, - }) - datas.append(new_data) - return request.make_response(data=datas) - - except: - return ("

Invalid JSON Data " - "!

") - if method == 'DELETE': - if not option.is_delete: - return ("

Method Not Allowed" - "

") - else: - if rec_id == 0: - return ("

No ID Provided" - "

") + 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) + + 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) + + resource = request.env[str(model_name)].browse( + int(query.get('id'))) + if not resource.exists(): + 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 + ) + return Response(json.dumps({'updated_record': partner_records})) + + except: + 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) + + if not 'id' in query: + return Response(json.dumps({'message': 'No ID Provided'}), status=403) + + resource = request.env[str(model_name)].browse( + int(query.get('id'))) + if not resource.exists(): + return Response(json.dumps({'message': 'Resource not found'}), status=404) else: - resource = request.env[str(model_name)].browse( - int(rec_id)) - if not resource.exists(): - return ("

Resource not found" - "

") - else: - - records = request.env[ - str(model_name)].search_read( - domain=[('id', '=', resource.id)], - fields=['id', 'display_name'] - ) - remove = json.dumps( - {"Resource deleted": records, - }) - resource.unlink() - return request.make_response(data=remove) + + 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) @http.route(['/send_request'], type='http', auth='none', @@ -196,7 +190,7 @@ class RestApi(http.Controller): http_method = request.httprequest.method api_key = request.httprequest.headers.get('api-key') auth_api = self.auth_api_key(api_key) - model = kw.get('model') + model = kw.pop('model') username = request.httprequest.headers.get('login') password = request.httprequest.headers.get('password') request.session.authenticate(request.session.db, username, @@ -204,17 +198,12 @@ class RestApi(http.Controller): model_id = request.env['ir.model'].search( [('model', '=', model)]) if not model_id: - return ("

Invalid model, check spelling or maybe " - "the related " - "module is not installed" - "

") + return Response(json.dumps( + {'message': 'Invalid model, check spelling or maybe the related module is not installed'}), + status=403) if auth_api == True: - if not kw.get('Id'): - rec_id = 0 - else: - rec_id = int(kw.get('Id')) - result = self.generate_response(http_method, model_id.id, rec_id) + result = self.generate_response(http_method, model=model_id.id, **kw) return result else: return auth_api @@ -239,5 +228,4 @@ class RestApi(http.Controller): "api-key": api_key}) return request.make_response(data=datas) except: - return ("

wrong login credentials" - "

") + return Response(json.dumps({'message': 'wrong login credentials'}), status=401) diff --git a/rest_api_odoo/static/description/index.html b/rest_api_odoo/static/description/index.html index bf41854b7..11a198179 100644 --- a/rest_api_odoo/static/description/index.html +++ b/rest_api_odoo/static/description/index.html @@ -217,7 +217,7 @@
  • First of all, we have to add a new parameter in odoo conf. file.
  • -
  • server_wide_modules = web, base, rest_api_odoo
    +
  • server_wide_modules = web, base, rest_api_odoo
    - This will allow us to send request to server without selecting database first.
    - Incase if you have to uninstall the module , you have to remove this parameter. @@ -251,10 +251,10 @@
  • Next you have to select the database and login.
  • We have attached Postman collections through which you can - authenticate rest api. + authenticate REST api.
  • First, extract the zip file. Then, you will obtain the JSON-format file, which you can directly import into POSTMAN.
  • -
  • The url format will be like this - http://cybrosys:8016/odoo_connect +
  • The url format will be like this - http://cybrosys:8016/odoo_connect Replace 'cybrosys:8016' with your localhost port number.
  • You have to provide database name, username and password @@ -266,9 +266,9 @@
  • This key will be used when sending api requests to database.
  • -
  • The response will be like this - {"Status": "auth +
  • The response will be like this - {"Status": "auth successful", "User": "Mitchell Admin", "api-key": - "66c2ebab-d4dc-42f0-87d0-d1646e887569"}.
  • + "66c2ebab-d4dc-42f0-87d0-d1646e887569"}.

    @@ -338,7 +339,7 @@

    @@ -373,7 +374,7 @@ Update Records

    @@ -401,7 +402,7 @@