You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.4 KiB

  1. # -*- coding: utf-8 -*-
  2. # (c) 2015 ACSONE SA/NV, Dhinesh D
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. import logging
  5. from os.path import getmtime
  6. from time import time
  7. from os import utime
  8. from odoo import api, http, models
  9. _logger = logging.getLogger(__name__)
  10. class ResUsers(models.Model):
  11. _inherit = 'res.users'
  12. @api.model_cr_context
  13. def _auth_timeout_get_ignored_urls(self):
  14. """Pluggable method for calculating ignored urls
  15. Defaults to stored config param
  16. """
  17. params = self.env['ir.config_parameter']
  18. return params._auth_timeout_get_parameter_ignored_urls()
  19. @api.model_cr_context
  20. def _auth_timeout_deadline_calculate(self):
  21. """Pluggable method for calculating timeout deadline
  22. Defaults to current time minus delay using delay stored as config
  23. param.
  24. """
  25. params = self.env['ir.config_parameter']
  26. delay = params._auth_timeout_get_parameter_delay()
  27. if delay <= 0:
  28. return False
  29. return time() - delay
  30. @api.model_cr_context
  31. def _auth_timeout_session_terminate(self, session):
  32. """Pluggable method for terminating a timed-out session
  33. This is a late stage where a session timeout can be aborted.
  34. Useful if you want to do some heavy checking, as it won't be
  35. called unless the session inactivity deadline has been reached.
  36. Return:
  37. True: session terminated
  38. False: session timeout cancelled
  39. """
  40. if session.db and session.uid:
  41. session.logout(keep_db=True)
  42. return True
  43. @api.model_cr_context
  44. def _auth_timeout_check(self):
  45. """Perform session timeout validation and expire if needed."""
  46. if not http.request:
  47. return
  48. session = http.request.session
  49. # Calculate deadline
  50. deadline = self._auth_timeout_deadline_calculate()
  51. # Check if past deadline
  52. expired = False
  53. if deadline is not False:
  54. path = http.root.session_store.get_session_filename(session.sid)
  55. try:
  56. expired = getmtime(path) < deadline
  57. except OSError as e:
  58. _logger.exception(
  59. 'Exception reading session file modified time.',
  60. )
  61. # Force expire the session. Will be resolved with new session.
  62. expired = True
  63. # Try to terminate the session
  64. terminated = False
  65. if expired:
  66. terminated = self._auth_timeout_session_terminate(session)
  67. # If session terminated, all done
  68. if terminated:
  69. return
  70. # Else, conditionally update session modified and access times
  71. ignored_urls = self._auth_timeout_get_ignored_urls()
  72. if http.request.httprequest.path not in ignored_urls:
  73. if 'path' not in locals():
  74. path = http.root.session_store.get_session_filename(
  75. session.sid,
  76. )
  77. try:
  78. utime(path, None)
  79. except OSError as e:
  80. _logger.exception(
  81. 'Exception updating session file access/modified times.',
  82. )
  83. @classmethod
  84. def check(cls, *args, **kwargs):
  85. res = super(ResUsers, cls).check(*args, **kwargs)
  86. http.request.env.user._auth_timeout_check()
  87. return res