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.

99 lines
3.8 KiB

5 years ago
5 years ago
5 years ago
5 years ago
  1. # -*- coding: utf-8 -*-
  2. import json
  3. import logging
  4. from functools import wraps
  5. from odoo import http
  6. from odoo.http import request
  7. import werkzeug
  8. _logger = logging.getLogger(__name__)
  9. class ApiException(Exception):
  10. INVALID_REQUEST = 'invalid_request'
  11. def __init__(self, message, code=None):
  12. super(Exception, self).__init__(message)
  13. self.code = code if code else self.INVALID_REQUEST
  14. def resource(path, method, auth='user'):
  15. assert auth in ['user', 'client']
  16. def endpoint_decorator(func):
  17. @http.route(path, auth='public', type='http', methods=[method, 'OPTIONS'], csrf=False)
  18. @wraps(func)
  19. def func_wrapper(self, **query):
  20. cors_headers = {
  21. 'Access-Control-Allow-Origin': '*',
  22. 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, X-Debug-Mode, Authorization',
  23. 'Access-Control-Max-Age': 60 * 60 * 24,
  24. }
  25. if request.httprequest.method == 'OPTIONS':
  26. return http.Response(
  27. status=200,
  28. headers=cors_headers
  29. )
  30. try:
  31. access_token = None
  32. if 'Authorization' in request.httprequest.headers:
  33. authorization_header = request.httprequest.headers['Authorization']
  34. if authorization_header[:7] == 'Bearer ':
  35. access_token = authorization_header.split(' ', 1)[1]
  36. if access_token is None:
  37. access_token = query.get('access_token')
  38. if not access_token:
  39. raise ApiException(
  40. 'access_token param is missing',
  41. 'invalid_request',
  42. )
  43. if auth == 'user':
  44. token = request.env['galicea_openid_connect.access_token'].sudo().search(
  45. [('token', '=', access_token)]
  46. )
  47. if not token:
  48. raise ApiException(
  49. 'access_token is invalid',
  50. 'invalid_request',
  51. )
  52. request.update_env(user=token.user_id.id)
  53. elif auth == 'client':
  54. token = request.env['galicea_openid_connect.client_access_token'].sudo().search(
  55. [('token', '=', access_token)]
  56. )
  57. if not token:
  58. raise ApiException(
  59. 'access_token is invalid',
  60. 'invalid_request',
  61. )
  62. request.update_env(user=token.client_id.system_user_id.id)
  63. request.update_env(context={'client_id': token.client_id.id})
  64. response = func(self, **query)
  65. return werkzeug.Response(
  66. response=json.dumps(response),
  67. headers=cors_headers,
  68. status=200
  69. )
  70. except ApiException as e:
  71. error_message = "error: {0}".format(e)
  72. return werkzeug.Response(
  73. response=json.dumps({'error': e.code, 'error_message': error_message}),
  74. status=400,
  75. headers=cors_headers
  76. )
  77. except:
  78. _logger.exception('Unexpected exception while processing API request')
  79. return werkzeug.Response(
  80. response=json.dumps({
  81. 'error': 'server_error',
  82. 'error_message': 'Unexpected server error',
  83. }),
  84. headers=cors_headers,
  85. status=500
  86. )
  87. return func_wrapper
  88. return endpoint_decorator