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.

100 lines
3.8 KiB

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