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.

129 lines
4.9 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016-2017 LasLabs Inc.
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. import mock
  5. from contextlib import contextmanager
  6. from odoo.tools.misc import mute_logger
  7. from odoo.tests.common import TransactionCase
  8. class EndTestException(Exception):
  9. """ It stops tests from continuing """
  10. pass
  11. class TestResUsers(TransactionCase):
  12. post_install = True
  13. at_install = False
  14. def setUp(self):
  15. super(TestResUsers, self).setUp()
  16. self.TestUser = self.env['res.users'].create({
  17. 'login': 'test_user',
  18. 'name': 'test_user',
  19. })
  20. @contextmanager
  21. def _mock_assets(self, assets=None):
  22. """ Multi patch names in `odoo.addons.auth_session_timeout.models.
  23. res_users` for mocking them.
  24. :param assets: The symbols in res_users that will be patched with
  25. MagicMock objects.
  26. """
  27. if assets is None:
  28. assets = ['http']
  29. patches = {name: mock.DEFAULT for name in assets}
  30. with mock.patch.multiple(
  31. 'odoo.addons.auth_session_timeout.models.res_users', **patches
  32. ) as mocks:
  33. yield mocks
  34. def _auth_timeout_check(self, http_mock):
  35. """ It wraps ``_auth_timeout_check`` for easier calling """
  36. self.db = mock.MagicMock()
  37. self.uid = mock.MagicMock()
  38. self.passwd = mock.MagicMock()
  39. self.path = '/this/is/a/test/path'
  40. get_filename = http_mock.root.session_store.get_session_filename
  41. get_filename.return_value = self.path
  42. return self.TestUser._auth_timeout_check()
  43. def test_session_validity_no_request(self):
  44. """ Tests what happens when the user being tested has not made any
  45. requests.
  46. """
  47. with self._mock_assets() as assets:
  48. assets['http'].request = False
  49. res = self._auth_timeout_check(assets['http'])
  50. self.assertFalse(res)
  51. def test_session_validity_gets_session_file(self):
  52. """ All the sessions a user generates are saved as a file in the
  53. filesystem by Werkzeug.
  54. This function makes sure that our `_auth_timeout_check` makes an
  55. attempt in fetching that file by the correct session id.
  56. """
  57. with self._mock_assets() as assets:
  58. store = assets['http'].root.session_store
  59. store.get_session_filename.side_effect = EndTestException
  60. with self.assertRaises(EndTestException):
  61. self._auth_timeout_check(assets['http'])
  62. store.get_session_filename.assert_called_once_with(
  63. assets['http'].request.session.sid,
  64. )
  65. def test_session_validity_logout(self):
  66. """ Forcefully expire an already existing session and see if the user
  67. is actually logged out.
  68. """
  69. with self._mock_assets(['http', 'getmtime', 'utime']) as assets:
  70. assets['getmtime'].return_value = 0
  71. self._auth_timeout_check(assets['http'])
  72. assets['http'].request.session.logout.assert_called_once_with(
  73. keep_db=True,
  74. )
  75. def test_session_validity_updates_utime(self):
  76. """ When a user makes a request, `_auth_timeout_check` is keeping the
  77. user's time of request by setting the access time of the session file
  78. using utime.
  79. This function asserts that the access time of the session file is set
  80. correctly.
  81. """
  82. with self._mock_assets(['http', 'getmtime', 'utime']) as assets:
  83. self._auth_timeout_check(assets['http'])
  84. assets['utime'].assert_called_once_with(
  85. assets['http'].root.session_store.get_session_filename(),
  86. None,
  87. )
  88. @mute_logger('odoo.addons.auth_session_timeout.models.res_users')
  89. def test_session_validity_os_error_guard(self):
  90. """ Make sure that when we get an OSError while trying to set up an
  91. access time the session is terminated immediately.
  92. """
  93. with self._mock_assets(['http', 'utime', 'getmtime']) as assets:
  94. assets['getmtime'].side_effect = OSError
  95. res = self._auth_timeout_check(assets['http'])
  96. self.assertFalse(res)
  97. def test_on_timeout_session_loggedout(self):
  98. """ Make sure that when the timeout has come, the user is actually
  99. logged out.
  100. """
  101. with self._mock_assets(['http', 'getmtime']) as assets:
  102. assets['getmtime'].return_value = 0
  103. assets['http'].request.env.user = self.TestUser
  104. assets['http'].request.session.uid = self.TestUser.id
  105. assets['http'].request.session.dbname = self.env.cr.dbname
  106. assets['http'].request.session.sid = '123'
  107. assets['http'].request.session.logout = mock.Mock()
  108. self.TestUser._compute_session_token('123')
  109. self.assertTrue(assets['http'].request.session.logout.called)