123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- # -*- coding: utf-8 -*-
- from openerp import http
- from openerp.http import request
- from passlib.context import CryptContext
- import os
- import jwt
- import json
- import pickle
- import marshal
- from werkzeug.wrappers import Response
- CRYPT_CONTEXT = CryptContext(
- ['pbkdf2_sha512', 'md5_crypt'],
- deprecated=['md5_crypt'],
- )
- RESOURCES_MAP = None
- with open(os.path.dirname(__file__) + '/resources.json') as resources:
- RESOURCES_MAP = json.load(resources)
- '''
- Class for manage authentication
- '''
- class Auth(http.Controller):
- JWT_SECRET_KEY = '@MjSk$2016?'
- # --------------------------------------------------------------------------
- # Generate JWT token based on username and password field
- # --------------------------------------------------------------------------
- @http.route(['/api/jwt'], type = 'http', auth = 'none', methods = ['POST'], cors = '*')
- def get_jwt(self, **args):
- try:
- user = request.env['res.users'].sudo().search([('login', '=', args['username']), ('active', '=', True)])
- if len(user) != 0 and self.get_crypt_context().verify(args['password'], user.password_crypt):
- payload = {
- 'uid': user.id,
- 'password': args['password']
- }
- encoded = jwt.encode(payload, self.JWT_SECRET_KEY, algorithm = 'HS256')
- user.write({'jwt_token': encoded})
- return json.dumps({'token': encoded})
- else:
- return json.dumps({'error': 'invalid user or password'})
- except Exception, e:
- return json.dumps({'error': 'fields required'})
- # --------------------------------------------------------------------------
- # Check JWT token auth
- # --------------------------------------------------------------------------
- @http.route(['/api/check'], type = 'http', auth = 'none', methods = ['POST'], cors = '*')
- def check_token(self, **args):
- try:
- user = request.env['res.users'].sudo().search([('jwt_token', '=', args['token'])])
- if len(user) != 0:
- decoded = jwt.decode(args['token'], self.JWT_SECRET_KEY, algorithms = ['HS256'])
- if self.get_crypt_context().verify(decoded['password'], user.password_crypt):
- return json.dumps({'token': 'valid'})
- return json.dumps({'token': 'invalid'})
- except Exception, e:
- return json.dumps({'error': 'token required'})
- # --------------------------------------------------------------------------
- # Get context for encryption
- # --------------------------------------------------------------------------
- def get_crypt_context(self):
- return CRYPT_CONTEXT
- '''
- Class for manage rest api interaction
- '''
- class ApiManager(http.Controller):
- RESOURCES_MAP = [
- {'customers': 'res.partner'}
- ]
- # --------------------------------------------------------------------------
- # Restify your request
- # --------------------------------------------------------------------------
- @http.route([
- '/api/<any(customers, leads, opportunities):resource>',
- '/api/<any(customers, leads, opportunities):resource>/<int:uid>'
- ],
- type = 'http',
- auth = 'none',
- cors = '*')
- def restify(self, resource, uid = None):
- if not self.resource_exists(resource):
- return self.make_response({'error': 'resource not available'})
- http_verb = request.httprequest.method
- if http_verb == 'GET':
- return self.http_get(resource, uid)
- if http_verb == 'POST':
- return json.dumps({'verb': 'POST'}, sort_keys = True)
- if http_verb == 'PUT' or http_verb == 'PATCH':
- return json.dumps({'verb': 'PUT OR PATCH'})
- if http_verb == 'DELETE':
- return self.http_delete(resource, uid)
- return json.dumps({'error': 'method not allowed'})
- # --------------------------------------------------------------------------
- # Manage GET request
- # --------------------------------------------------------------------------
- def http_get(self, resource, uid):
- model, filters = self.resource_inflater(resource)
- data = []
- if uid != None:
- filters.append(('id', '=', uid))
- result = request.env[model].sudo().search(filters)
- for item in result:
- data.append(item.dump())
- return self.make_response(data);
- # --------------------------------------------------------------------------
- # Manage DELETE request
- # --------------------------------------------------------------------------
- def http_delete(self, resource, uid):
- if uid == None:
- return self.make_response({'error': 'uid not provided'})
- model, filters = self.resource_inflater(resource)
- result = request.env[model].sudo().browse(uid)
- if not result.exists():
- return self.make_response({'error': 'cannot be deleted'})
- return self.make_response({'response': result.unlink()})
- # --------------------------------------------------------------------------
- # Make JSON response
- # --------------------------------------------------------------------------
- def make_response(self, data):
- return Response(json.dumps(data), mimetype = 'application/json')
- # --------------------------------------------------------------------------
- # Manage JWT token validity
- # --------------------------------------------------------------------------
- def resource_exists(self, resource):
- try:
- model = RESOURCES_MAP[resource]['module']
- module_name = model.replace('.', '_')
- module = request.env['ir.module.module'].sudo().search([('name', '=', module_name)])
- return True if module.state == 'installed' and len(module) != 0 else False
- except Exception, e:
- return False;
- # --------------------------------------------------------------------------
- # Manage JWT token validity
- # --------------------------------------------------------------------------
- def check_token(self, token):
- pass
- # --------------------------------------------------------------------------
- # Manage GET request
- # --------------------------------------------------------------------------
- def resource_inflater(self, resource):
- try:
- model = RESOURCES_MAP[resource]['model']
- filters = []
- for i in range(len(RESOURCES_MAP[resource]['filters'])):
- filters.append(tuple(RESOURCES_MAP[resource]['filters'][i]))
- return (model, filters)
- except Exception, e:
- return (None, None)
|