http_handler.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. # -*- coding: utf-8 -*-
  2. from openerp import http
  3. from openerp.http import request
  4. from passlib.context import CryptContext
  5. import os
  6. import jwt
  7. import json
  8. import pickle
  9. import marshal
  10. from werkzeug.wrappers import Response
  11. CRYPT_CONTEXT = CryptContext(
  12. ['pbkdf2_sha512', 'md5_crypt'],
  13. deprecated=['md5_crypt'],
  14. )
  15. RESOURCES_MAP = None
  16. with open(os.path.dirname(__file__) + '/resources.json') as resources:
  17. RESOURCES_MAP = json.load(resources)
  18. '''
  19. Class for manage authentication
  20. '''
  21. class Auth(http.Controller):
  22. JWT_SECRET_KEY = '@MjSk$2016?'
  23. # --------------------------------------------------------------------------
  24. # Generate JWT token based on username and password field
  25. # --------------------------------------------------------------------------
  26. @http.route(['/api/jwt'], type = 'http', auth = 'none', methods = ['POST'], cors = '*')
  27. def get_jwt(self, **args):
  28. try:
  29. user = request.env['res.users'].sudo().search([('login', '=', args['username']), ('active', '=', True)])
  30. if len(user) != 0 and self.get_crypt_context().verify(args['password'], user.password_crypt):
  31. payload = {
  32. 'uid': user.id,
  33. 'password': args['password']
  34. }
  35. encoded = jwt.encode(payload, self.JWT_SECRET_KEY, algorithm = 'HS256')
  36. user.write({'jwt_token': encoded})
  37. return json.dumps({'token': encoded})
  38. else:
  39. return json.dumps({'error': 'invalid user or password'})
  40. except Exception, e:
  41. return json.dumps({'error': 'fields required'})
  42. # --------------------------------------------------------------------------
  43. # Check JWT token auth
  44. # --------------------------------------------------------------------------
  45. @http.route(['/api/check'], type = 'http', auth = 'none', methods = ['POST'], cors = '*')
  46. def check_token(self, **args):
  47. try:
  48. user = request.env['res.users'].sudo().search([('jwt_token', '=', args['token'])])
  49. if len(user) != 0:
  50. decoded = jwt.decode(args['token'], self.JWT_SECRET_KEY, algorithms = ['HS256'])
  51. if self.get_crypt_context().verify(decoded['password'], user.password_crypt):
  52. return json.dumps({'token': 'valid'})
  53. return json.dumps({'token': 'invalid'})
  54. except Exception, e:
  55. return json.dumps({'error': 'token required'})
  56. # --------------------------------------------------------------------------
  57. # Get context for encryption
  58. # --------------------------------------------------------------------------
  59. def get_crypt_context(self):
  60. return CRYPT_CONTEXT
  61. '''
  62. Class for manage rest api interaction
  63. '''
  64. class ApiManager(http.Controller):
  65. RESOURCES_MAP = [
  66. {'customers': 'res.partner'}
  67. ]
  68. # --------------------------------------------------------------------------
  69. # Restify your request
  70. # --------------------------------------------------------------------------
  71. @http.route([
  72. '/api/<any(customers, leads, opportunities):resource>',
  73. '/api/<any(customers, leads, opportunities):resource>/<int:uid>'
  74. ],
  75. type = 'http',
  76. auth = 'none',
  77. cors = '*')
  78. def restify(self, resource, uid = None):
  79. if not self.resource_exists(resource):
  80. return self.make_response({'error': 'resource not available'})
  81. http_verb = request.httprequest.method
  82. if http_verb == 'GET':
  83. return self.http_get(resource, uid)
  84. if http_verb == 'POST':
  85. return json.dumps({'verb': 'POST'}, sort_keys = True)
  86. if http_verb == 'PUT' or http_verb == 'PATCH':
  87. return json.dumps({'verb': 'PUT OR PATCH'})
  88. if http_verb == 'DELETE':
  89. return self.http_delete(resource, uid)
  90. return json.dumps({'error': 'method not allowed'})
  91. # --------------------------------------------------------------------------
  92. # Manage GET request
  93. # --------------------------------------------------------------------------
  94. def http_get(self, resource, uid):
  95. model, filters = self.resource_inflater(resource)
  96. data = []
  97. if uid != None:
  98. filters.append(('id', '=', uid))
  99. result = request.env[model].sudo().search(filters)
  100. for item in result:
  101. data.append(item.dump())
  102. return self.make_response(data);
  103. # --------------------------------------------------------------------------
  104. # Manage DELETE request
  105. # --------------------------------------------------------------------------
  106. def http_delete(self, resource, uid):
  107. if uid == None:
  108. return self.make_response({'error': 'uid not provided'})
  109. model, filters = self.resource_inflater(resource)
  110. result = request.env[model].sudo().browse(uid)
  111. if not result.exists():
  112. return self.make_response({'error': 'cannot be deleted'})
  113. return self.make_response({'response': result.unlink()})
  114. # --------------------------------------------------------------------------
  115. # Make JSON response
  116. # --------------------------------------------------------------------------
  117. def make_response(self, data):
  118. return Response(json.dumps(data), mimetype = 'application/json')
  119. # --------------------------------------------------------------------------
  120. # Manage JWT token validity
  121. # --------------------------------------------------------------------------
  122. def resource_exists(self, resource):
  123. try:
  124. model = RESOURCES_MAP[resource]['module']
  125. module_name = model.replace('.', '_')
  126. module = request.env['ir.module.module'].sudo().search([('name', '=', module_name)])
  127. return True if module.state == 'installed' and len(module) != 0 else False
  128. except Exception, e:
  129. return False;
  130. # --------------------------------------------------------------------------
  131. # Manage JWT token validity
  132. # --------------------------------------------------------------------------
  133. def check_token(self, token):
  134. pass
  135. # --------------------------------------------------------------------------
  136. # Manage GET request
  137. # --------------------------------------------------------------------------
  138. def resource_inflater(self, resource):
  139. try:
  140. model = RESOURCES_MAP[resource]['model']
  141. filters = []
  142. for i in range(len(RESOURCES_MAP[resource]['filters'])):
  143. filters.append(tuple(RESOURCES_MAP[resource]['filters'][i]))
  144. return (model, filters)
  145. except Exception, e:
  146. return (None, None)