Skip to content

Commit

Permalink
added invite function
Browse files Browse the repository at this point in the history
  • Loading branch information
ceberhardt committed Feb 15, 2011
1 parent 430a34a commit 51f4e0d
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 21 deletions.
73 changes: 60 additions & 13 deletions emailauth/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib.auth.models import User

from emailauth.models import UserEmail
from uuid import uuid4

attrs_dict = {}

Expand Down Expand Up @@ -60,7 +61,7 @@ class RegistrationForm(forms.Form):
label=_(u'password'))
password2 = forms.CharField(widget=forms.PasswordInput(render_value=False),
label=_(u'password (again)'))

clean_password2 = clean_password2

def clean_email(self):
Expand All @@ -72,31 +73,77 @@ def clean_email(self):
except UserEmail.DoesNotExist:
pass
return email


def save(self):
data = self.cleaned_data
user = User()
user.email = data['email']
user.first_name = data['name']
user.set_password(data['password1'])
user.username = ('%s' % (uuid4()))[:get_max_length(User, 'username')]
user.is_active = False
user.save()

desired_username = 'id_%d_%s' % (user.id, user.email)
user.username = desired_username[:get_max_length(User, 'username')]
# registration_profile = (
# RegistrationProfile.objects.create_inactive_profile(user))
# registration_profile.save()
#
# profile = Account()
# profile.user = user
# profile.save()

return user #, registration_profile

class InviteForm(forms.Form):
email = forms.EmailField(label=_(u'email address'))
network_name = forms.CharField(label=_(u'network name'))

def clean_email(self):
email = self.cleaned_data['email']

try:
user = UserEmail.objects.get(email=email)
raise forms.ValidationError(_(u'This email is already taken.'))
except UserEmail.DoesNotExist:
pass
return email

def save(self):
data = self.cleaned_data
user = User()
user.email = data['email']
user.set_password(uuid4())
user.username = ('%s' % (uuid4()))[:get_max_length(User, 'username')]
user.is_active = False
user.save()

registration_profile = (
RegistrationProfile.objects.create_inactive_profile(user))
registration_profile.save()

profile = Account()
profile.user = user
profile.save()
class RegistrationAfterInviteForm(forms.Form):

first_name = forms.CharField(label=_(u'first name'),
max_length=get_max_length(User, 'first_name'),
help_text=_(u"That's how we'll call you in emails"))
password1 = forms.CharField(widget=forms.PasswordInput(render_value=False),
label=_(u'password'))
password2 = forms.CharField(widget=forms.PasswordInput(render_value=False),
label=_(u'password (again)'))

email = None

return user, registration_profile
def __init__(self, *args, **kwargs):
self.email = kwargs.pop('email')
super(RegistrationAfterInviteForm, self).__init__(*args, **kwargs)

clean_password2 = clean_password2

def save(self):
data = self.cleaned_data
user = UserEmail.objects.get(email=self.email).user
user.first_name = data['first_name']
user.set_password(data['password1'])
user.is_active = True
user.save()
return user

class PasswordResetRequestForm(forms.Form):
email = forms.EmailField(label=_(u'your email address'))
Expand All @@ -115,7 +162,7 @@ class PasswordResetForm(forms.Form):
label=_(u'password'))
password2 = forms.CharField(widget=forms.PasswordInput(render_value=False),
label=_(u'password (again)'))

clean_password2 = clean_password2


Expand Down
50 changes: 43 additions & 7 deletions emailauth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,20 @@ def make_random_key(self, email):
key = sha_constructor(salt + email).hexdigest()
return key

def create_unverified_email(self, email, user=None):
def create_unverified_email(self, email, user=None, invite=False):
if use_automaintenance():
self.delete_expired()

email_obj = UserEmail(email=email, user=user, default=user is None,
verification_key=self.make_random_key(email))
verification_key=self.make_random_key(email), invite=invite)
return email_obj

def is_to_verify(self, verification_key):
try:
return self.get(verification_key=verification_key)
except self.model.DoesNotExist:
return None

def verify(self, verification_key):
try:
email = self.get(verification_key=verification_key)
Expand All @@ -46,7 +52,7 @@ def delete_expired(self):
date_threshold = (datetime.datetime.now() -
datetime.timedelta(days=email_verification_days()))
expired_emails = self.filter(code_creation_date__lt=date_threshold)

for email in expired_emails:
if not email.verified:
user = email.user
Expand All @@ -72,6 +78,8 @@ class Meta:
verified = models.BooleanField(default=False)
code_creation_date = models.DateTimeField(default=datetime.datetime.now)
verification_key = models.CharField(_('verification key'), max_length=40)
invite = models.BooleanField(default=False)
network_name = models.CharField(_('network_name'), max_length=40)

def __init__(self, *args, **kwds):
super(UserEmail, self).__init__(*args, **kwds)
Expand All @@ -97,7 +105,7 @@ def make_new_key(self):

