cherrypy-foundation 1.0.0__py3-none-any.whl → 1.0.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. cherrypy_foundation/components/ColorModes.jinja +4 -5
  2. cherrypy_foundation/components/Datatable.jinja +2 -2
  3. cherrypy_foundation/components/Datatable.js +2 -2
  4. cherrypy_foundation/components/Field.jinja +6 -16
  5. cherrypy_foundation/components/Fields.jinja +2 -0
  6. cherrypy_foundation/components/Typeahead.css +1 -6
  7. cherrypy_foundation/components/Typeahead.jinja +2 -2
  8. cherrypy_foundation/components/__init__.py +2 -2
  9. cherrypy_foundation/components/tests/test_static.py +1 -1
  10. cherrypy_foundation/error_page.py +17 -20
  11. cherrypy_foundation/flash.py +15 -17
  12. cherrypy_foundation/form.py +2 -2
  13. cherrypy_foundation/logging.py +2 -2
  14. cherrypy_foundation/passwd.py +2 -2
  15. cherrypy_foundation/plugins/db.py +9 -35
  16. cherrypy_foundation/plugins/ldap.py +38 -46
  17. cherrypy_foundation/plugins/restapi.py +1 -1
  18. cherrypy_foundation/plugins/scheduler.py +84 -208
  19. cherrypy_foundation/plugins/smtp.py +46 -78
  20. cherrypy_foundation/plugins/tests/test_db.py +4 -4
  21. cherrypy_foundation/plugins/tests/test_ldap.py +3 -76
  22. cherrypy_foundation/plugins/tests/test_scheduler.py +50 -58
  23. cherrypy_foundation/plugins/tests/test_smtp.py +7 -40
  24. cherrypy_foundation/tests/__init__.py +0 -72
  25. cherrypy_foundation/tests/test_error_page.py +1 -7
  26. cherrypy_foundation/tests/test_passwd.py +2 -2
  27. cherrypy_foundation/tools/auth.py +38 -59
  28. cherrypy_foundation/tools/auth_mfa.py +88 -89
  29. cherrypy_foundation/tools/errors.py +27 -0
  30. cherrypy_foundation/tools/i18n.py +153 -246
  31. cherrypy_foundation/tools/jinja2.py +13 -29
  32. cherrypy_foundation/tools/ratelimit.py +27 -37
  33. cherrypy_foundation/tools/secure_headers.py +5 -1
  34. cherrypy_foundation/tools/sessions_timeout.py +21 -23
  35. cherrypy_foundation/tools/tests/locales/en/LC_MESSAGES/messages.mo +0 -0
  36. cherrypy_foundation/tools/tests/locales/{de → en}/LC_MESSAGES/messages.po +2 -2
  37. cherrypy_foundation/tools/tests/test_auth.py +4 -21
  38. cherrypy_foundation/tools/tests/test_i18n.py +6 -81
  39. cherrypy_foundation/tools/tests/test_ratelimit.py +2 -2
  40. cherrypy_foundation/url.py +25 -25
  41. cherrypy_foundation/widgets.py +2 -2
  42. cherrypy_foundation-1.0.0a1.dist-info/METADATA +42 -0
  43. {cherrypy_foundation-1.0.0.dist-info → cherrypy_foundation-1.0.0a1.dist-info}/RECORD +46 -65
  44. {cherrypy_foundation-1.0.0.dist-info → cherrypy_foundation-1.0.0a1.dist-info}/WHEEL +1 -1
  45. cherrypy_foundation/components/Flash.jinja +0 -13
  46. cherrypy_foundation/components/LocaleSelection.jinja +0 -13
  47. cherrypy_foundation/components/LocaleSelection.js +0 -26
  48. cherrypy_foundation/plugins/tests/test_scheduler_db.py +0 -107
  49. cherrypy_foundation/sessions.py +0 -93
  50. cherrypy_foundation/tests/templates/test_flash.html +0 -9
  51. cherrypy_foundation/tests/templates/test_form.html +0 -16
  52. cherrypy_foundation/tests/templates/test_url.html +0 -15
  53. cherrypy_foundation/tests/test_flash.py +0 -61
  54. cherrypy_foundation/tests/test_form.py +0 -148
  55. cherrypy_foundation/tests/test_logging.py +0 -78
  56. cherrypy_foundation/tests/test_sessions.py +0 -89
  57. cherrypy_foundation/tests/test_url.py +0 -161
  58. cherrypy_foundation/tools/tests/components/Button.jinja +0 -2
  59. cherrypy_foundation/tools/tests/locales/de/LC_MESSAGES/messages.mo +0 -0
  60. cherrypy_foundation/tools/tests/templates/test_jinja2.html +0 -11
  61. cherrypy_foundation/tools/tests/templates/test_jinjax.html +0 -9
  62. cherrypy_foundation/tools/tests/templates/test_jinjax_i18n.html +0 -22
  63. cherrypy_foundation/tools/tests/test_auth_mfa.py +0 -369
  64. cherrypy_foundation/tools/tests/test_jinja2.py +0 -153
  65. cherrypy_foundation/tools/tests/test_secure_headers.py +0 -200
  66. cherrypy_foundation-1.0.0.dist-info/METADATA +0 -71
  67. {cherrypy_foundation-1.0.0.dist-info → cherrypy_foundation-1.0.0a1.dist-info}/licenses/LICENSE.md +0 -0
  68. {cherrypy_foundation-1.0.0.dist-info → cherrypy_foundation-1.0.0a1.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # Scheduler plugins for Cherrypy
2
- # Copyright (C) 2026 IKUS Software
2
+ # Copyright (C) 2022-2025 IKUS Software
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -14,87 +14,79 @@
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
 
17
- from datetime import datetime, timezone
18
- from threading import Event
17
+ """
18
+ Created on Oct 17, 2015
19
+
20
+ @author: Patrik Dufresne <patrik@ikus-soft.com>
21
+ """
22
+ import importlib.util
23
+ import unittest
24
+ from time import sleep
19
25
 
20
26
  import cherrypy
21
27
  from cherrypy.test import helper
22
28
 
23
- from .. import scheduler # noqa
24
-
25
- done = Event()
29
+ HAS_APSCHEDULER = importlib.util.find_spec("apscheduler") is not None
26
30
 
27
-
28
- def a_task(*args, **kwargs):
29
- done.set()
31
+ if HAS_APSCHEDULER:
32
+ from .. import scheduler # noqa
30
33
 
31
34
 
35
+ @unittest.skipUnless(HAS_APSCHEDULER, "apscheduler not installed")
32
36
  class SchedulerPluginTest(helper.CPWebCase):
33
37
  def setUp(self) -> None:
34
- done.clear()
35
- cherrypy.scheduler.remove_all_jobs()
38
+ self.called = False
36
39
  return super().setUp()
37
40
 
38
- def tearDown(self):
39
- return super().tearDown()
40
-
41
41
  @classmethod
42
42
  def setup_server(cls):
43
43
  pass
44
44
 
45
- def test_add_job(self):
46
- # Given a scheduled job
47
- scheduled = cherrypy.engine.publish(
48
- 'scheduler:add_job',
49
- a_task,
50
- name='custom_name',
51
- args=(1, 2, 3),
52
- kwargs={'foo': 'bar'},
53
- next_run_time=datetime.now(timezone.utc),
54
- misfire_grace_time=None,
55
- )
56
- self.assertTrue(scheduled)
57
- self.assertEqual('custom_name', scheduled[0].name)
58
- # When waiting for all jobs
59
- cherrypy.scheduler.wait_for_jobs()
60
- # Then the job is done
61
- self.assertTrue(done.is_set())
62
-
63
- def test_add_job_daily(self):
45
+ def test_schedule_job(self):
64
46
  # Given a scheduler with a specific number of jobs
65
- count = len(cherrypy.scheduler.get_jobs())
66
- # When scheduling a daily job.
67
- scheduled = cherrypy.engine.publish('scheduler:add_job_daily', '23:00', a_task, 1, 2, 3, foo=1, bar=2)
68
- # Then the job is scheduled
47
+ count = len(cherrypy.scheduler.list_jobs())
48
+
49
+ # Given a job schedule every seconds
50
+ def a_job(*args, **kwargs):
51
+ self.called = True
52
+
53
+ scheduled = cherrypy.engine.publish('schedule_job', '23:00', a_job, 1, 2, 3, foo=1, bar=2)
69
54
  self.assertTrue(scheduled)
70
- self.assertEqual('a_task', scheduled[0].name)
71
- # Then the number of jobs increase.
72
- self.assertEqual(count + 1, len(cherrypy.scheduler.get_jobs()))
55
+ self.assertEqual(count + 1, len(cherrypy.scheduler.list_jobs()))
73
56
 
74
- def test_add_job_now(self):
57
+ def test_scheduler_task(self):
75
58
  # Given a task
59
+
60
+ def a_task(*args, **kwargs):
61
+ self.called = True
62
+
76
63
  # When scheduling that task
77
- scheduled = cherrypy.engine.publish('scheduler:add_job_now', a_task, 1, 2, 3, foo=1, bar=2)
64
+ scheduled = cherrypy.engine.publish('schedule_task', a_task, 1, 2, 3, foo=1, bar=2)
78
65
  self.assertTrue(scheduled)
79
- # When waiting for all tasks
80
- cherrypy.scheduler.wait_for_jobs()
66
+ sleep(1)
67
+ while len(cherrypy.scheduler.list_tasks()) >= 1:
68
+ sleep(1)
81
69
  # Then the task get called
82
- self.assertTrue(done.is_set())
70
+ self.assertTrue(self.called)
83
71
 
84
- def test_remove_job(self):
72
+ def test_unschedule_job(self):
85
73
  # Given a scheduler with a specific number of jobs
86
- count = len(cherrypy.scheduler.get_jobs())
74
+ count = len(cherrypy.scheduler.list_jobs())
75
+
87
76
  # Given a job schedule every seconds
88
- cherrypy.engine.publish('scheduler:add_job_daily', '23:00', a_task, 1, 2, 3, foo=1, bar=2)
89
- # Then number of job increase
90
- self.assertEqual(count + 1, len(cherrypy.scheduler.get_jobs()))
91
- # When the job is unscheduled.
92
- cherrypy.engine.publish('scheduler:remove_job', a_task)
93
- # Then the number of job decrease.
94
- self.assertEqual(count, len(cherrypy.scheduler.get_jobs()))
95
-
96
- def test_remove_job_with_invalid_job(self):
77
+ def a_job(*args, **kwargs):
78
+ self.called = True
79
+
80
+ cherrypy.engine.publish('schedule_job', '23:00', a_job, 1, 2, 3, foo=1, bar=2)
81
+ self.assertEqual(count + 1, len(cherrypy.scheduler.list_jobs()))
82
+ cherrypy.engine.publish('unschedule_job', a_job)
83
+ self.assertEqual(count, len(cherrypy.scheduler.list_jobs()))
84
+
85
+ def test_unschedule_job_with_invalid_job(self):
97
86
  # Given an unschedule job
87
+ def a_job(*args, **kwargs):
88
+ self.called = True
89
+
98
90
  # When unscheduling an invalid job
99
- cherrypy.engine.publish('scheduler:remove_job', a_task)
100
- # Then an error is not raised.
91
+ cherrypy.engine.publish('unschedule_job', a_job)
92
+ # Then no error are raised
@@ -1,5 +1,5 @@
1
1
  # SMTP Plugins for cherrypy
2
- # Copyright (C) 2022-2026 IKUS Software
2
+ # Copyright (C) 2022-2025 IKUS Software
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -18,7 +18,6 @@ from unittest import mock, skipUnless
18
18
 
19
19
  import cherrypy
20
20
  from cherrypy.test import helper
21
- from parameterized import parameterized
22
21
 
23
22
  from .. import smtp # noqa
24
23
 
@@ -64,15 +63,12 @@ class SmtpPluginTest(helper.CPWebCase):
64
63
 
65
64
  @skipUnless(hasattr(cherrypy, 'scheduler'), reason='Required scheduler')
66
65
  def test_queue_mail(self):
67
- with mock.patch(smtp.__name__ + '.smtplib') as smtplib:
68
- # Given a mail being queued.
69
- cherrypy.engine.publish('queue_mail', to='target@test.com', subject='subjet', message='body')
70
- # When waiting for all task to be processed
71
- cherrypy.scheduler.wait_for_jobs()
72
- # Then smtplib is called to send the mail.
73
- smtplib.SMTP.assert_called_once_with('__default__', 25)
74
- smtplib.SMTP.return_value.send_message.assert_called_once_with(mock.ANY)
75
- smtplib.SMTP.return_value.quit.assert_called_once_with()
66
+ # Given a paused scheduler plugin
67
+ cherrypy.scheduler._scheduler.pause()
68
+ # When queueing a email
69
+ cherrypy.engine.publish('queue_mail', to='target@test.com', subject='subjet', message='body')
70
+ # Then a new job get schedule
71
+ self.assertEqual(1, len(cherrypy.scheduler.list_tasks()))
76
72
 
77
73
  def test_html2plaintext(self):
78
74
  """
@@ -109,32 +105,3 @@ Here is the link [1] you wanted.
109
105
  self.assertEqual(
110
106
  'test2@test.com, TEST3 <test3@test.com>', smtp._formataddr(['test2@test.com', ('TEST3', 'test3@test.com')])
111
107
  )
112
-
113
- @parameterized.expand(
114
- [
115
- (None, None, None),
116
- (None, 'test2@test.com', 'test2@test.com'),
117
- ('test2@test.com', None, 'test2@test.com'),
118
- ('test1@test.com', 'test2@test.com', 'test1@test.com, test2@test.com'),
119
- ]
120
- )
121
- def test_with_bcc(self, smtp_bcc, bcc, expected_bcc):
122
- # Given a valid smtp server
123
- with mock.patch(smtp.__name__ + '.smtplib') as smtplib:
124
- # Given bcc is defined at plugin level.
125
- cherrypy.smtp.bcc = smtp_bcc
126
- # When publishing a send_mail with Bcc
127
- cherrypy.engine.publish(
128
- 'send_mail',
129
- to=('A name', 'target@test.com'),
130
- subject='subjet',
131
- message='body',
132
- bcc=bcc,
133
- )
134
- # Then message is sent
135
- smtplib.SMTP.assert_called_once_with('__default__', 25)
136
- smtplib.SMTP.return_value.send_message.assert_called_once_with(mock.ANY)
137
- msg = smtplib.SMTP.return_value.send_message.call_args.args[0]
138
- smtplib.SMTP.return_value.quit.assert_called_once_with()
139
- # Message include our expected Bcc
140
- self.assertEqual(expected_bcc, msg['Bcc'])
@@ -1,72 +0,0 @@
1
- # Cherrypy-foundation
2
- # Copyright (C) 2026 IKUS Software
3
- #
4
- # This program is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
-
17
- import os
18
- import tempfile
19
- import unittest
20
- from contextlib import contextmanager
21
-
22
- from selenium import webdriver
23
-
24
-
25
- class SeleniumUnitTest:
26
-
27
- @property
28
- def _session_id(self):
29
- if hasattr(self, 'cookies') and self.cookies:
30
- for unused, value in self.cookies:
31
- for part in value.split(';'):
32
- key, unused, value = part.partition('=')
33
- if key == 'session_id':
34
- return value
35
-
36
- @contextmanager
37
- def selenium(self, headless=True, implicitly_wait=3):
38
- """
39
- Decorator to load selenium for a test.
40
- """
41
- # Skip selenium test is display is not available.
42
- if not os.environ.get('DISPLAY', False):
43
- raise unittest.SkipTest("selenium require a display")
44
- # Start selenium driver
45
- options = webdriver.ChromeOptions()
46
- if headless:
47
- options.add_argument('--headless')
48
- options.add_argument('--disable-gpu')
49
- options.add_argument('--window-size=1280,800')
50
- options.add_argument('--no-sandbox')
51
- options.add_argument('--disable-dev-shm-usage')
52
- options.add_argument('--lang=en-US')
53
- driver = webdriver.Chrome(options=options)
54
- try:
55
- # If logged in, reuse the same session id.
56
- if self._session_id:
57
- driver.get(f'{self.baseurl}/login/')
58
- driver.add_cookie({"name": "session_id", "value": self.session_id})
59
- # Configure download folder
60
- download = os.path.join(os.path.expanduser('~'), 'Downloads')
61
- os.makedirs(download, exist_ok=True)
62
- self._selenium_download_dir = tempfile.mkdtemp(dir=download, prefix='selenium-download-')
63
- driver.execute_cdp_cmd(
64
- 'Page.setDownloadBehavior', {'behavior': 'allow', 'downloadPath': self._selenium_download_dir}
65
- )
66
- # Set default wait.
67
- driver.implicitly_wait(implicitly_wait)
68
- yield driver
69
- finally:
70
- # Code to release resource, e.g.:
71
- driver.close()
72
- driver = None
@@ -1,5 +1,5 @@
1
1
  # CherryPy
2
- # Copyright (C) 2026 IKUS Software
2
+ # Copyright (C) 2025 IKUS Software
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -29,10 +29,6 @@ class Root:
29
29
 
30
30
  @cherrypy.expose
31
31
  def not_found(self):
32
- raise cherrypy.NotFound()
33
-
34
- @cherrypy.expose
35
- def not_found_custom(self):
36
32
  raise cherrypy.HTTPError(404, message='My error message')
37
33
 
38
34
  @cherrypy.expose
@@ -64,8 +60,6 @@ class ErrorPageTest(helper.CPWebCase):
64
60
 
65
61
  @parameterized.expand(
66
62
  [
67
- ('/not_found', '<p>Nothing matches the given URI</p>'),
68
- ('/not_found_custom', '<p>My error message</p>'),
69
63
  ('/html_error', '<p>My error message</p>'),
70
64
  ('/json_error', '{"message": "json error message", "status": "400 Bad Request"}'),
71
65
  ('/text_error', 'text error message'),
@@ -1,5 +1,5 @@
1
- # Cherrypy-foundation
2
- # Copyright (C) 2026 IKUS Software
1
+ # CherryPy Foundation
2
+ # Copyright (C) 2025 IKUS Software inc.
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -1,5 +1,5 @@
1
1
  # Authentication tools for cherrypy
2
- # Copyright (C) 2026 IKUS Software
2
+ # Copyright (C) 2025 IKUS Software
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -20,8 +20,6 @@ import urllib.parse
20
20
 
21
21
  import cherrypy
22
22
 
23
- from cherrypy_foundation.sessions import session_lock
24
-
25
23
  AUTH_LAST_PASSWORD_AT = '_auth_last_password_at'
26
24
  AUTH_METHOD = '_auth_method'
27
25
  AUTH_ORIGINAL_URL = '_auth_original_url'
@@ -31,6 +29,9 @@ AUTH_DEFAULT_SESSION_KEY = "_auth_session_key"
31
29
  AUTH_DEFAULT_REAUTH_TIMEOUT = 60 # minutes
32
30
 
33
31
 
32
+ logger = logging.getLogger(__name__)
33
+
34
+
34
35
  class AuthManager(cherrypy.Tool):
35
36
  """
36
37
  CherryPy tool handling authentication.
@@ -73,17 +74,17 @@ class AuthManager(cherrypy.Tool):
73
74
  if not hasattr(cherrypy.serving, 'session'):
74
75
  return
75
76
  # Check if a user_key is stored in session.
76
- with session_lock() as session:
77
- user_key = session.get(self._session_user_key())
78
- if not user_key:
79
- return
77
+ session = cherrypy.serving.session
78
+ user_key = session.get(self._session_user_key())
79
+ if not user_key:
80
+ return
80
81
 
81
- last = session.get(AUTH_LAST_PASSWORD_AT)
82
- if last is None:
83
- return # never had a password login in this session
84
- timeout = self._reauth_timeout_minutes()
85
- if (last + datetime.timedelta(minutes=timeout)) < session.now():
86
- return
82
+ last = session.get(AUTH_LAST_PASSWORD_AT)
83
+ if last is None:
84
+ return # never had a password login in this session
85
+ timeout = self._reauth_timeout_minutes()
86
+ if (last + datetime.timedelta(minutes=timeout)) < session.now():
87
+ return
87
88
 
88
89
  # Mark request as authenticated by key; user object will be resolved later.
89
90
  cherrypy.serving.request.login = user_key
@@ -101,12 +102,7 @@ class AuthManager(cherrypy.Tool):
101
102
  try:
102
103
  currentuser = user_from_key_func(user_key)
103
104
  except Exception:
104
- cherrypy.log(
105
- f'unexpected error searching for user_key={user_key}',
106
- context='AUTH',
107
- severity=logging.ERROR,
108
- traceback=True,
109
- )
105
+ logger.exception('error while resolving user from key')
110
106
  currentuser = None
111
107
 
112
108
  if currentuser:
@@ -126,7 +122,7 @@ class AuthManager(cherrypy.Tool):
126
122
  Validate credentials with configured checkers; on success, call login_with_result.
127
123
  """
128
124
  if not login or not password:
129
- cherrypy.log('authentication failed reason=empty_credentials', context='AUTH', severity=logging.WARNING)
125
+ logger.warning('empty login or password provided')
130
126
  return None
131
127
  # Validate credentials using checkpassword function(s).
132
128
  conf = self._merged_args()
@@ -147,24 +143,15 @@ class AuthManager(cherrypy.Tool):
147
143
  login, user_info = login, None
148
144
  # If authentication is successful, initiate login process.
149
145
  return self.login_with_result(login=login, user_info=user_info)
150
- except Exception:
151
- cherrypy.log(
152
- f'unexpected error checking password login={login} checkpassword={func.__qualname__} - continue with next function',
153
- context='AUTH',
154
- severity=logging.ERROR,
155
- traceback=True,
146
+ except Exception as e:
147
+ logger.exception(
148
+ 'unexpected error during authentication for [%s] with [%s]: %s', login, func.__qualname__, e
156
149
  )
157
150
  # If we reach here, authentication failed
158
151
  if hasattr(cherrypy.serving, 'session'):
159
- with session_lock() as session:
160
- session.regenerate() # Prevent session analysis
152
+ cherrypy.serving.session.regenerate() # Prevent session analysis
161
153
 
162
- remote_ip = cherrypy.serving.request.remote.ip
163
- cherrypy.log(
164
- f'authentication failed login={login} ip={remote_ip} reason=wrong_credentials',
165
- context='AUTH',
166
- severity=logging.WARNING,
167
- )
154
+ logger.warning('Failed login attempt for user=%s from ip=%s', login, cherrypy.serving.request.remote.ip)
168
155
 
169
156
  return None
170
157
 
@@ -179,18 +166,11 @@ class AuthManager(cherrypy.Tool):
179
166
  try:
180
167
  user_key, userobj = user_lookup_func(login=login, user_info=user_info or {})
181
168
  except Exception:
182
- cherrypy.log(
183
- f"unexpected error searching user login={login} user_info={user_info}",
184
- context='AUTH',
185
- severity=logging.ERROR,
186
- traceback=True,
187
- )
169
+ logger.exception('failed to lookup user object for login=%s', login)
188
170
  return None
189
171
 
190
172
  if not userobj:
191
- cherrypy.log(
192
- f"authentication failed login={login} reason=not_found", context='AUTH', severity=logging.WARNING
193
- )
173
+ logger.warning('failed to lookup user object for login=%s', login)
194
174
  return None
195
175
 
196
176
  # Notify plugins about user login
@@ -198,13 +178,13 @@ class AuthManager(cherrypy.Tool):
198
178
 
199
179
  # Store in session
200
180
  if hasattr(cherrypy.serving, 'session'):
201
- with session_lock() as session:
202
- session_user_key = self._session_user_key()
203
- session[session_user_key] = user_key
204
- session[AUTH_METHOD] = auth_method
205
- session[AUTH_LAST_PASSWORD_AT] = session.now()
206
- # Generate a new session id
207
- session.regenerate()
181
+ session = cherrypy.serving.session
182
+ session_user_key = self._session_user_key()
183
+ session[session_user_key] = user_key
184
+ session[AUTH_METHOD] = auth_method
185
+ session[AUTH_LAST_PASSWORD_AT] = session.now()
186
+ # Generate a new session id
187
+ session.regenerate()
208
188
 
209
189
  # When authenticated, store user_key in request.
210
190
  cherrypy.serving.request.login = user_key
@@ -216,9 +196,9 @@ class AuthManager(cherrypy.Tool):
216
196
  """
217
197
  Clear session data and generate a new session id.
218
198
  """
219
- with session_lock() as session:
220
- session.clear()
221
- session.regenerate()
199
+ session = cherrypy.serving.session
200
+ session.clear()
201
+ session.regenerate()
222
202
 
223
203
  def get_original_url(self):
224
204
  """
@@ -226,16 +206,15 @@ class AuthManager(cherrypy.Tool):
226
206
  """
227
207
  if not hasattr(cherrypy.serving, 'session'):
228
208
  return None
229
- with session_lock() as session:
230
- return session.get(AUTH_ORIGINAL_URL)
209
+ return cherrypy.serving.session.get(AUTH_ORIGINAL_URL)
231
210
 
232
211
  def get_user_key(self):
233
212
  """Return the last username."""
234
213
  if not hasattr(cherrypy.serving, 'session'):
235
214
  return False
215
+ session = cherrypy.serving.session
236
216
  session_user_key = self._session_user_key()
237
- with session_lock() as session:
238
- return session.get(session_user_key)
217
+ return session.get(session_user_key)
239
218
 
240
219
  def redirect_to_original_url(self):
241
220
  # Redirect user to original URL
@@ -256,8 +235,8 @@ class AuthManager(cherrypy.Tool):
256
235
  query_string = request.query_string
257
236
 
258
237
  # Store value in session
259
- with session_lock() as session:
260
- session[AUTH_ORIGINAL_URL] = cherrypy.url(original_url, qs=query_string, base='')
238
+ session = cherrypy.serving.session
239
+ session[AUTH_ORIGINAL_URL] = cherrypy.url(original_url, qs=query_string, base='')
261
240
 
262
241
 
263
242
  cherrypy.tools.auth = AuthManager()