source: sharedcookieauthplugin/tags/sharedcookieauth-0.1.4/sharedcookieauth/sharedcookieauth.py

Last change on this file was 12348, checked in by agitronic, 11 years ago

Fix multiple call to authenticate problem, closes #5566.

There seem to be a possibility that the authenticate method is
called multiple times during the processing of a request.

Also the '0.11' directory has been renamed to 'trunk' and monkey
patching has been disabled.

File size: 3.9 KB
Line 
1"""
2SharedCookieAuth:
3a plugin for Trac to share cookies between Tracs
4http://trac.edgewall.org
5"""
6
7import os
8
9from trac.config import ListOption
10from trac.core import *
11from trac.web import auth
12from trac.web.api import IAuthenticator
13from trac.web.main import RequestDispatcher
14from trac.env import open_environment
15from trac.env import IEnvironmentSetupParticipant
16
17class GenericObject(object):
18    def __init__(self, **kw):
19        for key, item in kw.items():
20            setattr(self, key, item)
21
22### attributes to take from the request for the monkey-patched methods
23req_attr = [ 'authname',
24             'href',
25             'incookie', 
26             'outcookie', 
27             'redirect',
28             'remote_addr', 
29             'remote_user', ]
30
31def _do_login(self, req):
32    kw = dict([ (i, getattr(req, i)) for i in req_attr ])
33    kw['base_path'] = '/'
34    fake_req = GenericObject(**kw)
35    auth_login_module_do_login(self, fake_req)
36
37def _do_logout(self, req):
38    kw = dict([ (i, getattr(req, i)) for i in req_attr ])
39    kw['base_path'] = '/'
40    fake_req = GenericObject(**kw)
41    auth_login_module_do_logout(self, fake_req)
42   
43
44class SharedCookieAuth(Component):
45
46    ### class-level data
47    implements(IAuthenticator, IEnvironmentSetupParticipant)
48
49    ### method for IAuthenticator
50
51    def authenticate(self, req):
52
53        if req.remote_user:
54            return req.remote_user
55
56        if 'shared_cookie_auth' in req.environ:
57            return req.environ['shared_cookie_auth']
58        else:
59            req.environ['shared_cookie_auth'] = None
60            if req.incookie.has_key('trac_auth'):
61                for project, dispatcher in self.dispatchers().items():
62                    agent = dispatcher.authenticate(req)
63                    if agent != 'anonymous':
64                        req.authname = agent
65                        req.environ['shared_cookie_auth'] = agent
66                        return agent
67
68        return None
69
70    ### methods for IEnvironmentSetupParticipant
71
72    """Extension point interface for components that need to participate in the
73    creation and upgrading of Trac environments, for example to create
74    additional database tables."""
75
76    def environment_created(self):
77        """Called when a new Trac environment is created."""
78
79    def environment_needs_upgrade(self, db):
80        """Called when Trac checks whether the environment needs to be upgraded.
81       
82        Should return `True` if this participant needs an upgrade to be
83        performed, `False` otherwise.
84        """
85        #self.patch()
86        return False
87       
88
89    def upgrade_environment(self, db):
90        """Actually perform an environment upgrade.
91       
92        Implementations of this method should not commit any database
93        transactions. This is done implicitly after all participants have
94        performed the upgrades they need without an error being raised.
95        """
96
97    ### internal methods
98
99    def patch(self):
100        if not globals().has_key('auth_login_module_do_login'):
101            globals()['auth_login_module_do_login'] = auth.LoginModule._do_login
102            auth.LoginModule._do_login = _do_login
103            globals()['auth_login_module_do_logout'] = auth.LoginModule._do_logout
104            auth.LoginModule._do_logout = _do_logout
105
106
107    def dispatchers(self):
108        if not hasattr(self, '_dispatchers'):
109
110            dispatchers = {}
111            base_path, project = os.path.split(self.env.path)
112            projects = [ i for i in os.listdir(base_path)
113                         if i != project ]
114
115            for project in projects:
116                path = os.path.join(base_path, project)
117                try:
118                    env = open_environment(path)
119                    rd = RequestDispatcher(env)
120                except:
121                    continue
122                dispatchers[project] = rd
123
124            self._dispatchers = dispatchers
125        return self._dispatchers
Note: See TracBrowser for help on using the repository browser.