diff --git a/src/tixlbase/admin.py b/src/tixlbase/admin.py index 8c38f3f3da..2dc9d3772d 100644 --- a/src/tixlbase/admin.py +++ b/src/tixlbase/admin.py @@ -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) diff --git a/src/tixlbase/migrations/0002_auto_20140910_1628.py b/src/tixlbase/migrations/0002_auto_20140910_1628.py new file mode 100644 index 0000000000..d08eaa8e26 --- /dev/null +++ b/src/tixlbase/migrations/0002_auto_20140910_1628.py @@ -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, + ), + ] diff --git a/src/tixlbase/migrations/0003_auto_20140910_1649.py b/src/tixlbase/migrations/0003_auto_20140910_1649.py new file mode 100644 index 0000000000..826d1a1c9e --- /dev/null +++ b/src/tixlbase/migrations/0003_auto_20140910_1649.py @@ -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.'), + ), + ] diff --git a/src/tixlbase/models.py b/src/tixlbase/models.py index 45674511d2..de508aa492 100644 --- a/src/tixlbase/models.py +++ b/src/tixlbase/models.py @@ -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,16 +9,16 @@ 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) + def create_user(self, identifier, username, password=None): + user = self.model(identifier=identifier) user.set_password(user) 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) @@ -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)