def send_verification_email(self, first_name=None):
current_site = Site.objects.get_current()

subject = render_to_string('emailauth/verification_email_subject.txt',
{'site': current_site})
# Email subject *must not* contain newlines
Expand All @@ -112,7 +120,7 @@ def send_verification_email(self, first_name=None):

if first_name is None:
first_name = self.user.first_name

message = render_to_string('emailauth/verification_email.txt', {
'verification_key': self.verification_key,
'expiration_days': email_verification_days(),
Expand All @@ -125,11 +133,39 @@ def send_verification_email(self, first_name=None):

django.core.mail.send_mail(subject, message,
settings.DEFAULT_FROM_EMAIL, [self.email])


def verification_key_expired(self):
expiration_date = datetime.timedelta(days=email_verification_days())
return (self.verification_key == self.VERIFIED or
(self.code_creation_date + expiration_date <= datetime.datetime.now()))

verification_key_expired.boolean = True

def send_invite_email(self, network_name):
current_site = Site.objects.get_current()

subject = render_to_string('emailauth/invite_email_subject.txt',
{'site': current_site})
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())

emails = set()
if self.user is not None:
for email in self.__class__.objects.filter(user=self.user):
emails.add(email.email)
emails.add(self.email)
first_email = len(emails) == 1

message = render_to_string('emailauth/invite_email.txt', {
'verification_key': self.verification_key,
'expiration_days': email_verification_days(),
'site': current_site,
'first_email': first_email,
'network_name': network_name,
})

self.code_creation_date = datetime.datetime.now()

django.core.mail.send_mail(subject, message,
settings.DEFAULT_FROM_EMAIL, [self.email])
76 changes: 75 additions & 1 deletion emailauth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from emailauth.forms import (LoginForm, RegistrationForm,
PasswordResetRequestForm, PasswordResetForm, AddEmailForm, DeleteEmailForm,
ConfirmationForm)
ConfirmationForm, InviteForm, RegistrationAfterInviteForm)
from emailauth.models import UserEmail

from emailauth.utils import (use_single_email, requires_single_email_mode,
Expand Down Expand Up @@ -151,6 +151,77 @@ def register_continue(request, email,
return render_to_response(template_name, {'email': email},
RequestContext(request))

def default_invite_callback(form, email):
data = form.cleaned_data
user = User()
user.is_active = False
user.email = email.email
user.set_password(uuid4())
user.username = ('%s' % (uuid4()))[:get_max_length(User, 'username')]
user.save()
email.user = user

def invite(request, callback=default_invite_callback):
if request.method == 'POST':
form = InviteForm(request.POST)
if form.is_valid():
email_obj = UserEmail.objects.create_unverified_email(
form.cleaned_data['email'], invite=True)
email_obj.send_invite_email(form.cleaned_data['network_name'])

if callback is not None:
callback(form, email_obj)

site = Site.objects.get_current()
email_obj.user.message_set.create(message='Welcome to %s.' % site.name)

email_obj.network_name = form.cleaned_data['network_name']

email_obj.save()
return HttpResponseRedirect(reverse('emailauth_invite_continue',
args=[quote_plus(email_obj.email)]))
else:
form = InviteForm()

return render_to_response('emailauth/invite.html', {'form': form},
RequestContext(request))


def invite_continue(request, email,
template_name='emailauth/invite_continue.html'):

return render_to_response(template_name, {'email': email},
RequestContext(request))

def default_register_after_invite_callback(form, email):
data = form.cleaned_data
user = email.user
user.first_name = data['first_name']
user.is_active = True
user.set_password(data['password1'])
user.save()
email.user = user

def register_after_invite(request, email, verification_key, callback=default_register_after_invite_callback):
if request.method == 'POST':
form = RegistrationAfterInviteForm(request.POST, email=email)
if form.is_valid():
from django.contrib.auth import login
email_obj = UserEmail.objects.verify(verification_key)
if not email_obj.verified or not email_obj.invite:
return HttpResponseRedirect(settings.LOGIN_URL)
if callback is not None:
callback(form, email_obj)
email_obj.user.backend = 'emailauth.backends.EmailBackend'
login(request, email_obj.user)
return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
else:
form = RegistrationForm()

return render_to_response('emailauth/register_after_invite.html', {'form': form,
'email': email},
RequestContext(request))


def default_verify_callback(request, email):
email.user.is_active = True
Expand All @@ -170,6 +241,9 @@ def verify(request, verification_key, template_name='emailauth/verify.html',
extra_context=None, callback=default_verify_callback):

verification_key = verification_key.lower() # Normalize before trying anything with it.
email = UserEmail.objects.is_to_verify(verification_key)
if email and email.invite and email.verification_key:
return register_after_invite(request, email, verification_key)
email = UserEmail.objects.verify(verification_key)


Expand Down

0 comments on commit 51f4e0d

Please sign in to comment.