diff --git a/src/requirements.txt b/src/requirements.txt
index bbcb440316..4af31dbad9 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -1,4 +1,5 @@
Django>=1.7
+django-bootstrap3
django-compressor
BeautifulSoup4
html5lib
diff --git a/src/tixl/settings.py b/src/tixl/settings.py
index 3060dbbbf3..3249e59dfc 100644
--- a/src/tixl/settings.py
+++ b/src/tixl/settings.py
@@ -40,6 +40,7 @@ INSTALLED_APPS = (
'tixlcontrol',
'tixlpresale',
'compressor',
+ 'bootstrap3',
)
MIDDLEWARE_CLASSES = (
diff --git a/src/tixlcontrol/middleware.py b/src/tixlcontrol/middleware.py
index bfcd8e9443..63a97f89ee 100644
--- a/src/tixlcontrol/middleware.py
+++ b/src/tixlcontrol/middleware.py
@@ -14,7 +14,7 @@ class LoginRequiredMiddleware:
"""
EXCEPTIONS = (
- "login"
+ "auth.login"
)
def process_request(self, request):
diff --git a/src/tixlcontrol/static/tixlcontrol/less/auth.less b/src/tixlcontrol/static/tixlcontrol/less/auth.less
new file mode 100644
index 0000000000..be6422a7fb
--- /dev/null
+++ b/src/tixlcontrol/static/tixlcontrol/less/auth.less
@@ -0,0 +1,22 @@
+@import "../../../../tixlbase/static/bootstrap/less/bootstrap.less";
+
+body {
+ background: #eee;
+}
+
+.form-signin {
+ .well;
+
+ max-width: 330px;
+ margin: auto;
+ margin-top: 10%;
+ padding-bottom: 0;
+
+ .control-label {
+ .sr-only;
+ }
+
+ .buttons {
+ text-align: right;
+ }
+}
diff --git a/src/tixlcontrol/templates/tixlcontrol/auth/base.html b/src/tixlcontrol/templates/tixlcontrol/auth/base.html
new file mode 100644
index 0000000000..a4fe3a1097
--- /dev/null
+++ b/src/tixlcontrol/templates/tixlcontrol/auth/base.html
@@ -0,0 +1,16 @@
+{% load compress %}
+{% load staticfiles %}
+
+
+
+
+ {% compress css %}
+
+ {% endcompress %}
+
+
+
+ {% block content %}
+ {% endblock %}
+
+
diff --git a/src/tixlcontrol/templates/tixlcontrol/auth/login.html b/src/tixlcontrol/templates/tixlcontrol/auth/login.html
new file mode 100644
index 0000000000..b4897405c3
--- /dev/null
+++ b/src/tixlcontrol/templates/tixlcontrol/auth/login.html
@@ -0,0 +1,15 @@
+{% extends "tixlcontrol/auth/base.html" %}
+{% load bootstrap3 %}
+{% block content %}
+
+{% endblock %}
diff --git a/src/tixlcontrol/urls.py b/src/tixlcontrol/urls.py
index 29bbb7f646..3f6fc73632 100644
--- a/src/tixlcontrol/urls.py
+++ b/src/tixlcontrol/urls.py
@@ -2,4 +2,5 @@ from django.conf.urls import patterns, url
urlpatterns = patterns('',
url(r'^$', 'tixlcontrol.views.main.index', name='index'),
+ url(r'^login$', 'tixlcontrol.views.auth.login', name='auth.login'),
)
diff --git a/src/tixlcontrol/views/auth.py b/src/tixlcontrol/views/auth.py
new file mode 100644
index 0000000000..c5b6515224
--- /dev/null
+++ b/src/tixlcontrol/views/auth.py
@@ -0,0 +1,55 @@
+from django.shortcuts import render, redirect
+from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm
+from django import forms
+from django.utils.translation import ugettext as _
+from django.contrib.auth import authenticate
+from django.contrib.auth import login as auth_login
+
+
+class AuthenticationForm(BaseAuthenticationForm):
+ """
+ The login form.
+ """
+ email = forms.EmailField(label=_("E-mail address"), max_length=254)
+ password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
+ username = None
+
+ error_messages = {
+ 'invalid_login': _("Please enter a correct e-mail address and password."),
+ 'inactive': _("This account is inactive."),
+ }
+
+ def __init__(self, request=None, *args, **kwargs):
+ self.request = request
+ self.user_cache = None
+ super(forms.Form, self).__init__(*args, **kwargs)
+
+ def clean(self):
+ email = self.cleaned_data.get('email')
+ password = self.cleaned_data.get('password')
+
+ if email and password:
+ self.user_cache = authenticate(identifier=email.lower(),
+ password=password)
+ if self.user_cache is None:
+ raise forms.ValidationError(
+ self.error_messages['invalid_login'],
+ code='invalid_login',
+ )
+ else:
+ self.confirm_login_allowed(self.user_cache)
+
+ return self.cleaned_data
+
+
+def login(request):
+ ctx = {}
+ if request.method == 'POST':
+ form = AuthenticationForm(data=request.POST)
+ if form.is_valid() and form.user_cache:
+ auth_login(request, form.user_cache)
+ return redirect('control:index')
+ else:
+ form = AuthenticationForm()
+ ctx['form'] = form
+ return render(request, 'tixlcontrol/auth/login.html', ctx)