Skip to content

Commit

Permalink
[WIP] Used a plain HTML form for DjangoProject login
Browse files Browse the repository at this point in the history
Fixes django#95, django#61 and django#60
Also possibly django#100 and django#64
  • Loading branch information
bmispelon committed Jan 28, 2024
1 parent 125e6f9 commit 7a39e5d
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 113 deletions.
41 changes: 40 additions & 1 deletion DjangoPlugin/tracdjangoplugin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from trac.core import Component, implements
from trac.web.chrome import INavigationContributor
from trac.web.api import IRequestFilter, IRequestHandler
from trac.web.api import IRequestFilter, IRequestHandler, RequestDone
from trac.web.auth import LoginModule
from trac.wiki.web_ui import WikiModule
from trac.util import Markup
from trac.util.html import tag
Expand Down Expand Up @@ -91,3 +92,41 @@ def _format_changeset_link(self, formatter, ns, chgset, label, fullmatch=None):
return super(GitHubBrowserWithSVNChangesets, self)._format_changeset_link(
formatter, ns, chgset, label, fullmatch
)


class PlainLoginComponent(Component):
"""
Enable login through a plain HTML form (no more HTTP basic auth)
"""
implements(IRequestHandler)

def match_request(self, req):
return req.path_info == '/login'

def process_request(self, req):
if req.method == 'POST':
return self.do_post(req)
elif req.method == 'GET':
return self.do_get(req)
else:
req.send_response(405)
raise RequestDone

def do_get(self, req):
# XXX: Importing at the toplevel causes an AppRegistryNotReady as of now
# Probably because we're inside __init__ so when gunicorn tries to import wsgi.py it's
# also loading this module which triggers the error
from django.contrib.auth.forms import AuthenticationForm
return 'plainlogin.html', {'form': AuthenticationForm(), 'next': req.args.get('next', '/')}

def do_post(self, req):
from django.contrib.auth.forms import AuthenticationForm
form = AuthenticationForm(data=req.args)
if form.is_valid():
req.environ["REMOTE_USER"] = form.get_user().username
LoginModule(self.compmgr)._do_login(req)
redirect_url = req.args.get('next', '/')
# TODO: validate that the redirect URL is safe to redirect to (same domain at least)
# maybe using django.utils.http.is_safe_url()?
req.redirect(redirect_url)
return 'plainlogin.html', {'form': form, 'next': req.args.get('next', '/')}
101 changes: 0 additions & 101 deletions DjangoPlugin/tracdjangoplugin/djangoauth.py

This file was deleted.

2 changes: 0 additions & 2 deletions DjangoPlugin/tracdjangoplugin/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,3 @@


SECRET_KEY = str(SECRETS["secret_key"])

BASIC_AUTH_REALM = "Django's Trac"
10 changes: 3 additions & 7 deletions DjangoPlugin/tracdjangoplugin/wsgi.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import os

import trac.web.main

application = trac.web.main.dispatch_request

import django
django.setup()

# Massive hack to make Trac fast, otherwise every git call tries to close ulimit -n (1e6) fds
# Python 3 would perform better here, but we are still on 2.7 for Trac, so leak fds for now.
from tracopt.versioncontrol.git import PyGIT

PyGIT.close_fds = False

from .djangoauth import DjangoAuth

application = DjangoAuth(application)

trac_dsn = os.getenv("SENTRY_DSN")

if trac_dsn:
import sentry_sdk
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
Expand Down
1 change: 1 addition & 0 deletions trac-env/conf/trac.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ trac.ticket.roadmap.roadmapmodule = disabled
trac.versioncontrol.web_ui.browser.browsermodule = disabled
trac.versioncontrol.web_ui.changeset.changesetmodule = disabled
trac.versioncontrol.web_ui.log.logmodule = disabled
trac.web.auth.loginmodule = disabled; replaced by djangoplugin.PlainLoginComponent
trac.wiki.web_ui.wikimodule = disabled
tracdjangoplugin.* = enabled
tracext.github.githubloginmodule = enabled
Expand Down
3 changes: 1 addition & 2 deletions trac-env/templates/django_theme.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
</form>
</li>
# else
<li><a href="/github/login">GitHub Login</a></li>
<li><a href="/login">DjangoProject Login</a></li>
<li><a href="/login">Login</a></li>
# endif
<li><a href="${req.href.prefs()}">Preferences</a></li>
# if req.perm.has_permission('XML_RPC'):
Expand Down
36 changes: 36 additions & 0 deletions trac-env/templates/plainlogin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# extends 'layout.html'

# block title
Login ${ super() }
# endblock title

# block content
<h1>Choose how you want to log in</h1>

<section class="login-github">
<h2>Log in with you GitHub account</h2>
<a href="/github/login">Log in with GitHub</a>
<section>

<section class="login-djangoproject">
<h2>Log in with your DjangoProject account</h2>
<form action="" method="post" class="plainlogin">
${form.as_p()}
<p>
<button type="submit">Log in with DjangoProject</button>
<input type="hidden" name="__FORM_TOKEN" value="${req.form_token}">{# Trac's CSRF protection #}
<input type="hidden" name="next" value="${next|default('/')}">
</p>
</form>
</section>

<section class="login-managing">
<h2>Account management</h2>
<nav>
<ul>
<li><a href="https://www.djangoproject.com/accounts/register/">Create a new DjangoProject account</a></li>
<li><a href="https://www.djangoproject.com/accounts/password_reset/">Reset your password</a></li>
</ul>
</nav>
</section>
# endblock content

0 comments on commit 7a39e5d

Please sign in to comment.