Another Step in the Quest to clean up the code base.
This commit is contained in:
@@ -1 +1,13 @@
|
||||
""" Django Application to administrate the membership of Kasu.
|
||||
It was initaly designed to track the membership fees, but this part is not in
|
||||
use at the moment.
|
||||
|
||||
It also extends the stanard Django User model with avatars and contact infos.
|
||||
"""
|
||||
from kasu.settings import gettext as _
|
||||
|
||||
PAID_MEMBERSHIP_GROUP = 2
|
||||
GENDER_CHOICES = (
|
||||
('m', _('Male')),
|
||||
('f', _('Female')),
|
||||
)
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
"""
|
||||
Created on 19.09.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
""" Admin Interface to manage the memberships."""
|
||||
# import stuff we need from django
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.admin import UserAdmin, GroupAdmin
|
||||
# from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
||||
from django.contrib.auth.models import Group
|
||||
from django.utils.translation import ugettext as _
|
||||
from easy_thumbnails import fields, widgets
|
||||
|
||||
from membership.models import Membership, ActivationRequest
|
||||
|
||||
|
||||
def activate_user(modeladmin, request, queryset):
|
||||
def activate_user(modeladmin, request, queryset): # Ignore PyLintBear (W0613)
|
||||
"""Triggers activation of the selects actication requests by hand."""
|
||||
for activation in queryset:
|
||||
membership = Membership.objects.get(username=activation.user.username)
|
||||
membership.save()
|
||||
@@ -23,7 +20,8 @@ def activate_user(modeladmin, request, queryset):
|
||||
activate_user.short_description = _('Activate selected User')
|
||||
|
||||
|
||||
def cleanup_activation(modeladmin, request, queryset):
|
||||
def cleanup_activation(modeladmin, request, queryset): # Ignore PyLintBear (W0613)
|
||||
"""Delete every selected activation request that has been expired."""
|
||||
for activation in queryset:
|
||||
if activation.expired:
|
||||
activation.user.delete()
|
||||
@@ -34,18 +32,23 @@ cleanup_activation.short_description = _(
|
||||
|
||||
|
||||
class ProxyGroup(Group):
|
||||
"""A Proxy to list Usergroups from django.contrib.auth here."""
|
||||
|
||||
class Meta:
|
||||
""" MetaData to localize this Proxy Group."""
|
||||
proxy = True
|
||||
verbose_name = _('Group')
|
||||
verbose_name_plural = _('Groups')
|
||||
|
||||
|
||||
class MembershipAdmin(UserAdmin):
|
||||
# admin_thumbnail = AdminThumbnail(image_field='thumbnail')
|
||||
"""Admin interface to manage membership. e.g. users."""
|
||||
formfield_overrides = {
|
||||
fields.ThumbnailerImageField: {
|
||||
'widget': widgets.ImageClearableFileInput},
|
||||
}
|
||||
list_filter = ('is_active', 'membership', 'confirmed')
|
||||
list_display = (
|
||||
'avatar',
|
||||
'username',
|
||||
'first_name',
|
||||
'last_name',
|
||||
@@ -60,8 +63,10 @@ class MembershipAdmin(UserAdmin):
|
||||
(None, {'fields': (('username', 'password'), 'gender', 'avatar',
|
||||
('first_name', 'last_name'), ('email', 'website'))}),
|
||||
(_('Membership'), {'classes': ('collapse',),
|
||||
'fields': (('membership', 'confirmed'), 'birthday', 'telephone',
|
||||
'street_name', ('post_code', 'city'))}),
|
||||
'fields': (
|
||||
('membership', 'confirmed'), 'birthday',
|
||||
'telephone',
|
||||
'street_name', ('post_code', 'city'))}),
|
||||
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
|
||||
'groups', 'user_permissions')}),
|
||||
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
|
||||
@@ -74,6 +79,8 @@ admin.site.register(Membership, MembershipAdmin)
|
||||
|
||||
|
||||
class RegistrationAdmin(admin.ModelAdmin):
|
||||
"""To administrag user activation requests.
|
||||
Kasu uses an two factor registration via email."""
|
||||
list_display = ('username', 'first_name', 'last_name', 'email',
|
||||
'registration_date', 'expired')
|
||||
search_fields = ('user__username', 'user__first_name')
|
||||
|
||||
@@ -3,20 +3,20 @@ Created on 03.10.2011
|
||||
|
||||
@author: Christian
|
||||
"""
|
||||
import sys
|
||||
|
||||
from captcha.fields import ReCaptchaField
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib import auth
|
||||
from django.contrib.sites.models import Site
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from utils.massmailer import MassMailer
|
||||
from captcha.fields import ReCaptchaField
|
||||
from . import models
|
||||
|
||||
|
||||
class MembershipForm(forms.ModelForm):
|
||||
"""Form for users to change their own user data."""
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
birthday = forms.DateField(
|
||||
@@ -27,6 +27,7 @@ class MembershipForm(forms.ModelForm):
|
||||
email = forms.EmailField(label=_('Email'), required=True)
|
||||
|
||||
class Meta:
|
||||
"""get the user model dyamicly"""
|
||||
model = auth.get_user_model()
|
||||
fields = (
|
||||
'username', 'gender', 'first_name', 'last_name', 'email', 'avatar',
|
||||
@@ -35,26 +36,31 @@ class MembershipForm(forms.ModelForm):
|
||||
)
|
||||
|
||||
def clean_birthday(self):
|
||||
if self.cleaned_data['membership'] and not self.cleaned_data['birthday']:
|
||||
"""If the user wants to be a member the birthday field is mandatory."""
|
||||
if self.cleaned_data['membership'] \
|
||||
and not self.cleaned_data['birthday']:
|
||||
raise forms.ValidationError(_('For your membership, we need this. \
|
||||
Please fill out this field yet.'))
|
||||
return self.cleaned_data['birthday']
|
||||
|
||||
def clean_street_name(self):
|
||||
if self.cleaned_data['membership'] and not self.cleaned_data[
|
||||
'street_name']:
|
||||
"""If the user wants to be a member the address is mandatory."""
|
||||
if self.cleaned_data['membership'] \
|
||||
and not self.cleaned_data['street_name']:
|
||||
raise forms.ValidationError(_('For your membership, we need this. \
|
||||
Please fill out this field yet.'))
|
||||
return self.cleaned_data['street_name']
|
||||
|
||||
def clean_post_code(self):
|
||||
if self.cleaned_data['membership'] and not self.cleaned_data[
|
||||
'post_code']:
|
||||
"""If the user wants to be a member the address is mandatory."""
|
||||
if self.cleaned_data['membership'] \
|
||||
and not self.cleaned_data['post_code']:
|
||||
raise forms.ValidationError(_('For your membership, we need this. \
|
||||
Please fill out this field yet.'))
|
||||
return self.cleaned_data['post_code']
|
||||
|
||||
def clean_city(self):
|
||||
"""If the user wants to be a member the address is mandatory."""
|
||||
if self.cleaned_data['membership'] and not self.cleaned_data['city']:
|
||||
raise forms.ValidationError(_('For your membership, we need this. \
|
||||
Please fill out this field yet.'))
|
||||
@@ -62,11 +68,11 @@ class MembershipForm(forms.ModelForm):
|
||||
|
||||
|
||||
class RegistrationForm(MembershipForm):
|
||||
"""
|
||||
Form to register a new user account.
|
||||
"""Form to register a new user account.
|
||||
|
||||
Validates that the requested username and email is not already in use,
|
||||
requires the password to be entered twice to catch typos.
|
||||
sends an activation request per mail, to validate the eMail.
|
||||
Also sends an activation request per mail, to validate the email.
|
||||
"""
|
||||
password1 = forms.CharField(
|
||||
widget=forms.PasswordInput(), label=_('password'))
|
||||
@@ -75,6 +81,7 @@ class RegistrationForm(MembershipForm):
|
||||
recaptcha = ReCaptchaField()
|
||||
|
||||
class Meta:
|
||||
"""Metadata to localize and customize the ModelForm."""
|
||||
model = auth.get_user_model()
|
||||
fields = ('first_name', 'last_name', 'username', 'email',
|
||||
'username', 'gender', 'first_name', 'last_name', 'email',
|
||||
@@ -85,9 +92,7 @@ class RegistrationForm(MembershipForm):
|
||||
)
|
||||
|
||||
def clean_username(self):
|
||||
"""
|
||||
Validate that the username is not already in use.
|
||||
"""
|
||||
"""Validate that the username is not already in use."""
|
||||
try:
|
||||
auth.get_user_model().objects.get(
|
||||
username__iexact=self.cleaned_data['username']
|
||||
@@ -98,9 +103,7 @@ class RegistrationForm(MembershipForm):
|
||||
Please choose another.'))
|
||||
|
||||
def clean_email(self):
|
||||
"""
|
||||
Validate that the supplied email address is unique for the site.
|
||||
"""
|
||||
"""Validate that the supplied email address is unique for the site."""
|
||||
if auth.get_user_model().objects.filter(
|
||||
email__iexact=self.cleaned_data['email']):
|
||||
raise forms.ValidationError(_(u'This email address is already in \
|
||||
@@ -108,6 +111,7 @@ class RegistrationForm(MembershipForm):
|
||||
return self.cleaned_data['email']
|
||||
|
||||
def clean_password2(self):
|
||||
"""Check that the password has been entered identical for two times."""
|
||||
password1 = self.cleaned_data.get("password1", "")
|
||||
password2 = self.cleaned_data["password2"]
|
||||
if password1 != password2:
|
||||
@@ -115,30 +119,29 @@ class RegistrationForm(MembershipForm):
|
||||
_("The two password fields didn't match."))
|
||||
return password2
|
||||
|
||||
def send_email(self, activation):
|
||||
mailer = MassMailer()
|
||||
mailer.subject = 'Deine Anmeldung auf %s' % Site.objects.get_current()
|
||||
mailer.txt_template = 'membership/email/activation_email.txt'
|
||||
mailer.context = {
|
||||
'user': activation.user,
|
||||
'site': Site.objects.get_current(),
|
||||
'activation_key': activation.activation_key,
|
||||
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
|
||||
}
|
||||
mailer.add_recipient(activation.user)
|
||||
mailer.send()
|
||||
|
||||
def save(self, commit=True):
|
||||
"""
|
||||
Creates the new ``User`` and ``RegistrationProfile`` and
|
||||
returns the ``User``.
|
||||
""" Create the new User, set him/her inactive, create an acitivation
|
||||
request for the user and send him/her an activation email.
|
||||
|
||||
:param commit: commit the SQL and send the email if True
|
||||
:return: the created User Object
|
||||
"""
|
||||
user = super(RegistrationForm, self).save(commit=False)
|
||||
user.set_password(self.cleaned_data["password1"])
|
||||
user.is_active = False
|
||||
if commit:
|
||||
user.save()
|
||||
activation = models.ActivationRequest.objects.create_pending_registration(
|
||||
user) # @IgnorePep8
|
||||
self.send_email(activation)
|
||||
activation_request = models.ActivationRequest.objects \
|
||||
.create_pending_registration(user)
|
||||
mailer = MassMailer(
|
||||
subject='Deine Anmeldung auf %s' % Site.objects.get_current(),
|
||||
txt_template='membership/email/activation_email.txt',
|
||||
context={
|
||||
'user': activation_request.user,
|
||||
'site': Site.objects.get_current(),
|
||||
'activation_key': activation_request.activation_key,
|
||||
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
|
||||
}
|
||||
)
|
||||
mailer.send(recipients=[activation_request.user])
|
||||
return user
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: kasu.membership\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-05-10 23:16+0200\n"
|
||||
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
|
||||
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
|
||||
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
|
||||
"Language-Team: Kasu <verein@kasu.at>\n"
|
||||
@@ -19,78 +19,78 @@ msgstr ""
|
||||
"X-Translated-Using: django-rosetta 0.7.2\n"
|
||||
"X-Generator: Poedit 1.8.9\n"
|
||||
|
||||
#: membership/admin.py:23
|
||||
#: membership/admin.py:22
|
||||
msgid "Activate selected User"
|
||||
msgstr "Ausgewählte Benutzer freischalten"
|
||||
|
||||
#: membership/admin.py:33
|
||||
#: membership/admin.py:31
|
||||
msgid "Cleanup selected Activation Requests"
|
||||
msgstr "Ausgewählte Aktivierungsanfragen bereinigen"
|
||||
|
||||
#: membership/admin.py:40
|
||||
#: membership/admin.py:37
|
||||
msgid "Group"
|
||||
msgstr "Gruppe"
|
||||
|
||||
#: membership/admin.py:41
|
||||
#: membership/admin.py:38
|
||||
msgid "Groups"
|
||||
msgstr "Gruppen"
|
||||
|
||||
#: membership/admin.py:62 membership/models.py:164 membership/models.py:215
|
||||
#: membership/templates/membership/register_form.html:31
|
||||
#: membership/admin.py:59 membership/models.py:164 membership/models.py:215
|
||||
#: membership/templates/membership/register_form.html:32
|
||||
msgid "Membership"
|
||||
msgstr "Mitgliedschaft"
|
||||
|
||||
#: membership/admin.py:65
|
||||
#: membership/admin.py:64
|
||||
msgid "Permissions"
|
||||
msgstr "Berechtigung"
|
||||
|
||||
#: membership/admin.py:67
|
||||
#: membership/admin.py:66
|
||||
msgid "Important dates"
|
||||
msgstr "Wichtige Daten"
|
||||
|
||||
#: membership/forms.py:20
|
||||
#: membership/forms.py:23
|
||||
msgid "birthday"
|
||||
msgstr "Geburtstag"
|
||||
|
||||
#: membership/forms.py:22
|
||||
#: membership/forms.py:25
|
||||
msgid "Input format: yyyy-mm-dd"
|
||||
msgstr "Eingabeformat: tt.mm.jjjj"
|
||||
|
||||
#: membership/forms.py:24
|
||||
#: membership/forms.py:27
|
||||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: membership/forms.py:36 membership/forms.py:43 membership/forms.py:50
|
||||
#: membership/forms.py:39 membership/forms.py:46 membership/forms.py:53
|
||||
msgid ""
|
||||
"For your membership, we need this. Please fill out this field "
|
||||
"yet."
|
||||
msgstr "Diese Angabe wird für eine Mitgliedschaft benötigt, bitte ausfüllen."
|
||||
|
||||
#: membership/forms.py:56
|
||||
#: membership/forms.py:59
|
||||
msgid ""
|
||||
"For your membership, we need this. Please fill out this field "
|
||||
"yet."
|
||||
msgstr "Diese Angabe wird für eine Mitgliedschaft benötigt, bitte ausfüllen."
|
||||
|
||||
#: membership/forms.py:68
|
||||
#: membership/forms.py:72
|
||||
msgid "password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: membership/forms.py:69
|
||||
#: membership/forms.py:74
|
||||
msgid "password (again)"
|
||||
msgstr "Passwort (wiederholen)"
|
||||
|
||||
#: membership/forms.py:92
|
||||
#: membership/forms.py:97
|
||||
msgid "This username is already taken. Please choose another."
|
||||
msgstr "Diesen Benutzername ist schon vergeben. Bitte einen anderen auswählen."
|
||||
|
||||
#: membership/forms.py:101
|
||||
#: membership/forms.py:106
|
||||
msgid ""
|
||||
"This email address is already in use. Please supply a different "
|
||||
"email address."
|
||||
msgstr "Die E-Mail Adresse wird schon verwendet. Bitte eine andere angeben."
|
||||
|
||||
#: membership/forms.py:110
|
||||
#: membership/forms.py:115
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Die beiden Passwörter passen nicht."
|
||||
|
||||
@@ -360,11 +360,11 @@ msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: membership/templates/membership/register_form.html:4
|
||||
#: membership/templates/membership/register_form.html:6
|
||||
#: membership/templates/membership/register_form.html:7
|
||||
msgid "Registration"
|
||||
msgstr "Registrieren"
|
||||
|
||||
#: membership/templates/membership/register_form.html:8
|
||||
#: membership/templates/membership/register_form.html:9
|
||||
msgid ""
|
||||
"After you've provided your account data, you'll receive\n"
|
||||
" an email asking you to verify your email address. You have to click on "
|
||||
@@ -378,20 +378,20 @@ msgstr ""
|
||||
"Bitte klicke auf den Link in dieser E-Mail zur Verifizierung, erst dann ist "
|
||||
"die Anmeldung möglich."
|
||||
|
||||
#: membership/templates/membership/register_form.html:19
|
||||
#: membership/templates/membership/register_form.html:20
|
||||
msgid "name"
|
||||
msgstr "Name"
|
||||
|
||||
#: membership/templates/membership/register_form.html:25
|
||||
#: membership/templates/membership/register_form.html:26
|
||||
#: membership/templates/registration/login.html:41
|
||||
msgid "login"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: membership/templates/membership/register_form.html:38
|
||||
#: membership/templates/membership/register_form.html:39
|
||||
msgid "reset"
|
||||
msgstr "Zurücksetzen"
|
||||
|
||||
#: membership/templates/membership/register_form.html:40
|
||||
#: membership/templates/membership/register_form.html:41
|
||||
#: membership/templates/registration/login.html:35
|
||||
msgid "register"
|
||||
msgstr "Registrieren"
|
||||
@@ -574,7 +574,7 @@ msgstr "Passwort zurücksetzen"
|
||||
msgid "Transmit"
|
||||
msgstr "Übermitteln"
|
||||
|
||||
#: membership/views.py:58
|
||||
#: membership/views.py:63
|
||||
msgid ""
|
||||
"Activation successful. You can now login anytime with you username "
|
||||
"and password."
|
||||
@@ -582,13 +582,14 @@ msgstr ""
|
||||
"Die Aktivierung war erfolgreich. Du kannst dich ab jetzt jederzeit mit "
|
||||
"deinem Benutzernamen und Passwort anmelden."
|
||||
|
||||
#: membership/views.py:78
|
||||
#: membership/views.py:83
|
||||
msgid "User Profile changed successfully"
|
||||
msgstr "Benutzerprofil erfolgreich geändert."
|
||||
|
||||
#: membership/views.py:92
|
||||
#, python-format
|
||||
msgid "No %(verbose_name)s found matching the query"
|
||||
#: membership/views.py:97
|
||||
#, fuzzy
|
||||
#| msgid "No %(verbose_name)s found matching the query"
|
||||
msgid "No Membership found matching the query"
|
||||
msgstr "Kein %(verbose_name)s gefunden welche der Anfrage entspricht"
|
||||
|
||||
#~ msgid "Given Name"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Adds a command to cleanup the expired registration attempts."""
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
@@ -6,8 +6,9 @@ from membership.models import ActivationRequest
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Delete all expired user registrations from the database"
|
||||
"""Delete all expired user registrations from the database."""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"""Get all expired Activation Objects and call the delete() method."""
|
||||
for activation in ActivationRequest.objects.expired():
|
||||
activation.user.delete()
|
||||
@@ -1,14 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
When you get an error email from your Django app telling you someone got a
|
||||
server error,
|
||||
it’s not always easy to tell which user had a problem.
|
||||
"""When you get an error email from your Django app telling you someone got a
|
||||
server error, it’s not always easy to tell which user had a problem.
|
||||
It might help your debugging to know or you might want to contact the user to
|
||||
tell them you have fixed the problem.
|
||||
"""
|
||||
|
||||
from optparse import make_option
|
||||
tell them you have fixed the problem."""
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import auth
|
||||
@@ -17,37 +10,45 @@ from django.core.management.base import BaseCommand
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = '<session_key session_key ...>'
|
||||
"""Management command to find the right user to a session."""
|
||||
help = 'If the session still exists find it and show the related User'
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option(
|
||||
|
||||
def add_arguments(self, parser):
|
||||
"""add commandline parameters to ban or delete the user."""
|
||||
# Positional arguments
|
||||
parser.add_argument('session_id_list', nargs='+', type=str)
|
||||
|
||||
# Named (optional) arguments
|
||||
parser.add_argument(
|
||||
'--delete',
|
||||
action='store_true',
|
||||
dest='delete',
|
||||
default=False,
|
||||
help='Delete the Useraccount'
|
||||
),
|
||||
make_option(
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--ban',
|
||||
action='store_true',
|
||||
dest='ban',
|
||||
default=False,
|
||||
help='Ban the Useraccount'
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
for session_key in args:
|
||||
"""Try to find the users that belong to the given session_ids.
|
||||
delete or ban them if parametes had been set."""
|
||||
for session_id in options['session_id_list']:
|
||||
try:
|
||||
session = Session.objects.get(session_key=session_key)
|
||||
session = Session.objects.get(session_key=session_id)
|
||||
uid = session.get_decoded().get('_auth_user_id')
|
||||
user = auth.get_user_model().objects.get(pk=uid)
|
||||
except Session.DoesNotExist:
|
||||
self.stderr.write('Session "%s" does not exist' % session_key)
|
||||
self.stderr.write('Session "%s" does not exist' % session_id)
|
||||
continue
|
||||
except settings.AUTH_USER_MODEL.DoesNotExist:
|
||||
self.stderr.write(
|
||||
'Session "%s" has no registed User' % session_key)
|
||||
'Session "%s" has no registed User' % session_id)
|
||||
continue
|
||||
if options['delete']:
|
||||
self.stdout.write('deleting %s' % user.username)
|
||||
@@ -1,30 +1,24 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
"""ORM Models for Users that could be members and user activation requests."""
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
from datetime import timedelta
|
||||
from os import path
|
||||
import random
|
||||
import hashlib
|
||||
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
from . import PAID_MEMBERSHIP_GROUP
|
||||
from easy_thumbnails.fields import ThumbnailerImageField
|
||||
|
||||
from utils import OverwriteStorage
|
||||
|
||||
|
||||
GENDER_CHOICES = (
|
||||
('m', _('Male')),
|
||||
('f', _('Female')),
|
||||
)
|
||||
from . import PAID_MEMBERSHIP_GROUP, GENDER_CHOICES
|
||||
|
||||
|
||||
def get_upload_path(instance, filename):
|
||||
"""
|
||||
Erstellt den Pfad und Dateinamen für den Upload dynmisch.
|
||||
"""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
|
||||
@@ -34,9 +28,7 @@ def get_upload_path(instance, filename):
|
||||
|
||||
|
||||
class ActivationManager(models.Manager):
|
||||
"""
|
||||
Manages pending user registrations
|
||||
"""
|
||||
"""Manages pending user registrations."""
|
||||
|
||||
def activate(self, activation_key):
|
||||
"""
|
||||
@@ -61,17 +53,17 @@ class ActivationManager(models.Manager):
|
||||
return False
|
||||
|
||||
def create_pending_registration(self, user):
|
||||
"""
|
||||
creates a PendingActivation instance with an random activation key.
|
||||
"""Creates a PendingActivation instance with an random activation key.
|
||||
@param user: the user that requests activation.
|
||||
"""
|
||||
salt = str(user.pk * random.random()) + \
|
||||
user.registration_date.isoformat()
|
||||
activation_key = hashlib.sha1(salt.encode('utf-8')).hexdigest()
|
||||
|
||||
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(
|
||||
@@ -101,20 +93,24 @@ class ActivationRequest(models.Model):
|
||||
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:
|
||||
@@ -126,24 +122,28 @@ class ActivationRequest(models.Model):
|
||||
|
||||
@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):
|
||||
# user = models.OneToOneField(settings.AUTH_USER_MODEL)
|
||||
# nickname = models.SlugField(_('Nickname'), unique=True)
|
||||
"""An expanded Django User with additional data to manage club memberships.
|
||||
"""
|
||||
gender = models.CharField(
|
||||
_("Gender"),
|
||||
max_length=1,
|
||||
@@ -151,9 +151,6 @@ class Membership(AbstractUser):
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
# first_name = models.CharField(_("Given Name"), max_length=30)
|
||||
# last_name = models.CharField(_("Last Name"), max_length=30)
|
||||
# email = models.EmailField(_('Email'), unique=True)
|
||||
website = models.URLField(blank=True)
|
||||
avatar = ThumbnailerImageField(
|
||||
upload_to=get_upload_path,
|
||||
@@ -207,11 +204,13 @@ class Membership(AbstractUser):
|
||||
default=False,
|
||||
help_text=_('This person has paid the membership fee.')
|
||||
)
|
||||
|
||||
# comment = models.TextField(blank=True)
|
||||
# objects = MembershipManager()
|
||||
|
||||
class Meta(object):
|
||||
ordering = ('username', )
|
||||
"""To manage object ordering and dispalynames on the admin interface."""
|
||||
ordering = ('username',)
|
||||
swappable = 'AUTH_USER_MODEL'
|
||||
verbose_name = _('Membership')
|
||||
verbose_name_plural = _('Memberships')
|
||||
@@ -220,12 +219,16 @@ class Membership(AbstractUser):
|
||||
return self.username
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
'membership-details',
|
||||
kwargs={'username': self.username}
|
||||
)
|
||||
""":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)
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
from imagekit.specs import ImageSpec
|
||||
from imagekit import processors
|
||||
|
||||
|
||||
class ResizeThumbnail(processors.Resize):
|
||||
width = 60
|
||||
height = 60
|
||||
crop = True
|
||||
|
||||
|
||||
class ResizeProfile(processors.Resize):
|
||||
width = 140
|
||||
height = 140
|
||||
crop = True
|
||||
|
||||
|
||||
class Thumbnail(ImageSpec):
|
||||
pre_cache = True
|
||||
processors = (ResizeThumbnail,)
|
||||
|
||||
|
||||
class Profile(ImageSpec):
|
||||
pre_cache = False
|
||||
processors = (ResizeProfile,)
|
||||
@@ -4,7 +4,6 @@ Created on 03.10.2011
|
||||
@author: christian
|
||||
"""
|
||||
import django.contrib.auth.views as auth_views
|
||||
from django.conf.urls import include
|
||||
from django.conf.urls import url
|
||||
|
||||
from . import views
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
"""Views to register, edit and view users and/or members including their
|
||||
profile."""
|
||||
from datetime import date
|
||||
|
||||
from csp.decorators import csp_update
|
||||
from django import http
|
||||
from django.conf import settings
|
||||
from django.contrib import auth, messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import Http404
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views import generic
|
||||
from django.utils.decorators import method_decorator
|
||||
from csp.decorators import csp_update
|
||||
|
||||
from mahjong_ranking.models import KyuDanRanking, SeasonRanking
|
||||
from utils import mixins
|
||||
from . import forms, models
|
||||
|
||||
RECAPTCHA_CSP = {
|
||||
'SCRIPT_SRC': (
|
||||
'https://www.google.com/recaptcha/',
|
||||
@@ -20,24 +25,26 @@ RECAPTCHA_CSP = {
|
||||
}
|
||||
|
||||
|
||||
class ActivateRegistration(generic.DetailView):
|
||||
class ActivateRegistration(generic.TemplateView):
|
||||
"""
|
||||
Activates the Registration of an User and logs him in
|
||||
Activates the Registration of an User, log him in and redirect to his
|
||||
profile, also display an error message if the activation has failed.
|
||||
"""
|
||||
template_name = 'membership/activation_error.html'
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""fetch the activation key and try to activate it."""
|
||||
activation_key = self.kwargs.get('activation_key')
|
||||
user = self.get_user(activation_key)
|
||||
user = models.ActivationRequest.objects.activate(activation_key)
|
||||
if user:
|
||||
return self.login(user)
|
||||
else:
|
||||
self.object = user
|
||||
context = self.get_context_data()
|
||||
return self.render_to_response(context)
|
||||
return super(ActivateRegistration, self).get(
|
||||
request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.DetailView.get_context_data(self, **kwargs)
|
||||
"""Add the acctivation days and the activation key to the template
|
||||
context."""
|
||||
context = super(ActivateRegistration, self).get_context_data(**kwargs)
|
||||
context.update({
|
||||
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
|
||||
'activation_key': self.kwargs.get('activation_key'),
|
||||
@@ -45,58 +52,70 @@ class ActivateRegistration(generic.DetailView):
|
||||
})
|
||||
return context
|
||||
|
||||
def get_user(self, activation_key):
|
||||
user = models.ActivationRequest.objects.activate(activation_key)
|
||||
if user:
|
||||
return user
|
||||
elif self.request.user.is_authenticated():
|
||||
return self.request.user
|
||||
else:
|
||||
return None
|
||||
|
||||
def login(self, user):
|
||||
"""Log the user in and redirect to his profile."""
|
||||
backend = auth.get_backends()[0]
|
||||
user.backend = "%s.%s" % (
|
||||
backend.__module__, backend.__class__.__name__) # @IgnorePep8
|
||||
backend.__module__, backend.__class__.__name__)
|
||||
auth.login(self.request, user)
|
||||
messages.success(self.request, _('Activation successful. \
|
||||
You can now login anytime with you username and password.'))
|
||||
redirect_url = reverse('membership-edit', args=(user.username,))
|
||||
return http.HttpResponseRedirect(redirect_url) # @IgnorePep8
|
||||
return http.HttpResponseRedirect(
|
||||
reverse('membership-edit', args=(user.username,)))
|
||||
|
||||
|
||||
class ActivationSent(generic.TemplateView):
|
||||
"""Inform a user that a activation request has been send to him."""
|
||||
template_name = 'membership/activation_sent.html'
|
||||
|
||||
|
||||
class EditMembership(mixins.LoginRequiredMixin, generic.UpdateView):
|
||||
class EditMembership(LoginRequiredMixin, generic.UpdateView):
|
||||
"""A From that allows Memebers to edit their profile."""
|
||||
form_class = forms.MembershipForm
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
"""If the authenticated user is allowed to change Membership objects,
|
||||
fetch the given account. Everybody else only get his own Membeship
|
||||
object returned."""
|
||||
if self.request.user.has_perm('membership.change_membership'):
|
||||
return models.Membership.objects.get(username=self.kwargs['username'])
|
||||
return models.Membership.objects.get(
|
||||
username=self.kwargs['username'])
|
||||
else:
|
||||
return models.Membership.objects.get(username=self.request.user)
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Add a success message to the message queue."""
|
||||
messages.success(self.request, _('User Profile changed successfully'))
|
||||
return generic.UpdateView.form_valid(self, form)
|
||||
|
||||
|
||||
class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView):
|
||||
class MembershipDetail(LoginRequiredMixin, generic.DetailView):
|
||||
"""To display the public user profile of an spcific user.
|
||||
If no user has been specified, display your own profile.
|
||||
"""
|
||||
model = models.Membership
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
"""Get the Membership Profile matching the username given in the URI,
|
||||
or the current logged in user if no username has been specified.
|
||||
|
||||
:param queryset: the `QuerySet` that will be used to look up the object.
|
||||
:return: a Membership Object, or raises a 404 if nothing found.
|
||||
"""
|
||||
queryset = queryset or self.get_queryset()
|
||||
try:
|
||||
if self.kwargs.get('username'):
|
||||
return models.Membership.objects.get(username=self.kwargs['username'])
|
||||
return queryset.get(username=self.kwargs['username'])
|
||||
elif self.request.user.is_authenticated():
|
||||
return self.request.user
|
||||
except models.Membership.DoesNotExist:
|
||||
raise Http404(_("No %(verbose_name)s found matching the query") %
|
||||
{'verbose_name': self.model._meta.verbose_name})
|
||||
raise Http404(_("No Membership found matching the query"))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
""" Add the ladder ranking and the Kyu and Dan ranking the user profile.
|
||||
|
||||
:return: array with the context data
|
||||
"""
|
||||
context = generic.DetailView.get_context_data(self, **kwargs)
|
||||
try:
|
||||
context['kyu_dan_ranking'] = KyuDanRanking.objects.get(
|
||||
@@ -113,14 +132,22 @@ class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView):
|
||||
|
||||
|
||||
class RegisterForm(generic.FormView):
|
||||
"""To register a new user on this website. Secured by reCaptcha."""
|
||||
form_class = forms.RegistrationForm
|
||||
success_url = '/membership/activation_sent/'
|
||||
template_name = 'membership/register_form.html'
|
||||
|
||||
@method_decorator(csp_update(**RECAPTCHA_CSP))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(RegisterForm, self).dispatch(*args, **kwargs)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
"""Overwrite to add googles recaptcha ressoruces to the
|
||||
Content-Security_Policity HTTP Headers.
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return: """
|
||||
return super(RegisterForm, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Save the formdata and redirect to the success_url. """
|
||||
form.save()
|
||||
return generic.FormView.form_valid(self, form)
|
||||
|
||||
Reference in New Issue
Block a user