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.

103 lines
3.8 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. import json
  2. import logging
  3. from functools import wraps
  4. from odoo import http
  5. import werkzeug
  6. _logger = logging.getLogger(__name__)
  7. class ApiException(Exception):
  8. INVALID_REQUEST = "invalid_request"
  9. def __init__(self, message, code=None):
  10. super(Exception, self).__init__(message)
  11. self.code = code if code else self.INVALID_REQUEST
  12. def resource(path, method, auth="user"):
  13. assert auth in ["user", "client"]
  14. def endpoint_decorator(func):
  15. @http.route(
  16. path, auth="public", type="http", methods=[method, "OPTIONS"], csrf=False
  17. )
  18. @wraps(func)
  19. def func_wrapper(self, req, **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 req.httprequest.method == "OPTIONS":
  26. return http.Response(status=200, headers=cors_headers)
  27. try:
  28. access_token = None
  29. if "Authorization" in req.httprequest.headers:
  30. authorization_header = req.httprequest.headers["Authorization"]
  31. if authorization_header[:7] == "Bearer ":
  32. access_token = authorization_header.split(" ", 1)[1]
  33. if access_token is None:
  34. access_token = query.get("access_token")
  35. if not access_token:
  36. raise ApiException(
  37. "access_token param is missing", "invalid_request",
  38. )
  39. if auth == "user":
  40. token = (
  41. req.env["galicea_openid_connect.access_token"]
  42. .sudo()
  43. .search([("token", "=", access_token)])
  44. )
  45. if not token:
  46. raise ApiException(
  47. "access_token is invalid", "invalid_request",
  48. )
  49. req.uid = token.user_id.id
  50. elif auth == "client":
  51. token = (
  52. req.env["galicea_openid_connect.client_access_token"]
  53. .sudo()
  54. .search([("token", "=", access_token)])
  55. )
  56. if not token:
  57. raise ApiException(
  58. "access_token is invalid", "invalid_request",
  59. )
  60. req.uid = token.client_id.system_user_id.id
  61. ctx = req.context.copy()
  62. ctx.update({"client_id": token.client_id.id})
  63. req.context = ctx
  64. response = func(self, req, **query)
  65. return werkzeug.Response(
  66. response=json.dumps(response), headers=cors_headers, status=200
  67. )
  68. except ApiException as e:
  69. error_message = "error: {0}".format(e)
  70. return werkzeug.Response(
  71. response=json.dumps(
  72. {"error": e.code, "error_message": error_message}
  73. ),
  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. {
  82. "error": "server_error",
  83. "error_message": "Unexpected server error",
  84. }
  85. ),
  86. headers=cors_headers,
  87. status=500,
  88. )
  89. return func_wrapper
  90. return endpoint_decorator