Skip to content

Commit 7a39e5d

Browse files
committed
[WIP] Used a plain HTML form for DjangoProject login
Fixes django#95, django#61 and django#60 Also possibly django#100 and django#64
1 parent 125e6f9 commit 7a39e5d

File tree

7 files changed

+81
-113
lines changed

7 files changed

+81
-113
lines changed

DjangoPlugin/tracdjangoplugin/__init__.py

+40-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from trac.core import Component, implements
22
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
45
from trac.wiki.web_ui import WikiModule
56
from trac.util import Markup
67
from trac.util.html import tag
@@ -91,3 +92,41 @@ def _format_changeset_link(self, formatter, ns, chgset, label, fullmatch=None):
9192
return super(GitHubBrowserWithSVNChangesets, self)._format_changeset_link(
9293
formatter, ns, chgset, label, fullmatch
9394
)
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', '/')}

DjangoPlugin/tracdjangoplugin/djangoauth.py

-101
This file was deleted.

DjangoPlugin/tracdjangoplugin/settings.py

-2
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,3 @@
2424

2525

2626
SECRET_KEY = str(SECRETS["secret_key"])
27-
28-
BASIC_AUTH_REALM = "Django's Trac"

DjangoPlugin/tracdjangoplugin/wsgi.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
import os
22

33
import trac.web.main
4-
54
application = trac.web.main.dispatch_request
65

6+
import django
7+
django.setup()
8+
79
# Massive hack to make Trac fast, otherwise every git call tries to close ulimit -n (1e6) fds
810
# Python 3 would perform better here, but we are still on 2.7 for Trac, so leak fds for now.
911
from tracopt.versioncontrol.git import PyGIT
10-
1112
PyGIT.close_fds = False
1213

13-
from .djangoauth import DjangoAuth
14-
15-
application = DjangoAuth(application)
16-
1714
trac_dsn = os.getenv("SENTRY_DSN")
18-
1915
if trac_dsn:
2016
import sentry_sdk
2117
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware

trac-env/conf/trac.ini

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ trac.ticket.roadmap.roadmapmodule = disabled
2222
trac.versioncontrol.web_ui.browser.browsermodule = disabled
2323
trac.versioncontrol.web_ui.changeset.changesetmodule = disabled
2424
trac.versioncontrol.web_ui.log.logmodule = disabled
25+
trac.web.auth.loginmodule = disabled; replaced by djangoplugin.PlainLoginComponent
2526
trac.wiki.web_ui.wikimodule = disabled
2627
tracdjangoplugin.* = enabled
2728
tracext.github.githubloginmodule = enabled

trac-env/templates/django_theme.html

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
2828
</form>
2929
</li>
3030
# else
31-
<li><a href="/github/login">GitHub Login</a></li>
32-
<li><a href="/login">DjangoProject Login</a></li>
31+
<li><a href="/login">Login</a></li>
3332
# endif
3433
<li><a href="${req.href.prefs()}">Preferences</a></li>
3534
# if req.perm.has_permission('XML_RPC'):

trac-env/templates/plainlogin.html

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# extends 'layout.html'
2+
3+
# block title
4+
Login ${ super() }
5+
# endblock title
6+
7+
# block content
8+
<h1>Choose how you want to log in</h1>
9+
10+
<section class="login-github">
11+
<h2>Log in with you GitHub account</h2>
12+
<a href="/github/login">Log in with GitHub</a>
13+
<section>
14+
15+
<section class="login-djangoproject">
16+
<h2>Log in with your DjangoProject account</h2>
17+
<form action="" method="post" class="plainlogin">
18+
${form.as_p()}
19+
<p>
20+
<button type="submit">Log in with DjangoProject</button>
21+
<input type="hidden" name="__FORM_TOKEN" value="${req.form_token}">{# Trac's CSRF protection #}
22+
<input type="hidden" name="next" value="${next|default('/')}">
23+
</p>
24+
</form>
25+
</section>
26+
27+
<section class="login-managing">
28+
<h2>Account management</h2>
29+
<nav>
30+
<ul>
31+
<li><a href="https://www.djangoproject.com/accounts/register/">Create a new DjangoProject account</a></li>
32+
<li><a href="https://www.djangoproject.com/accounts/password_reset/">Reset your password</a></li>
33+
</ul>
34+
</nav>
35+
</section>
36+
# endblock content

0 commit comments

Comments
 (0)