After the removal the loop must be broken and if no session has been removed it should log an error message. issue7852 review74421002
140 lines
5.0 KiB
Python
140 lines
5.0 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
import logging
|
|
|
|
from trytond.pool import Pool
|
|
from trytond.config import config
|
|
from trytond.transaction import Transaction
|
|
from trytond import backend
|
|
from trytond.exceptions import LoginException, RateLimitException
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _get_pool(dbname):
|
|
database_list = Pool.database_list()
|
|
pool = Pool(dbname)
|
|
if dbname not in database_list:
|
|
pool.init()
|
|
return pool
|
|
|
|
|
|
def _get_remote_addr(context):
|
|
if context and '_request' in context:
|
|
return context['_request'].get('remote_addr')
|
|
|
|
|
|
def login(dbname, loginname, parameters, cache=True, context=None):
|
|
DatabaseOperationalError = backend.get('DatabaseOperationalError')
|
|
for count in range(config.getint('database', 'retry'), -1, -1):
|
|
with Transaction().start(dbname, 0, context=context) as transaction:
|
|
pool = _get_pool(dbname)
|
|
User = pool.get('res.user')
|
|
try:
|
|
user_id = User.get_login(loginname, parameters)
|
|
break
|
|
except DatabaseOperationalError:
|
|
if count:
|
|
continue
|
|
raise
|
|
except (LoginException, RateLimitException):
|
|
# Let's store any changes done
|
|
transaction.commit()
|
|
raise
|
|
session = None
|
|
if user_id:
|
|
if not cache:
|
|
session = user_id
|
|
else:
|
|
with Transaction().start(dbname, user_id):
|
|
Session = pool.get('ir.session')
|
|
session = user_id, Session.new()
|
|
logger.info("login succeeded for '%s' from '%s' on database '%s'",
|
|
loginname, _get_remote_addr(context), dbname)
|
|
else:
|
|
logger.error("login failed for '%s' from '%s' on database '%s'",
|
|
loginname, _get_remote_addr(context), dbname)
|
|
return 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, context=context):
|
|
pool = _get_pool(dbname)
|
|
Session = pool.get('ir.session')
|
|
try:
|
|
name = Session.remove(session)
|
|
break
|
|
except DatabaseOperationalError:
|
|
if count:
|
|
continue
|
|
raise
|
|
if name:
|
|
logger.info("logout for '%s' from '%s' on database '%s'",
|
|
name, _get_remote_addr(context), dbname)
|
|
else:
|
|
logger.error("logout failed for '%s' from '%s' on database '%s'",
|
|
user, _get_remote_addr(context), dbname)
|
|
|
|
|
|
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, context=context) as transaction:
|
|
pool = _get_pool(dbname)
|
|
Session = pool.get('ir.session')
|
|
try:
|
|
find = Session.check(user, session)
|
|
break
|
|
except DatabaseOperationalError:
|
|
if count:
|
|
continue
|
|
raise
|
|
finally:
|
|
transaction.commit()
|
|
if find is None:
|
|
logger.error("session failed for '%s' from '%s' on database '%s'",
|
|
user, _get_remote_addr(context), dbname)
|
|
return
|
|
elif not find:
|
|
logger.info("session expired for '%s' from '%s' on database '%s'",
|
|
user, _get_remote_addr(context), dbname)
|
|
return
|
|
else:
|
|
logger.debug("session valid for '%s' from '%s' on database '%s'",
|
|
user, _get_remote_addr(context), dbname)
|
|
return user
|
|
|
|
|
|
def check_timeout(dbname, user, session, context=None):
|
|
DatabaseOperationalError = backend.get('DatabaseOperationalError')
|
|
for count in range(config.getint('database', 'retry'), -1, -1):
|
|
with Transaction().start(dbname, user, context=context) as transaction:
|
|
pool = _get_pool(dbname)
|
|
Session = pool.get('ir.session')
|
|
try:
|
|
valid = Session.check_timeout(user, session)
|
|
break
|
|
except DatabaseOperationalError:
|
|
if count:
|
|
continue
|
|
raise
|
|
finally:
|
|
transaction.commit()
|
|
if not valid:
|
|
logger.info("session timeout for '%s' from '%s' on database '%s'",
|
|
user, _get_remote_addr(context), dbname)
|
|
return valid
|
|
|
|
|
|
def reset(dbname, session, context):
|
|
DatabaseOperationalError = backend.get('DatabaseOperationalError')
|
|
try:
|
|
with Transaction().start(dbname, 0, context=context):
|
|
pool = _get_pool(dbname)
|
|
Session = pool.get('ir.session')
|
|
Session.reset(session)
|
|
except DatabaseOperationalError:
|
|
logger.debug('Reset session failed', exc_info=True)
|