I am developping an Android application, and I'd like to retrieve data from an Odoo server.
For that I developped a custom module in Odoo, in which I created a controller.
import json
import xmlrpc.client as xmlrpclib
from odoo import http
from openerp.http import Response
class resUserController(http.Controller):
url = '<my url>'
db = '<name of my database>'
@http.route('/user/login', type='json', method='GET', auth='public')
def get_login(self, **kwargs):
username = kwargs.get('email')
password = kwargs.get('password')
common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(self.url), allow_none=True)
uid = common.authenticate(self.db, username, password, {})
if uid:
Response.status = '200 Succesful operation'
json_result = {'token': uid}
return json.dumps(json_result)
Response.status = '400 Invalid credentials'
return
When I call it from a python script to try it, it works fine and I get a <Response [200]>
and a json {u'jsonrpc': u'2.0', u'result': u'{"token": 8}', u'id': None}
with the id of the account I connect to.
But then I have an other function I call with an other route in the same controller, but with auth='user'
this time, because I want the user to be able to see only informations he has rights on.
@http.route('/user/getInfo', type='json', method='GET', auth='user')
def get_info(self, **kwargs):
uid = 1
password = '<my admin password>'
models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(self.url), allow_none=True)
info = models.execute_kw(self.db, uid, password, 'res.users',
'search_read', [[['id', '=', kwargs.get('token')]]],
{'fields': ['info']})[0]['invite_code']
if info:
Response.status = '200 Succesful operation'
json_result = {'info': info}
return json.dumps(json_result)
Response.status = '404 User not found'
return
This function works fine when I use auth='public'
, but when I go for auth='user'
, I get the following json response :
Response [200]
{ u'jsonrpc': u'2.0', u'id': None, u'error': { u'message': u'Odoo Session Expired', u'code': 100, u'data': { u'debug': u'Traceback (most recent call last): File "/usr/lib/python3/dist-packages/odoo/http.py", line 650, in _handle_exception return super(JsonRequest, self)._handle_exception(exception) File "/usr/lib/python3/dist-packages/odoo/http.py", line 310, in _handle_exception raise pycompat.reraise(type(exception), exception, sys.exc_info()[2]) File "/usr/lib/python3/dist-packages/odoo/tools/pycompat.py", line 87, in reraise raise value File "/usr/lib/python3/dist-packages/odoo/addons/http_routing/models/ir_http.py", line 342, in _dispatch cls._authenticate(func.routing[\'auth\']) File "/usr/lib/python3/dist-packages/odoo/addons/base/ir/ir_http.py", line 117, in _authenticate getattr(cls, "_auth_method_%s" % auth_method)() File "/usr/lib/python3/dist-packages/odoo/addons/base/ir/ir_http.py", line 90, in _auth_method_user raise http.SessionExpiredException("Session expired") odoo.http.SessionExpiredException: Session expired', u'exception_type': u'internal_error', u'message': u'Session expired', u'name': u'odoo.http.SessionExpiredException', u'arguments': [u'Session expired'] } } }
I based my work on This documentation, which is an official Odoo doc, but here are the problems :
1 It ask me to write my admin password in each function, which seems dangerous.
2 After authentication, I get the id of my user, but no session token. Then how can I inform my function with auth='user'
that I'm connected and to which user?
Here is my script to test my calls :
import requests
import json
url_connect = "<my url>/user/login"
url = "<my url>/user/getInfo"
headers = {'Content-Type': 'application/json'}
data_connect = {
"params": {
"email": "<my test account email>",
"password": "<my test account password>",
}
}
data = {
"params": {
"token": <my test account id>,
}
}
data_json = json.dumps(data)
r = requests.get(url=url_connect, data=json.dumps(data_connect), headers=headers)
print(r)
print(r.json())
r = requests.get(url=url, data=data_json, headers=headers)
print(r)
print(r.json())
You can easily convert your Odoo store into a beautiful mobile application with the help of the Odoo Mobile App for Android & iOS. Customers may quickly download the app onto their mobile devices, which provides a better user experience. As a result, they can conveniently shop for products while on the go.
Odoo Web Login Screen v9 Then go to you odoo webinterface to the module section and start "Update module list". Then look for the "Odoo Web Login Screen" in Apps (module list) and install. I hope you enjoy checking out what all you can do with this application.
ngnix, apache as web servers to deploy Odoo.
Odoo is a suite of open source business apps that covers all your company needs: CRM, eCommerce, Accounting, Inventory, Point of Sale, Project Management, and more. The mobile app offers a smooth and friendly user experience that has been carefully built to ensure quick and seamless user adoption.
Things to note:
Here is an example using /web/session/autenticate:
import requests
import json
url_connect = "http://localhost:8069/web/session/authenticate"
url = "http://localhost:8069/web/session/get_session_info"
headers = {'Content-Type': 'application/json'}
data_connect = {
"params": {
"db": "demo1",
"login": "admin",
"password": "admin",
}
}
data = {}
session = requests.Session()
r = session.post(url=url_connect, data=json.dumps(data_connect), headers=headers)
if r.ok:
result = r.json()['result']
if result.get('session_id'):
session.cookies['session_id'] = result.get('session_id')
r = session.post(url=url, data=json.dumps(data), headers=headers)
print(r)
print(r.json())
To get the info from your controller you could use request.env.user which holds the logged user at the moment and since you specify auth='user' it is required to be a valid. The sample code might look like:
from odoo.http import request
class UserController(http.Controller):
@http.route('/user/getInfo', type='json', method='POST', auth='user')
def get_info(self, **kwargs):
current_user = request.env.user
Response.status = '200 Succesful operation'
json_result = {'info': current_user.info}
return json.dumps(json_result)
Very well write question, you have done the homework. This works for me to be able to authenticate the mobile users sessions using an api style requests.
@http.route([
'/m/login/email',
], type='http', auth="public", website=True, methods=["POST"], csrf=False)
def users_login_email(self, **kwargs):
if kwargs:
data = json.loads(kwargs.keys()[0])
else:
data = json.loads(request.httprequest.data)
email = data.get('email')
password = data.get('password')
if not request.session.db:
setup_db()
uid = request.session.authenticate(request.session.db, email, password)
if uid:
return self._user_details(uid)
body = json.dumps({"body": ["Credenciales Incorrectas"]})
return werkzeug.wrappers.Response(body, status=403, headers=[
('Content-Type', 'application/json'), ('Content-Length', len(body))
])
Also I didn't use auth='user'
to don't let Odoo to mess with redirects and web stuffs checks. I use this annotation wrapper in my controllers routes that require an authenticated user to return the proper HTTP error status code
def check_user(f):
@functools.wraps(f)
def wrap(*args, **kwargs):
if not request.session.db:
setup_db()
request.uid = request.session.uid
if not request.uid:
body = json.dumps({"body": ["Session Expired"]})
return werkzeug.wrappers.Response(body, status=403, headers=[
('Content-Type', 'application/json'), ('Content-Length', len(body))
])
return f(*args, **kwargs)
return wrap
You could use it like this:
@check_user
@http.route([
'/m/<int:shop_id>/cart/info',
], type='http', auth="public", website=True)
def cart_info(self, shop_id, **kwargs):
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With