forked from CGM_Public/pretix_original
Merge branch 'master' of github.com:tixl/tixl
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
[submodule "src/tixlbase/static/bootstrap"]
|
||||
path = src/tixlbase/static/bootstrap
|
||||
url = https://github.com/twbs/bootstrap.git
|
||||
+2
-2
@@ -6,7 +6,7 @@ install:
|
||||
- pip install -q -r src/requirements.txt
|
||||
before_script:
|
||||
- cd src
|
||||
- "pep8 --ignore=E501,E128 --exclude=migrations ."
|
||||
- pyflakes .
|
||||
- flake8 --ignore=E128,F403,F401 .
|
||||
- python manage.py validate
|
||||
script:
|
||||
- python manage.py test
|
||||
|
||||
@@ -3,11 +3,18 @@ The development setup
|
||||
|
||||
Obtain a copy of the source code
|
||||
--------------------------------
|
||||
Just clone our git repository::
|
||||
Just clone our git repository including its submodules::
|
||||
|
||||
git clone https://github.com/tixl/tixl.git
|
||||
git clone --recursive https://github.com/tixl/tixl.git
|
||||
cd tixl/
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
* Python 3.4 or newer
|
||||
* ``pip`` for Python 3
|
||||
* ``git``
|
||||
* ``lessc`` (Debian package: ``node-less``)
|
||||
|
||||
Your local python environment
|
||||
-----------------------------
|
||||
|
||||
@@ -29,13 +36,29 @@ Then, create the local database::
|
||||
|
||||
python manage.py syncdb
|
||||
|
||||
Create the translation files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
To generate updated translation files, run a::
|
||||
|
||||
make localegen
|
||||
|
||||
To compile the language files for use, run::
|
||||
|
||||
make localecompile
|
||||
|
||||
Run the development server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Execute::
|
||||
|
||||
python manage.py runserver
|
||||
|
||||
to start a local development webserver on port 8000.
|
||||
|
||||
Static code checks
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Before you check in your code into git, always run::
|
||||
|
||||
pyflakes .
|
||||
pep8 --ignore=E501,E128 .
|
||||
flake8 .
|
||||
|
||||
to check for syntax, style and other errors.
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
*.aux
|
||||
*.log
|
||||
*.toc
|
||||
*.mo
|
||||
*~
|
||||
.ropeproject
|
||||
__pycache__/
|
||||
_static/
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
all: localecompile
|
||||
|
||||
localecompile:
|
||||
django-admin compilemessages
|
||||
|
||||
localegen:
|
||||
django-admin makemessages --all
|
||||
@@ -0,0 +1,84 @@
|
||||
# tixl translation file German
|
||||
# Copyright (C) 2014 the tixl authors
|
||||
# This file is distributed under the same license as the tixl package.
|
||||
# Raphael Michel <michel@rami.io>, 2014.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-09-11 11:16+0200\n"
|
||||
"PO-Revision-Date: 2014-09-11 11:05+200\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: Raphael Michel <michel@rami.io>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: tixl/settings.py:92
|
||||
msgid "German"
|
||||
msgstr "Deutsch"
|
||||
|
||||
#: tixl/settings.py:93
|
||||
msgid "English"
|
||||
msgstr "Englisch"
|
||||
|
||||
#: tixlbase/admin.py:16
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Die beiden eingegebenen Passwörter stimmen nicht überein."
|
||||
|
||||
#: tixlbase/admin.py:18 tixlcontrol/views/auth.py:14
|
||||
msgid "Password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: tixlbase/admin.py:20
|
||||
msgid "Password confirmation"
|
||||
msgstr "Passwort bestätigen"
|
||||
|
||||
#: tixlbase/admin.py:22
|
||||
msgid "Enter the same password as above, for verification."
|
||||
msgstr "Geben Sie zur Bestätigung das selbe Passwort wie oben ein"
|
||||
|
||||
#: tixlbase/admin.py:50
|
||||
msgid "Personal info"
|
||||
msgstr "Persönliche Daten"
|
||||
|
||||
#: tixlbase/admin.py:51
|
||||
msgid "Permissions"
|
||||
msgstr "Berechtigungen"
|
||||
|
||||
#: tixlbase/models.py:65
|
||||
msgid "Letters, digits and @/./+/-/_ only."
|
||||
msgstr "Nur Buchstaben, Zahlen und @/./+/-/_"
|
||||
|
||||
#: tixlbase/models.py:71
|
||||
msgid "E-mail"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: tixlbase/models.py:74
|
||||
msgid "Given name"
|
||||
msgstr "Vorname"
|
||||
|
||||
#: tixlbase/models.py:77
|
||||
msgid "Family name"
|
||||
msgstr "Nachname"
|
||||
|
||||
#: tixlcontrol/templates/tixlcontrol/auth/login.html:12
|
||||
msgid "Log in"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: tixlcontrol/views/auth.py:13
|
||||
msgid "E-mail address"
|
||||
msgstr "E-Mail-Adresse"
|
||||
|
||||
#: tixlcontrol/views/auth.py:18
|
||||
msgid "Please enter a correct e-mail address and password."
|
||||
msgstr ""
|
||||
"Bitte geben Sie eine gültige Kombination aus E-Mail-Adresse und Passwort ein."
|
||||
|
||||
#: tixlcontrol/views/auth.py:19
|
||||
msgid "This account is inactive."
|
||||
msgstr "Dieses Konto ist deaktiviert."
|
||||
@@ -1,3 +1,11 @@
|
||||
Django>=1.7
|
||||
django-bootstrap3
|
||||
django-compressor
|
||||
BeautifulSoup4
|
||||
html5lib
|
||||
slimit
|
||||
lxml
|
||||
pyflakes
|
||||
pep8
|
||||
pep8-naming
|
||||
flake8
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[flake8]
|
||||
ignore = E128
|
||||
max-line-length = 160
|
||||
exclude = tests,migrations,.ropeproject,static
|
||||
max-complexity = 12
|
||||
+34
-1
@@ -39,16 +39,20 @@ INSTALLED_APPS = (
|
||||
'tixlbase',
|
||||
'tixlcontrol',
|
||||
'tixlpresale',
|
||||
'compressor',
|
||||
'bootstrap3',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'tixlcontrol.middleware.LoginRequiredMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'tixl.urls'
|
||||
@@ -79,17 +83,46 @@ USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
LOCALE_PATHS = (
|
||||
'locale',
|
||||
)
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
LANGUAGES = (
|
||||
('de', _('German')),
|
||||
('en', _('English')),
|
||||
)
|
||||
|
||||
|
||||
# Authentication
|
||||
|
||||
AUTH_USER_MODEL = 'tixlbase.User'
|
||||
|
||||
LOGIN_URL = '/login'
|
||||
LOGIN_URL_CONTROL = '/control/login'
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/dev/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
STATIC_ROOT = '_static'
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/less', 'lessc {infile} {outfile}'),
|
||||
)
|
||||
|
||||
COMPRESS_CSS_FILTERS = (
|
||||
'compressor.filters.css_default.CssAbsoluteFilter',
|
||||
'compressor.filters.cssmin.CSSMinFilter',
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
|
||||
+10
-4
@@ -1,10 +1,16 @@
|
||||
from django.conf.urls import patterns, include, url
|
||||
from django.contrib import admin
|
||||
from django.conf import settings
|
||||
|
||||
import tixlcontrol.urls
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# Examples:
|
||||
# url(r'^$', 'tixl.views.home', name='home'),
|
||||
# url(r'^blog/', include('blog.urls')),
|
||||
|
||||
url(r'^control/', include(tixlcontrol.urls, namespace='control')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += patterns('django.contrib.staticfiles.views',
|
||||
url(r'^static/(?P<path>.*)$', 'serve'),
|
||||
)
|
||||
|
||||
+58
-1
@@ -1,3 +1,60 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.utils.translation import ugettext as _
|
||||
from django import forms
|
||||
|
||||
# Register your models here.
|
||||
from tixlbase.models import User
|
||||
|
||||
|
||||
class TixlUserCreationForm(forms.ModelForm):
|
||||
|
||||
"""
|
||||
A form that creates a user, with no privileges, from the given username and
|
||||
password.
|
||||
"""
|
||||
error_messages = {
|
||||
'password_mismatch': _("The two password fields didn't match."),
|
||||
}
|
||||
password1 = forms.CharField(label=_("Password"),
|
||||
widget=forms.PasswordInput)
|
||||
password2 = forms.CharField(label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput,
|
||||
help_text=_("Enter the same password as above, for verification."))
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("email", "username", "event")
|
||||
|
||||
def clean_password2(self):
|
||||
password1 = self.cleaned_data.get("password1")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password1 and password2 and password1 != password2:
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
|
||||
def save(self, commit=True):
|
||||
user = super(TixlUserCreationForm, self).save(commit=False)
|
||||
user.set_password(self.cleaned_data["password1"])
|
||||
if commit:
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
class TixlUserAdmin(UserAdmin):
|
||||
|
||||
fieldsets = (
|
||||
(None, {'fields': ('identifier', 'event', 'username', 'password')}),
|
||||
(_('Personal info'), {'fields': ('familyname', 'givenname', 'email')}),
|
||||
(_('Permissions'), {'fields': ('is_active', 'is_staff',
|
||||
'groups', 'user_permissions')}),
|
||||
)
|
||||
list_display = ('identifier', 'event', 'username', 'email', 'givenname', 'familyname', 'is_staff')
|
||||
search_fields = ('identifier', 'username', 'givenname', 'familyname', 'email')
|
||||
ordering = ('identifier',)
|
||||
list_filter = ('is_staff', 'is_active', 'groups')
|
||||
add_form = TixlUserCreationForm
|
||||
|
||||
admin.site.register(User, TixlUserAdmin)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tixlbase', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='familyname',
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='givenname',
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tixlbase', '0002_auto_20140910_1628'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='username',
|
||||
field=models.CharField(blank=True, max_length=120, null=True, help_text='Letters, digits and @/./+/-/_ only.'),
|
||||
),
|
||||
]
|
||||
+49
-13
@@ -1,5 +1,6 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
||||
class UserManager(BaseUserManager):
|
||||
@@ -8,19 +9,19 @@ class UserManager(BaseUserManager):
|
||||
model documentation to see what's so special about our user model.
|
||||
"""
|
||||
|
||||
def create_user(self, email, password=None):
|
||||
user = self.model(email=email)
|
||||
user.set_password(user)
|
||||
def create_user(self, identifier, username, password=None):
|
||||
user = self.model(identifier=identifier)
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
def create_superuser(self, email, password=None):
|
||||
def create_superuser(self, identifier, username, password=None):
|
||||
if password is None:
|
||||
raise Exception("You must provide a password")
|
||||
user = self.model(email=email)
|
||||
user = self.model(identifier=identifier, username=username)
|
||||
user.is_staff = True
|
||||
user.is_superuser = True
|
||||
user.set_password(user)
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
return user
|
||||
|
||||
@@ -59,11 +60,21 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||
"""
|
||||
|
||||
identifier = models.CharField(max_length=255, unique=True)
|
||||
username = models.CharField(max_length=120)
|
||||
username = models.CharField(max_length=120, blank=True,
|
||||
null=True,
|
||||
help_text=_('Letters, digits and @/./+/-/_ only.'))
|
||||
event = models.ForeignKey('Event', related_name="users",
|
||||
null=True, blank=True)
|
||||
null=True, blank=True,
|
||||
on_delete=models.PROTECT)
|
||||
email = models.EmailField(unique=False, db_index=True,
|
||||
null=True, blank=True)
|
||||
null=True, blank=True,
|
||||
verbose_name=_('E-mail'))
|
||||
givenname = models.CharField(max_length=255, blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Given name'))
|
||||
familyname = models.CharField(max_length=255, blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Family name'))
|
||||
is_active = models.BooleanField(default=True)
|
||||
is_staff = models.BooleanField(default=False)
|
||||
date_joined = models.DateTimeField(auto_now_add=True)
|
||||
@@ -73,12 +84,35 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||
def __str__(self):
|
||||
return self.identifier
|
||||
|
||||
def get_short_name(self):
|
||||
if self.givenname:
|
||||
return self.givenname
|
||||
elif self.familyname:
|
||||
return self.familyname
|
||||
else:
|
||||
return self.username
|
||||
|
||||
def get_full_name(self):
|
||||
if self.givenname and not self.familyname:
|
||||
return self.givenname
|
||||
elif not self.givenname and self.familyname:
|
||||
return self.familyname
|
||||
elif self.familyname and self.givenname:
|
||||
return '%(family)s, %(given)s' % {
|
||||
'family': self.familyname,
|
||||
'given': self.givenname
|
||||
}
|
||||
else:
|
||||
return self.username
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.identifier is None:
|
||||
if self.event is None:
|
||||
self.identifier = self.email
|
||||
self.identifier = self.email.lower()
|
||||
else:
|
||||
self.identifier = "%s@%d.event.tixl" % (self.username, self.event.id)
|
||||
self.identifier = "%s@%d.event.tixl" % (self.username.lower(), self.event.id)
|
||||
if not self.pk:
|
||||
self.identifier = self.identifier.lower()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
USERNAME_FIELD = 'identifier'
|
||||
@@ -101,7 +135,8 @@ class Organizer(models.Model):
|
||||
slug = models.CharField(max_length=50,
|
||||
unique=True,
|
||||
db_index=True)
|
||||
owner = models.ForeignKey(User, null=True, blank=True)
|
||||
owner = models.ForeignKey(User, null=True, blank=True,
|
||||
on_delete=models.PROTECT)
|
||||
|
||||
class Meta:
|
||||
ordering = ("name",)
|
||||
@@ -133,7 +168,8 @@ class Event(models.Model):
|
||||
matter when they were ordered (and thus, ignoring payment_term_days).
|
||||
"""
|
||||
|
||||
organizer = models.ForeignKey(Organizer, related_name="events")
|
||||
organizer = models.ForeignKey(Organizer, related_name="events",
|
||||
on_delete=models.PROTECT)
|
||||
name = models.CharField(max_length=200)
|
||||
slug = models.CharField(max_length=50,
|
||||
db_index=True)
|
||||
|
||||
Submodule
+1
Submodule src/tixlbase/static/bootstrap added at 97027a2f6f
@@ -0,0 +1,39 @@
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import resolve
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.six.moves.urllib.parse import urlparse
|
||||
from django.shortcuts import resolve_url
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
|
||||
|
||||
class LoginRequiredMiddleware:
|
||||
|
||||
"""
|
||||
This middleware enforces all requests to the control app
|
||||
to require login.
|
||||
"""
|
||||
|
||||
EXCEPTIONS = (
|
||||
"auth.login"
|
||||
)
|
||||
|
||||
def process_request(self, request):
|
||||
if not request.user.is_authenticated():
|
||||
url_namespace = resolve(request.path_info).namespace
|
||||
url_name = resolve(request.path_info).url_name
|
||||
if url_namespace == 'control' and url_name not in self.EXCEPTIONS:
|
||||
# Taken from django/contrib/auth/decorators.py
|
||||
path = request.build_absolute_uri()
|
||||
# urlparse chokes on lazy objects in Python 3, force to str
|
||||
resolved_login_url = force_str(
|
||||
resolve_url(settings.LOGIN_URL_CONTROL))
|
||||
# If the login url is the same scheme and net location then just
|
||||
# use the path as the "next" url.
|
||||
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
|
||||
current_scheme, current_netloc = urlparse(path)[:2]
|
||||
if ((not login_scheme or login_scheme == current_scheme) and
|
||||
(not login_netloc or login_netloc == current_netloc)):
|
||||
path = request.get_full_path()
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
return redirect_to_login(
|
||||
path, resolved_login_url, REDIRECT_FIELD_NAME)
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{% load compress %}
|
||||
{% load staticfiles %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" type="text/less" href="{% static "tixlcontrol/less/auth.less" %}" />
|
||||
{% endcompress %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
{% extends "tixlcontrol/auth/base.html" %}
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
<form class="form-signin" action="" method="post">
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
{% csrf_token %}
|
||||
{% bootstrap_field form.email %}
|
||||
{% bootstrap_field form.password %}
|
||||
<div class="form-group buttons">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Log in" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
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'),
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1,61 @@
|
||||
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.user.is_authenticated():
|
||||
if "next" in request.GET:
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
return redirect('control:index')
|
||||
if request.method == 'POST':
|
||||
form = AuthenticationForm(data=request.POST)
|
||||
if form.is_valid() and form.user_cache:
|
||||
auth_login(request, form.user_cache)
|
||||
if "next" in request.GET:
|
||||
return redirect(request.GET.get("next", 'control:index'))
|
||||
return redirect('control:index')
|
||||
else:
|
||||
form = AuthenticationForm()
|
||||
ctx['form'] = form
|
||||
return render(request, 'tixlcontrol/auth/login.html', ctx)
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.http import HttpResponse
|
||||
|
||||
|
||||
def index(request):
|
||||
return HttpResponse('Coming soon.')
|
||||
Reference in New Issue
Block a user