244 lines
7.6 KiB
Python
244 lines
7.6 KiB
Python
"""ORM Models for Users that could be members and user activation requests."""
|
|
|
|
import hashlib
|
|
import random
|
|
from datetime import timedelta
|
|
from os import path
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import AbstractUser
|
|
from django.db import models
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext as _
|
|
from easy_thumbnails.fields import ThumbnailerImageField
|
|
|
|
from utils import OverwriteStorage
|
|
from . import PAID_MEMBERSHIP_GROUP, GENDER_CHOICES
|
|
|
|
|
|
def get_upload_path(instance, filename):
|
|
"""Erstellt den Pfad und Dateinamen für den Upload dynmisch.
|
|
|
|
@param instance: The Membership Object for the uploaded image
|
|
@param filename: the filename of the uploaded image
|
|
"""
|
|
extension = path.splitext(filename)[1]
|
|
return 'membership/%s%s' % (instance.username, extension)
|
|
|
|
|
|
class ActivationManager(models.Manager):
|
|
"""Manages pending user registrations."""
|
|
|
|
def activate(self, activation_key):
|
|
"""
|
|
searches the pending registrations for the given activation key.
|
|
Set the corresponding user to active, if the key was found
|
|
and the key has not expired yet.s
|
|
|
|
@param activation_key: the key found in the activation email
|
|
"""
|
|
try:
|
|
activation_request = self.get(activation_key=activation_key)
|
|
if activation_request.expired():
|
|
activation_request.user.delete()
|
|
activation_request.delete()
|
|
return False
|
|
elif not activation_request.user.is_active:
|
|
activation_request.user.is_active = True
|
|
activation_request.user.save()
|
|
activation_request.delete()
|
|
return activation_request.user
|
|
except self.model.DoesNotExist:
|
|
return False
|
|
|
|
def create_pending_registration(self, user):
|
|
"""Creates a PendingActivation instance with an random activation key.
|
|
@param user: the user that requests activation.
|
|
"""
|
|
salt = str(user.pk * random.random())
|
|
salt += user.registration_date.isoformat()
|
|
activation_key = hashlib.sha1(salt.encode()).hexdigest()
|
|
return self.create(user=user, activation_key=activation_key)
|
|
|
|
def expired(self):
|
|
"""Return all ActivationRequest that haven't been activated and
|
|
whose valid activation time has been expired"""
|
|
timespan = timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
|
|
expiration_date = timezone.now() - timespan
|
|
return self.filter(
|
|
user__is_active=False,
|
|
user__date_joined__lt=expiration_date
|
|
)
|
|
|
|
|
|
class ActivationRequest(models.Model):
|
|
"""
|
|
Each ActivationRequest contains an activation key and an user.
|
|
The key will be send by email to the user
|
|
if the user clicks on the link he can activate his in_active account.
|
|
"""
|
|
user = models.OneToOneField(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.CASCADE,
|
|
verbose_name=_('user')
|
|
)
|
|
activation_key = models.CharField(_('activation key'), max_length=40)
|
|
objects = ActivationManager()
|
|
|
|
class Meta:
|
|
verbose_name = _('pending activation')
|
|
verbose_name_plural = _('pending activations')
|
|
|
|
def __str__(self):
|
|
return _("user registration for %s") % self.user
|
|
|
|
def activate(self):
|
|
"""Activate the user account and delete this ActivationRequest"""
|
|
self.user.is_active = True
|
|
self.user.save()
|
|
self.delete()
|
|
|
|
@property
|
|
def expiration_date(self):
|
|
"""The datetime until this user activation request is valid."""
|
|
timespan = timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
|
|
return self.user.date_joined + timespan
|
|
|
|
@property
|
|
def email(self):
|
|
"""The email adress of the user that should be activated."""
|
|
return self.user.email
|
|
|
|
def expired(self):
|
|
"""True if user is inactive and expiration_date is in the past."""
|
|
if self.user.is_active:
|
|
return False
|
|
elif timezone.now() >= self.expiration_date:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
expired.boolean = True
|
|
|
|
@property
|
|
def first_name(self):
|
|
"""First name of the user that should be activated."""
|
|
return self.user.first_name
|
|
|
|
@property
|
|
def last_name(self):
|
|
"""Last name of the user that should be activated."""
|
|
return self.user.last_name
|
|
|
|
@property
|
|
def registration_date(self):
|
|
"""Date when the user joined/registered his account."""
|
|
return self.user.date_joined
|
|
|
|
@property
|
|
def username(self):
|
|
"""Loing name of the user that should be activated."""
|
|
return self.user.username
|
|
|
|
|
|
class Membership(AbstractUser):
|
|
"""An expanded Django User with additional data to manage club memberships.
|
|
"""
|
|
gender = models.CharField(
|
|
_("Gender"),
|
|
max_length=1,
|
|
choices=GENDER_CHOICES,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
website = models.URLField(blank=True)
|
|
avatar = ThumbnailerImageField(
|
|
upload_to=get_upload_path,
|
|
storage=OverwriteStorage(),
|
|
blank=True,
|
|
null=True
|
|
)
|
|
membership = models.BooleanField(
|
|
_('Membership'),
|
|
default=False,
|
|
help_text=_('Yes, I confirm that I am in agreement with the statutes \
|
|
and would like to become a member.')
|
|
)
|
|
birthday = models.DateField(
|
|
_("Birthday Date"),
|
|
blank=True, null=True,
|
|
)
|
|
telephone = models.CharField(
|
|
_("Telephone"),
|
|
max_length=30,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
street_name = models.CharField(
|
|
_("Address"),
|
|
max_length=75,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
post_code = models.PositiveSmallIntegerField(
|
|
_("Postcode"),
|
|
blank=True,
|
|
null=True
|
|
)
|
|
city = models.CharField(
|
|
_("Town/City"),
|
|
max_length=75,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
deposit = models.PositiveSmallIntegerField(default=0, editable=False)
|
|
registration_date = models.DateField(auto_now_add=True, editable=False)
|
|
paid_until = models.DateField(
|
|
_('Paid until'),
|
|
blank=True,
|
|
null=True,
|
|
editable=True
|
|
)
|
|
confirmed = models.BooleanField(
|
|
_('Confirmed'),
|
|
default=False,
|
|
help_text=_('This person has paid the membership fee.')
|
|
)
|
|
|
|
nullable_personal_data = (
|
|
'gender', 'birthday', 'telephone', 'street_name', 'post_code', 'city')
|
|
blankable_personal_data = (
|
|
'email', 'password', 'first_name', 'last_name', 'website',)
|
|
|
|
class Meta(object):
|
|
"""To manage object ordering and dispalynames on the admin interface."""
|
|
ordering = ('username',)
|
|
swappable = 'AUTH_USER_MODEL'
|
|
verbose_name = _('Membership')
|
|
verbose_name_plural = _('Memberships')
|
|
|
|
@property
|
|
def full_name(self):
|
|
return " ".join([self.last_name, self.first_name])
|
|
|
|
def __str__(self):
|
|
return self.username
|
|
|
|
def get_absolute_url(self):
|
|
""":return the URL for this Membership DetailView"""
|
|
return reverse('membership-details', kwargs={'username': self.username})
|
|
|
|
def save(self, *args, **kwargs):
|
|
"""Save the Useraccount, and add him tho the "Paid Membership" group
|
|
if he activated the "membership" checkbox and has been validated.
|
|
|
|
:param args: passed through the save() method from django
|
|
:param kwargs: passed through the save() method from django
|
|
"""
|
|
super(Membership, self).save(*args, **kwargs)
|
|
if self.confirmed:
|
|
self.groups.add(PAID_MEMBERSHIP_GROUP)
|
|
else:
|
|
self.groups.remove(PAID_MEMBERSHIP_GROUP)
|