Opened 7 weeks ago
Last modified 3 weeks ago
#13792 assigned defect
AttributeError: is_authenticated
Reported by: | Dirk Stöcker | Owned by: | Jun Omae |
---|---|---|---|
Priority: | normal | Milestone: | 1.6.1 |
Component: | general | Version: | 1.6 |
Severity: | normal | Keywords: | |
Cc: | Branch: | ||
Release Notes: | |||
API Changes: | |||
Internal Changes: |
Description (last modified by )
Traceback (most recent call last): File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 609, in dispatch_request dispatcher.dispatch(req) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 301, in dispatch raise e File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 210, in dispatch chosen_handler = self._get_valid_default_handler(req) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 337, in _get_valid_default_handler name = req.session.get('default_handler') File "/usr/local/lib/python3.10/dist-packages/trac/web/api.py", line 661, in __getattr__ value = self.callbacks[name](self) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 364, in _get_session return Session(self.env, req) File "/usr/local/lib/python3.10/dist-packages/trac/web/session.py", line 266, in __init__ if not req.is_authenticated: File "/usr/local/lib/python3.10/dist-packages/trac/web/api.py", line 664, in __getattr__ raise AttributeError(name) AttributeError: is_authenticated
We got multiple reports since Trac 1.6 which report an error which is only temporary and wasn't reproducible for us.
Original reports and duplicates here: https://josm.openstreetmap.de/ticket/23394
Log shows 116 entries since May 2024.
I don't understand the @lazy stuff in python and found no good description, so I can't debug it myself.
Attachments (0)
Change History (10)
comment:1 by , 7 weeks ago
Description: | modified (diff) |
---|
comment:2 by , 7 weeks ago
Milestone: | → 1.6.1 |
---|---|
Owner: | set to |
Status: | new → assigned |
comment:3 by , 7 weeks ago
Unable to reproduce it to me.
Hmm, I'm considering that AttributeError
was raised from req.authname
in req.is_authenticated
. So that, it is probably caused by LoginModule.authenticate
(in Trac or th:AccountManagerPlugin).
-
trac/web/api.py
diff --git a/trac/web/api.py b/trac/web/api.py index 7f8b59bdc..fb46051e6 100644
a b class Request(object): 685 685 def __getattr__(self, name): 686 686 """Performs lazy attribute lookup by delegating to the functions in the 687 687 callbacks dictionary.""" 688 if name in self.callbacks: 689 value = self.callbacks[name](self) 690 setattr(self, name, value) 691 return value 688 try: 689 if name in self.callbacks: 690 value = self.callbacks[name](self) 691 setattr(self, name, value) 692 return value 693 except AttributeError as e: 694 raise ValueError('AttributeError caught while resolving %s ' 695 'attribute' % name) 692 696 raise AttributeError(name) 693 697 694 698 def __repr__(self):
comment:4 by , 6 weeks ago
Why do you believe it is the if? Line 664 is raise AttributeError(name)
which also matches the error. So that would be the line after your change.
My interpretation is that Request.__getattr__("is_authenticated")
is called instead of Request.is_authenticated()
. But as said, I don't fully understand the programm flow yet, but at east I found the @lazy code which it seems mainly caches the call result.
comment:5 by , 6 weeks ago
Demonstration:
>>> from trac.web.api import Request >>> environ = {'SERVER_PORT': '80', 'SERVER_NAME': 'localhost', 'wsgi.url_scheme': 'http'} >>> start_response = lambda: () >>> req = Request(environ, start_response) >>> def autenticate(req): ... raise AttributeError('from autenticate') ... >>> req.callbacks['authname'] = autenticate >>> req.authname Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 689, in __getattr__ value = self.callbacks[name](self) File "<stdin>", line 2, in autenticate AttributeError: from autenticate >>> req.is_authenticated Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 692, in __getattr__ raise AttributeError(name) AttributeError: is_authenticated
- Read
req.is_authenticated
attribute - Read
req.authname
in theis_authenticated
method - The callback for
authname
raisesAttributeError
is_authenticated
method raises theAttributeError
- Python interpreter tries to resolve
is_authenticated
from__getattr__
becauseAttributeError
is raised fromis_authenticated
AttributeError(name)
is raised becauseis_authenticated
is not in thecallbacks
- We received the
AttributeError
from__getattr__
Applying the patch in comment:3 and the following patch:
-
trac/util/__init__.py
diff --git a/trac/util/__init__.py b/trac/util/__init__.py index f4804e01b..3cb400719 100644
a b class lazy(object): 1298 1298 functools.update_wrapper(self, fn) 1299 1299 1300 1300 def __get__(self, instance, owner): 1301 if instance is None: 1302 return self 1303 if self.fn.__name__ in instance.__dict__: 1304 return instance.__dict__[self.fn.__name__] 1305 result = self.fn(instance) 1306 instance.__dict__[self.fn.__name__] = result 1307 return result 1301 try: 1302 if instance is None: 1303 return self 1304 if self.fn.__name__ in instance.__dict__: 1305 return instance.__dict__[self.fn.__name__] 1306 result = self.fn(instance) 1307 instance.__dict__[self.fn.__name__] = result 1308 return result 1309 except AttributeError: 1310 raise ValueError('AttributeError caught while resolving %s ' 1311 'attribute' % self.fn.__name__) 1308 1312 1309 1313 def __set__(self, instance, value): 1310 1314 instance.__dict__[self.fn.__name__] = value
After the patch, trying demonstration code:
>>> req.authname Traceback (most recent call last): File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 690, in __getattr__ value = self.callbacks[name](self) File "<stdin>", line 2, in autenticate AttributeError: from autenticate During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 694, in __getattr__ raise ValueError('AttributeError caught while resolving %s ' ValueError: AttributeError caught while resolving authname attribute >>> req.is_authenticated Traceback (most recent call last): File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 690, in __getattr__ value = self.callbacks[name](self) File "<stdin>", line 2, in autenticate AttributeError: from autenticate During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/jun66j5/src/tracdev/git/trac/util/__init__.py", line 1306, in __get__ result = self.fn(instance) File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 713, in is_authenticated return self.authname and self.authname != 'anonymous' File "/home/jun66j5/src/tracdev/git/trac/web/api.py", line 694, in __getattr__ raise ValueError('AttributeError caught while resolving %s ' ValueError: AttributeError caught while resolving authname attribute >>>
comment:7 by , 6 weeks ago
It seems you're right and this may be caused by auth manager plugin.
Traceback (most recent call last): File "/usr/local/lib/python3.10/dist-packages/trac/web/api.py", line 662, in __getattr__ value = self.callbacks[name](self) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 180, in authenticate authname = authenticator.authenticate(req) File "/usr/local/lib/python3.10/dist-packages/acct_mgr/util.py", line 54, in wrap return func(self, *args, **kwds) File "/usr/local/lib/python3.10/dist-packages/acct_mgr/web_ui.py", line 488, in authenticate return super(LoginModule, self).authenticate(req) File "/usr/local/lib/python3.10/dist-packages/trac/web/auth.py", line 97, in authenticate authname = self._get_name_for_cookie(req, File "/usr/local/lib/python3.10/dist-packages/acct_mgr/web_ui.py", line 596, in _get_name_for_cookie cookie.value = hex_entropy() AttributeError: can't set attribute 'value' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 609, in dispatch_request dispatcher.dispatch(req) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 301, in dispatch raise e File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 214, in dispatch chosen_handler = self._pre_process_request(req, chosen_handler) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 456, in _pre_process_request chosen_handler = filter_.pre_process_request(req, chosen_handler) File "/usr/local/lib/python3.10/dist-packages/acct_mgr/api.py", line 469, in pre_process_request if not req.session.authenticated or 'ACCTMGR_USER_ADMIN' in req.perm: File "/usr/local/lib/python3.10/dist-packages/trac/web/api.py", line 662, in __getattr__ value = self.callbacks[name](self) File "/usr/local/lib/python3.10/dist-packages/trac/web/main.py", line 364, in _get_session return Session(self.env, req) File "/usr/local/lib/python3.10/dist-packages/trac/web/session.py", line 266, in __init__ if not req.is_authenticated: File "/usr/local/lib/python3.10/dist-packages/trac/util/__init__.py", line 1306, in __get__ result = self.fn(instance) File "/usr/local/lib/python3.10/dist-packages/trac/web/api.py", line 685, in is_authenticated return self.authname and self.authname != 'anonymous' File "/usr/local/lib/python3.10/dist-packages/trac/web/api.py", line 666, in __getattr__ raise ValueError('AttributeError caught while resolving %s ' ValueError: AttributeError caught while resolving authname attribute
follow-up: 9 comment:8 by , 6 weeks ago
Okay. That is an issue of th:AccountManagerPlugin.
-
acct_mgr/web_ui.py
diff --git a/acct_mgr/web_ui.py b/acct_mgr/web_ui.py index 8f409b82c..3185f4e03 100644
a b class LoginModule(auth.LoginModule): 593 593 if random.random() + self.cookie_refresh_pct / 100.0 > 1: 594 594 old_cookie = cookie.value 595 595 # Update auth cookie value 596 cookie.value = hex_entropy() 596 new_cookie = hex_entropy() 597 cookie.set('value', new_cookie, new_cookie) 597 598 self.log.debug("Changing session id for user %s to %s", name, 598 599 cookie.value) 599 600
Python 3.11.10 (main, Sep 7 2024, 18:35:42) [GCC 9.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from trac.web.api import Cookie >>> cookies = Cookie('name1=value1; name2=value2') >>> cookies <Cookie: name1='value1' name2='value2'> >>> cookies['name1'] <Morsel: name1=value1> >>> cookies['name1'].value = '?' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'value' of 'Morsel' object has no setter >>> cookies['name1'].value = 'vvv' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'value' of 'Morsel' object has no setter >>> cookies['name1'].set('value', 'vvvv', 'vvvv') >>> cookies['name1'].value 'vvvv' >>>
follow-up: 10 comment:9 by , 3 weeks ago
Replying to Jun Omae:
Okay. That is an issue of th:AccountManagerPlugin.
I've filed this issue at th:#14361.
comment:10 by , 3 weeks ago
Replying to Jun Omae:
Replying to Jun Omae:
Okay. That is an issue of th:AccountManagerPlugin.
I've filed this issue at th:#14361.
Fixed in th:r18669.
Thanks for the reporting. I'll investigate it.