Skip to content

Commit

Permalink
Migrate to multiple invite, post-user creation flow.
Browse files Browse the repository at this point in the history
  • Loading branch information
yesimon committed Jan 22, 2013
1 parent 824ed0d commit 5b0e000
Show file tree
Hide file tree
Showing 12 changed files with 602 additions and 133 deletions.
48 changes: 24 additions & 24 deletions hunger/admin.py
Expand Up @@ -2,12 +2,8 @@
from datetime import datetime
from django.contrib import admin
from django.http import HttpResponse
from hunger.models import InvitationCode
from hunger.signals import invite_sent
from hunger.receivers import invitation_code_sent


invite_sent.connect(invitation_code_sent)
from hunger.models import InvitationCode, Invitation
from hunger.utils import now


def export_email(modeladmin, request, queryset):
Expand All @@ -18,23 +14,22 @@ def export_email(modeladmin, request, queryset):
writer.writerow(["email", "is_used", "is_invited", "created", "invited", "used"])

for obj in queryset:
code = obj
email = code.email
is_used = code.is_used
is_invited = code.is_invited
code = obj.code
email = obj.user.email
is_used = obj.is_used
is_invited = obj.is_invited
created = datetime.strftime(code.created, "%Y-%m-%d %H:%M:%S")
try:
invited = datetime.strftime(code.invited, "%Y-%m-%d %H:%M:%S")
invited = datetime.strftime(obj.invited, "%Y-%m-%d %H:%M:%S")
except TypeError:
invited = ""
try:
used = datetime.strftime(code.used, "%Y-%m-%d %H:%M:%S")
used = datetime.strftime(obj.used, "%Y-%m-%d %H:%M:%S")
except TypeError:
used = ""

if len(email) >0 and email != "None":
if email:
row = [email, is_used, is_invited, created, invited, used]
row.append(email)
writer.writerow(row)
# Return CSV file to browser as download
return response
Expand All @@ -43,24 +38,29 @@ def export_email(modeladmin, request, queryset):
def send_invite(modeladmin, request, queryset):
for obj in queryset:
if not obj.is_invited:
invite_sent.send(sender=modeladmin.__class__, email=obj.email,
invitation_code=obj.code,
user=obj.user, request=request)
obj.invited = now()
obj.save(send_email=True, request=request)


def resend_invite(modeladmin, request, queryset):
for obj in queryset:
if obj.is_invited:
invite_sent.send(sender=modeladmin.__class__, email=obj.email,
invitation_code=obj.code,
user=obj.user, request=request)
obj.save(send_email=True, request=request)


class InvitationAdmin(admin.ModelAdmin):
list_display = ('user', 'code', 'used', 'invited')
list_filter = ('code',)
search_fields = ['user__username', 'user__email']
actions = [send_invite, resend_invite, export_email]

class InvitationCodeAdmin(admin.ModelAdmin):
"""Admin for invitation code"""
list_display = ('code', 'is_used', 'is_invited', 'email', 'user', 'created', 'invited', 'used', )
list_filter = ('is_used', 'is_invited', 'created', 'invited', 'used')
search_fields = ['email']
actions = [send_invite, resend_invite, export_email]
list_display = ('code', 'num_invites', 'created_by', 'created', )
list_filter = ('created', )
filter_horizontal = ('invited_users', )
search_fields = ['created_by__email', 'created_by__username']


admin.site.register(Invitation, InvitationAdmin)
admin.site.register(InvitationCode, InvitationCodeAdmin)
6 changes: 2 additions & 4 deletions hunger/forms.py
@@ -1,8 +1,6 @@
from django import forms
from hunger.models import InvitationCode
from hunger.models import Invitation

class InviteRequestForm(forms.ModelForm):
class Meta:
model = InvitationCode
fields = ['email']
widgets = {"email": forms.TextInput({"placeholder": "Enter your email"}), }
model = Invitation
25 changes: 6 additions & 19 deletions hunger/middleware.py
@@ -1,11 +1,7 @@
from django.conf import settings
from django.http import HttpResponseRedirect
from hunger.models import InvitationCode
from hunger.signals import invite_used
from hunger.receivers import invitation_code_used
from hunger.models import InvitationCode, Invitation

#setup signals
invite_used.connect(invitation_code_used)

class BetaMiddleware(object):
"""
Expand Down Expand Up @@ -60,8 +56,6 @@ def process_view(self, request, view_func, view_args, view_kwargs):
#Do nothing is beta is not activated
return

invitation_code = request.COOKIES.get('invitation_code', '')
in_beta, exists = InvitationCode.validate_code(invitation_code)
whitelisted_modules = ['django.contrib.auth.views',
'django.contrib.admin.sites',
'django.views.static',
Expand Down Expand Up @@ -91,27 +85,20 @@ def process_view(self, request, view_func, view_args, view_kwargs):
if view_name in self.always_allow_views or full_view_name in self.always_allow_views:
return

if view_name == self.signup_confirmation_view or full_view_name == self.signup_confirmation_view:
#signup completed - deactivate invitation code
request.session['beta_complete'] = True
invite_used.send(sender=self.__class__, user=request.user, invitation_code=invitation_code)
if full_view_name == self.signup_confirmation_view:
return

if request.user.is_authenticated() and full_view_name not in self.signup_views \
and view_name not in self.signup_views:
# User is logged in, or beta is not active, no need to check anything else.
return

if (view_name in self.signup_views or full_view_name in self.signup_views) and in_beta:

if full_view_name in self.signup_views:
#if beta code is valid and trying to register then let them through
return
else:
# next_page = request.META.get('REQUEST_URI')
next_page = request.path
if in_beta:
return HttpResponseRedirect(self.signup_url + '?next=%s' % next_page)
else:
return HttpResponseRedirect(self.redirect_url + '?next=%s' % next_page)
next_page = request.path
return HttpResponseRedirect(self.redirect_url + '?next=%s' % next_page)

def process_response(self, request, response):
try:
Expand Down
96 changes: 96 additions & 0 deletions hunger/migrations/0001_initial.py
@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'InvitationCode'
db.create_table('hunger_invitationcode', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('code', self.gf('django.db.models.fields.CharField')(unique=True, max_length=8, blank=True)),
('is_used', self.gf('django.db.models.fields.BooleanField')(default=False)),
('is_invited', self.gf('django.db.models.fields.BooleanField')(default=False)),
('email', self.gf('django.db.models.fields.EmailField')(unique=True, max_length=75)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['auth.User'], null=True, blank=True)),
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('invited', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
('used', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
))
db.send_create_signal('hunger', ['InvitationCode'])


def backwards(self, orm):
# Deleting model 'InvitationCode'
db.delete_table('hunger_invitationcode')


models = {
'actstream.action': {
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Action'},
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actor'", 'to': "orm['contenttypes.ContentType']"}),
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'hunger.invitationcode': {
'Meta': {'object_name': 'InvitationCode'},
'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '8', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invited': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'is_invited': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_used': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'used': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
}
}

complete_apps = ['hunger']

0 comments on commit 5b0e000

Please sign in to comment.