# HG changeset patch # User Brian Neal # Date 1299028292 0 # Node ID 69d0306a6fe7422221ea75a843070f089923fd89 # Parent efa3b4901777187077854c61a77c028715336d58 Fixing #165: add a way to filter users in the admin by join date; add an admin action to approve a pending user; added a honeypot type field to the registration form. diff -r efa3b4901777 -r 69d0306a6fe7 gpp/accounts/__init__.py --- a/gpp/accounts/__init__.py Mon Feb 28 03:53:04 2011 +0000 +++ b/gpp/accounts/__init__.py Wed Mar 02 01:11:32 2011 +0000 @@ -0,0 +1,37 @@ +import datetime +import logging + +from django.contrib.auth.models import User + + +def create_new_user(pending_user, ip=None, admin_activation=False): + """ + This function contains the code to create a new user from a + pending user. The pending user is deleted and the new user + is saved. A log message is produced. If admin_activation is false, + then ip should be the user's IP they confirmed from, if available. + + """ + new_user = User() + + new_user.username = pending_user.username + new_user.first_name = '' + new_user.last_name = '' + new_user.email = pending_user.email + new_user.password = pending_user.password # already been hashed + new_user.is_staff = False + new_user.is_active = True + new_user.is_superuser = False + new_user.last_login = datetime.datetime.now() + new_user.date_joined = new_user.last_login + + new_user.save() + pending_user.delete() + + if admin_activation: + msg = 'Accounts registration confirmed by ADMIN for %s' % new_user.username + else: + msg = 'Accounts registration confirmed by USER for %s from %s' % ( + new_user.username, ip) + + logging.info(msg) diff -r efa3b4901777 -r 69d0306a6fe7 gpp/accounts/admin.py --- a/gpp/accounts/admin.py Mon Feb 28 03:53:04 2011 +0000 +++ b/gpp/accounts/admin.py Wed Mar 02 01:11:32 2011 +0000 @@ -4,9 +4,23 @@ from accounts.models import IllegalUsername from accounts.models import IllegalEmail from accounts.models import PendingUser +from accounts import create_new_user + class PendingUserAdmin(admin.ModelAdmin): list_display = ('username', 'email', 'date_joined') + actions = ('activate_account', ) + + def activate_account(self, request, qs): + """ + Activate the accounts of the selected pending users. + + """ + for pending_user in qs: + create_new_user(pending_user, admin_activation=True) + + activate_account.short_description = "Activate accounts for selected users" + admin.site.register(IllegalUsername) admin.site.register(IllegalEmail) diff -r efa3b4901777 -r 69d0306a6fe7 gpp/accounts/forms.py --- a/gpp/accounts/forms.py Mon Feb 28 03:53:04 2011 +0000 +++ b/gpp/accounts/forms.py Wed Mar 02 01:11:32 2011 +0000 @@ -19,7 +19,7 @@ """Form used to register with the website""" username = forms.RegexField(max_length=30, regex=r'^\w+$', error_messages={ - 'invalid': 'Your username must be 30 characters or less and ' \ + 'invalid': 'Your username must be 30 characters or less and ' 'contain only letters, numbers and underscores.'}) email = forms.EmailField() password1 = forms.CharField(label="Password", widget=forms.PasswordInput) @@ -27,7 +27,7 @@ agree_age = forms.BooleanField(required=True, label='I certify that I am over the age of 13', error_messages={ - 'required': 'Sorry, but you must be over the age of 13 to ' \ + 'required': 'Sorry, but you must be over the age of 13 to ' 'register at our site.', }) agree_tos = forms.BooleanField(required=True, @@ -41,6 +41,8 @@ 'required': 'You have not agreed to our Privacy Policy.', }) question1 = forms.CharField(label="What number appears in the site name?") + question2 = forms.CharField(label='', required=False, + widget=forms.TextInput(attrs={'style': 'display: none;'})) def __init__(self, *args, **kwargs): self.ip = kwargs.pop('ip', '?') @@ -101,6 +103,15 @@ self._validation_error("Incorrect answer to our anti-spam question.", answer) return answer + def clean_question2(self): + """ + Honeypot field should be empty. + """ + answer = self.cleaned_data.get('question2') + if answer: + self._validation_error('Wrong answer #2: %s' % answer) + return answer + def save(self): pending_user = PendingUser.objects.create_pending_user(self.cleaned_data['username'], self.cleaned_data['email'], diff -r efa3b4901777 -r 69d0306a6fe7 gpp/accounts/views.py --- a/gpp/accounts/views.py Mon Feb 28 03:53:04 2011 +0000 +++ b/gpp/accounts/views.py Wed Mar 02 01:11:32 2011 +0000 @@ -12,6 +12,7 @@ from accounts.models import PendingUser from accounts.forms import RegisterForm +from accounts import create_new_user ####################################################################### @@ -69,23 +70,8 @@ }, context_instance = RequestContext(request)) - new_user = User() + create_new_user(pending_user, ip) - new_user.username = pending_user.username - new_user.first_name = '' - new_user.last_name = '' - new_user.email = pending_user.email - new_user.password = pending_user.password # already been hashed - new_user.is_staff = False - new_user.is_active = True - new_user.is_superuser = False - new_user.last_login = datetime.datetime.now() - new_user.date_joined = new_user.last_login - - new_user.save() - pending_user.delete() - - logging.info('Accounts register_confirm [%s]: success: %s', ip, username) return render_to_response('accounts/register_success.html', { 'username': username, }, diff -r efa3b4901777 -r 69d0306a6fe7 gpp/bio/admin.py --- a/gpp/bio/admin.py Mon Feb 28 03:53:04 2011 +0000 +++ b/gpp/bio/admin.py Wed Mar 02 01:11:32 2011 +0000 @@ -5,6 +5,9 @@ from django.contrib import admin +import django.contrib.auth.models +import django.contrib.auth.admin + import bio.models import bio.badges from comments.models import Comment @@ -26,7 +29,7 @@ date_hierarchy = 'status_date' inlines = (BadgeOwnerInline, ) actions = ( - 'mark_active', + 'mark_active', 'mark_resigned', 'mark_removed', 'mark_suspended', @@ -40,8 +43,8 @@ def mark_user_status(self, request, qs, status): """ - Common code for the admin actions. Updates the status field in the - profiles to 'status'. Updates the status_date. Sets the is_active + Common code for the admin actions. Updates the status field in the + profiles to 'status'. Updates the status_date. Sets the is_active field to True if the status is STA_ACTIVE and False otherwise. """ now = datetime.datetime.now() @@ -120,14 +123,20 @@ accept_flags.short_description = "Accept selected flagged profiles" - - - class BadgeAdmin(admin.ModelAdmin): list_display = ('name', 'html', 'order', 'numeric_id', 'description') list_editable = ('order', 'numeric_id') +# We like the User admin but would like a date hierarcy on date_joined. +class UserAdmin(django.contrib.auth.admin.UserAdmin): + date_hierarchy = 'date_joined' + + admin.site.register(bio.models.UserProfile, UserProfileAdmin) admin.site.register(bio.models.UserProfileFlag, UserProfileFlagAdmin) admin.site.register(bio.models.Badge, BadgeAdmin) + +# Unregister existing ModelAdmin for User, then register ours +admin.site.unregister(django.contrib.auth.models.User) +admin.site.register(django.contrib.auth.models.User, UserAdmin)