1 | # Created by Noah Kantrowitz on 2007-08-27. |
---|
2 | # Copyright (c) 2007-2008 Noah Kantrowitz. All rights reserved. |
---|
3 | from pprint import pformat |
---|
4 | import sys |
---|
5 | |
---|
6 | from trac.core import * |
---|
7 | from trac.config import BoolOption |
---|
8 | from trac.web.api import IRequestFilter, RequestDone |
---|
9 | from trac.perm import PermissionError |
---|
10 | from trac.admin.web_ui import AdminModule |
---|
11 | |
---|
12 | class PermRedirectModule(Component): |
---|
13 | """Redirect users to the login screen on PermissionError.""" |
---|
14 | |
---|
15 | implements(IRequestFilter) |
---|
16 | |
---|
17 | redirect_login_https = BoolOption( |
---|
18 | 'permredirect', 'redirect_login_https', 'false', |
---|
19 | """Redirect all requests to /login/ to HTTPS""") |
---|
20 | |
---|
21 | redirect_login = BoolOption( |
---|
22 | 'permredirect', 'redirect_login', 'true', |
---|
23 | """Redirect unauthenticated users to /login/ on PermissionError""") |
---|
24 | |
---|
25 | # IRequestFilter methods |
---|
26 | def pre_process_request(self, req, handler): |
---|
27 | if not self.redirect_login_https: |
---|
28 | return handler |
---|
29 | |
---|
30 | path = req.base_path + req.path_info |
---|
31 | |
---|
32 | pos = req.base_url.find(':') |
---|
33 | base_scheme = req.base_url[:pos] |
---|
34 | base_noscheme = req.base_url[pos:] |
---|
35 | base_noscheme_norm = base_noscheme.rstrip('/') |
---|
36 | if path == req.href.login() and base_scheme == 'http': |
---|
37 | login_url = 'https' + base_noscheme_norm + req.path_info |
---|
38 | if req.query_string: |
---|
39 | login_url = login_url + '?' + req.query_string |
---|
40 | req.redirect(login_url) |
---|
41 | return handler |
---|
42 | |
---|
43 | def post_process_request(self, req, template, data, content_type): |
---|
44 | if not self.redirect_login: |
---|
45 | return template, data, content_type |
---|
46 | |
---|
47 | if template is None: |
---|
48 | # Some kind of exception in progress |
---|
49 | if req.authname != 'anonymous': |
---|
50 | # Already logged in |
---|
51 | return template, data, content_type |
---|
52 | |
---|
53 | ref_url = req.base_url + req.path_info |
---|
54 | if req.query_string: |
---|
55 | ref_url = ref_url + "?" + req.query_string |
---|
56 | |
---|
57 | exctype, exc = sys.exc_info()[0:2] |
---|
58 | if exctype is None: |
---|
59 | self.log.debug("template and exctype both None for request " |
---|
60 | "to %s: %s" % (ref_url, pformat(req.environ))) |
---|
61 | return template, data, content_type |
---|
62 | |
---|
63 | |
---|
64 | login_url = req.href.login(referer=ref_url) |
---|
65 | |
---|
66 | if issubclass(exctype, PermissionError): |
---|
67 | req.redirect(login_url) |
---|
68 | |
---|
69 | try: |
---|
70 | if req.path_info.startswith('/admin') and \ |
---|
71 | not AdminModule(self.env)._get_panels(req)[0]: |
---|
72 | # No admin panels available, assume user should log in. |
---|
73 | req.redirect(login_url) |
---|
74 | except RequestDone: |
---|
75 | # Reraise on redirect |
---|
76 | raise |
---|
77 | except Exception: |
---|
78 | # It is possible the error we got called on happened inside |
---|
79 | # the _get_panels call. Be sure to ignore it. |
---|
80 | pass |
---|
81 | |
---|
82 | return template, data, content_type |
---|
83 | |
---|