diff --git a/CHANGELOG b/CHANGELOG index d012bd8b4c..6b50ef248e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add '_request' attribute to Transaction context * Delete translations on deletion only when model has translatable field * Remove MySQL backend * Add keyword attribute to button tag diff --git a/trytond/protocols/dispatcher.py b/trytond/protocols/dispatcher.py index 2d25add79b..d460561d9a 100644 --- a/trytond/protocols/dispatcher.py +++ b/trytond/protocols/dispatcher.py @@ -49,9 +49,13 @@ def login(request, database_name, user, parameters, language=None): except DatabaseOperationalError: logger.error('fail to connect to %s', database_name, exc_info=True) abort(404) + context = { + 'language': language, + '_request': request.context, + } try: session = security.login( - database_name, user, parameters, language=language) + database_name, user, parameters, context=context) code = 403 except RateLimitException: session = None @@ -68,7 +72,8 @@ def login(request, database_name, user, parameters, language=None): def logout(request, database_name): auth = request.authorization name = security.logout( - database_name, auth.get('userid'), auth.get('session')) + database_name, auth.get('userid'), auth.get('session'), + context={'_request': request.context}) logger.info('logout \'%s\' from %s using %s on database \'%s\'', name, request.remote_addr, request.scheme, database_name) return True @@ -97,11 +102,13 @@ def db_exist(request, database_name): return False -def db_list(*args): +def db_list(request, *args): if not config.getboolean('database', 'list'): raise Exception('AccessDenied') + context = {'_request': request.context} with Transaction().start( - None, 0, close=True, _nocache=True) as transaction: + None, 0, context=context, close=True, _nocache=True + ) as transaction: return transaction.database.list() @@ -159,6 +166,7 @@ def _dispatch(request, pool, *args, **kwargs): try: c_args, c_kwargs, transaction.context, transaction.timestamp \ = rpc.convert(obj, *args, **kwargs) + transaction.context['_request'] = request.context meth = getattr(obj, method) if (rpc.instantiate is None or not is_instance_method(obj, method)): @@ -187,8 +195,10 @@ def _dispatch(request, pool, *args, **kwargs): # Need to commit to unlock SQLite database transaction.commit() if request.authorization.type == 'session': + context = {'_request': request.context} try: - with Transaction().start(pool.database_name, 0) as transaction: + with Transaction().start( + pool.database_name, 0, context=context) as transaction: Session = pool.get('ir.session') Session.reset(request.authorization.get('session')) except DatabaseOperationalError: diff --git a/trytond/protocols/wrappers.py b/trytond/protocols/wrappers.py index 9dfccfec27..76eff6a9cd 100644 --- a/trytond/protocols/wrappers.py +++ b/trytond/protocols/wrappers.py @@ -62,12 +62,22 @@ class Request(_Request): return None if auth.type == 'session': user_id = security.check( - database_name, auth.get('userid'), auth.get('session')) + database_name, auth.get('userid'), auth.get('session'), + context={'_request': self.context}) else: user_id = security.login( database_name, auth.username, auth, cache=False) return user_id + @cached_property + def context(self): + return { + 'remote_addr': self.remote_addr, + 'http_host': self.environ.get('HTTP_HOST'), + 'scheme': self.scheme, + 'is_secure': self.is_secure, + } + def parse_authorization_header(value): if not value: diff --git a/trytond/security.py b/trytond/security.py index d911f87b8e..4b313fa021 100644 --- a/trytond/security.py +++ b/trytond/security.py @@ -15,9 +15,8 @@ def _get_pool(dbname): return pool -def login(dbname, loginname, parameters, cache=True, language=None): +def login(dbname, loginname, parameters, cache=True, context=None): DatabaseOperationalError = backend.get('DatabaseOperationalError') - context = {'language': language} for count in range(config.getint('database', 'retry'), -1, -1): with Transaction().start(dbname, 0, context=context) as transaction: pool = _get_pool(dbname) @@ -43,10 +42,10 @@ def login(dbname, loginname, parameters, cache=True, language=None): return -def logout(dbname, user, session): +def logout(dbname, user, session, context=None): DatabaseOperationalError = backend.get('DatabaseOperationalError') for count in range(config.getint('database', 'retry'), -1, -1): - with Transaction().start(dbname, 0): + with Transaction().start(dbname, 0, context=context): pool = _get_pool(dbname) Session = pool.get('ir.session') try: @@ -65,10 +64,10 @@ def logout(dbname, user, session): return name -def check(dbname, user, session): +def check(dbname, user, session, context=None): DatabaseOperationalError = backend.get('DatabaseOperationalError') for count in range(config.getint('database', 'retry'), -1, -1): - with Transaction().start(dbname, user) as transaction: + with Transaction().start(dbname, user, context=context) as transaction: pool = _get_pool(dbname) Session = pool.get('ir.session') try: