|
1 | 1 | from trac.core import Component, implements
|
2 | 2 | from trac.web.chrome import INavigationContributor
|
3 |
| -from trac.web.api import IRequestFilter, IRequestHandler |
| 3 | +from trac.web.api import IRequestFilter, IRequestHandler, RequestDone |
| 4 | +from trac.web.auth import LoginModule |
4 | 5 | from trac.wiki.web_ui import WikiModule
|
5 | 6 | from trac.util import Markup
|
6 | 7 | from trac.util.html import tag
|
@@ -91,3 +92,41 @@ def _format_changeset_link(self, formatter, ns, chgset, label, fullmatch=None):
|
91 | 92 | return super(GitHubBrowserWithSVNChangesets, self)._format_changeset_link(
|
92 | 93 | formatter, ns, chgset, label, fullmatch
|
93 | 94 | )
|
| 95 | + |
| 96 | + |
| 97 | +class PlainLoginComponent(Component): |
| 98 | + """ |
| 99 | + Enable login through a plain HTML form (no more HTTP basic auth) |
| 100 | + """ |
| 101 | + implements(IRequestHandler) |
| 102 | + |
| 103 | + def match_request(self, req): |
| 104 | + return req.path_info == '/login' |
| 105 | + |
| 106 | + def process_request(self, req): |
| 107 | + if req.method == 'POST': |
| 108 | + return self.do_post(req) |
| 109 | + elif req.method == 'GET': |
| 110 | + return self.do_get(req) |
| 111 | + else: |
| 112 | + req.send_response(405) |
| 113 | + raise RequestDone |
| 114 | + |
| 115 | + def do_get(self, req): |
| 116 | + # XXX: Importing at the toplevel causes an AppRegistryNotReady as of now |
| 117 | + # Probably because we're inside __init__ so when gunicorn tries to import wsgi.py it's |
| 118 | + # also loading this module which triggers the error |
| 119 | + from django.contrib.auth.forms import AuthenticationForm |
| 120 | + return 'plainlogin.html', {'form': AuthenticationForm(), 'next': req.args.get('next', '/')} |
| 121 | + |
| 122 | + def do_post(self, req): |
| 123 | + from django.contrib.auth.forms import AuthenticationForm |
| 124 | + form = AuthenticationForm(data=req.args) |
| 125 | + if form.is_valid(): |
| 126 | + req.environ["REMOTE_USER"] = form.get_user().username |
| 127 | + LoginModule(self.compmgr)._do_login(req) |
| 128 | + redirect_url = req.args.get('next', '/') |
| 129 | + # TODO: validate that the redirect URL is safe to redirect to (same domain at least) |
| 130 | + # maybe using django.utils.http.is_safe_url()? |
| 131 | + req.redirect(redirect_url) |
| 132 | + return 'plainlogin.html', {'form': form, 'next': req.args.get('next', '/')} |
0 commit comments