|
| 1 | +import logging |
| 2 | + |
| 3 | +from odoo import api, fields, models |
| 4 | +from odoo.http import request |
| 5 | + |
| 6 | +_logger = logging.getLogger(__name__) |
| 7 | + |
| 8 | +SESSION_TIMEOUT_DELAY = "inactive_session_timeout_seconds" |
| 9 | +SESSION_TIMEOUT_ACTIVE = "inactive_session_timeout_active" |
| 10 | + |
| 11 | + |
| 12 | +class IrConfigParameter(models.Model): |
| 13 | + _inherit = "ir.config_parameter" |
| 14 | + |
| 15 | + def write(self, values): |
| 16 | + result = super().write(values) |
| 17 | + if SESSION_TIMEOUT_DELAY in values or SESSION_TIMEOUT_ACTIVE in values: |
| 18 | + self.env.registry.clear_cache() |
| 19 | + _logger.info("Session config cache cleared due to session timeout setting update.") |
| 20 | + return result |
| 21 | + |
| 22 | + @api.model |
| 23 | + def _get_session_config(self): |
| 24 | + config = self.sudo() |
| 25 | + timeout = int(config.get_param(SESSION_TIMEOUT_DELAY, default="7200")) |
| 26 | + active = config.get_param(SESSION_TIMEOUT_ACTIVE, default="False") == "True" |
| 27 | + return { |
| 28 | + SESSION_TIMEOUT_DELAY: timeout, |
| 29 | + SESSION_TIMEOUT_ACTIVE: active, |
| 30 | + } |
| 31 | + |
| 32 | + |
| 33 | +class IrHttp(models.AbstractModel): |
| 34 | + _inherit = "ir.http" |
| 35 | + |
| 36 | + @classmethod |
| 37 | + def _authenticate(cls, endpoint): |
| 38 | + result = super()._authenticate(endpoint=endpoint) |
| 39 | + if ( |
| 40 | + request |
| 41 | + and request.session |
| 42 | + and request.session.uid |
| 43 | + and not request.env["res.users"].browse(request.session.uid)._is_public() |
| 44 | + ): |
| 45 | + if request.httprequest.path: |
| 46 | + last_activity = request.session.get("last_activity") |
| 47 | + current_time = fields.Datetime.now() |
| 48 | + if last_activity and last_activity < current_time: |
| 49 | + request.env.user._handle_session_timeout(last_activity, current_time) |
| 50 | + else: |
| 51 | + request.session["last_activity"] = current_time |
| 52 | + |
| 53 | + return result |
| 54 | + |
| 55 | + |
| 56 | +class ResUsers(models.Model): |
| 57 | + _inherit = "res.users" |
| 58 | + |
| 59 | + def _is_session_expired(self, last_activity, current_time, timeout_duration): |
| 60 | + elapsed_seconds = (current_time - last_activity).total_seconds() |
| 61 | + return elapsed_seconds > timeout_duration |
| 62 | + |
| 63 | + def _logout_user_session(self): |
| 64 | + if request.session.db and request.session.uid: |
| 65 | + request.session.logout(keep_db=True) |
| 66 | + return True |
| 67 | + |
| 68 | + def _handle_session_timeout(self, last_activity, current_time): |
| 69 | + session_config = self.env["ir.config_parameter"].sudo()._get_session_config() |
| 70 | + is_timeout_active = session_config.get("inactive_session_timeout_active", False) |
| 71 | + |
| 72 | + if not is_timeout_active: |
| 73 | + request.session["last_activity"] = current_time |
| 74 | + return |
| 75 | + |
| 76 | + timeout_duration = session_config.get("inactive_session_timeout_seconds", 7200) |
| 77 | + if self._is_session_expired(last_activity, current_time, timeout_duration): |
| 78 | + self._logout_user_session() |
| 79 | + else: |
| 80 | + request.session["last_activity"] = current_time |
0 commit comments