--- /dev/null
+# Copyright 2011 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above
+# copyright notice, this list of conditions and the following
+# disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+from django import forms
+from django.utils.translation import ugettext as _
+from django.conf import settings
+
+from pithos.im.models import User
+
+openid_providers = (
+('Google','https://www.google.com/accounts/o8/id'),
+('Yahoo', 'http://yahoo.com/'),
+('AOL','http://openid.aol.com/%s/'),
+('OpenID', None),
+('MyOpenID','http://%s.myopenid.com/'),
+('LiveJournal', 'http://%s.livejournal.com/'),
+('Flickr', 'http://flickr.com/%s/'),
+('Technorati', 'http://technorati.com/people/technorati/%s/'),
+('Wordpress', 'http://%s.wordpress.com/'),
+('Blogger', 'http://%s.blogspot.com/'),
+('Verisign', 'http://%s.pip.verisignlabs.com/'),
+('Vidoop', 'http://%s.myvidoop.com/'),
+('ClaimID','http://claimid.com/%s')
+)
+
+class RegisterForm(forms.Form):
+ uniq = forms.CharField(widget=forms.widgets.TextInput())
+ provider = forms.CharField(widget=forms.TextInput(),
+ label=u'Identity Provider')
+ email = forms.EmailField(widget=forms.TextInput(),
+ label=_('Email address'))
+ realname = forms.CharField(widget=forms.TextInput(),
+ label=u'Real Name')
+
+ def __init__(self, *args, **kwargs):
+ super(forms.Form, self).__init__(*args, **kwargs)
+
+ #set readonly form fields
+ self.fields['provider'].widget.attrs['readonly'] = True
+
+ def clean_uniq(self):
+ """
+ Validate that the uniq is alphanumeric and is not already
+ in use.
+
+ """
+ try:
+ user = User.objects.get(uniq__iexact=self.cleaned_data['uniq'])
+ except User.DoesNotExist:
+ return self.cleaned_data['uniq']
+ raise forms.ValidationError(_("A user with that uniq already exists."))
+
+class ShibbolethRegisterForm(RegisterForm):
+ pass
+
+class TwitterRegisterForm(RegisterForm):
+ pass
+
+class OpenidRegisterForm(RegisterForm):
+ openidurl = forms.ChoiceField(widget=forms.Select,
+ choices=((url, l) for l, url in openid_providers))
+
+class LocalRegisterForm(RegisterForm):
+ """ local signup form"""
+ password = forms.CharField(widget=forms.PasswordInput(render_value=False),
+ label=_('Password'))
+ password2 = forms.CharField(widget=forms.PasswordInput(render_value=False),
+ label=_('Confirm Password'))
+
+ def __init__(self, *args, **kwargs):
+ super(LocalRegisterForm, self).__init__(*args, **kwargs)
+
+ def clean_uniq(self):
+ """
+ Validate that the uniq is alphanumeric and is not already
+ in use.
+
+ """
+ try:
+ user = User.objects.get(uniq__iexact=self.cleaned_data['uniq'])
+ except User.DoesNotExist:
+ return self.cleaned_data['uniq']
+ raise forms.ValidationError(_("A user with that uniq already exists."))
+
+ def clean(self):
+ """
+ Verifiy that the values entered into the two password fields
+ match. Note that an error here will end up in
+ ``non_field_errors()`` because it doesn't apply to a single
+ field.
+
+ """
+ if 'password' in self.cleaned_data and 'password2' in self.cleaned_data:
+ if self.cleaned_data['password'] != self.cleaned_data['password2']:
+ raise forms.ValidationError(_("The two password fields didn't match."))
+ return self.cleaned_data
+
+class InvitedRegisterForm(RegisterForm):
+ inviter = forms.CharField(widget=forms.TextInput(),
+ label=_('Inviter Real Name'))
+
+ def __init__(self, *args, **kwargs):
+ super(RegisterForm, self).__init__(*args, **kwargs)
+
+ #set readonly form fields
+ self.fields['uniq'].widget.attrs['readonly'] = True
+ self.fields['inviter'].widget.attrs['readonly'] = True
+ self.fields['provider'].widget.attrs['provider'] = True
+
+class InvitedLocalRegisterForm(LocalRegisterForm, InvitedRegisterForm):
+ pass
+
+class InvitedOpenidRegisterForm(OpenidRegisterForm, InvitedRegisterForm):
+ pass
+
+class InvitedTwitterRegisterForm(TwitterRegisterForm, InvitedRegisterForm):
+ pass
+
+class InvitedShibbolethRegisterForm(ShibbolethRegisterForm, InvitedRegisterForm):
+ pass
\ No newline at end of file
# Adding field 'User.provider'
db.add_column('im_user', 'provider', self.gf('django.db.models.fields.CharField')(default='', max_length=255), keep_default=False)
- # Deleting field 'Invitation.is_accepted'
- db.delete_column('im_invitation', 'is_accepted')
-
- # Deleting field 'Invitation.accepted'
- db.delete_column('im_invitation', 'accepted')
+ # Adding field 'User.openidurl'
+ db.add_column('im_user', 'openidurl', self.gf('django.db.models.fields.CharField')(default='', max_length=255), keep_default=False)
# Adding field 'Invitation.is_consumed'
db.add_column('im_invitation', 'is_consumed', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
# Deleting field 'User.provider'
db.delete_column('im_user', 'provider')
- # Adding field 'Invitation.is_accepted'
- db.add_column('im_invitation', 'is_accepted', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
-
- # Adding field 'Invitation.accepted'
- db.add_column('im_invitation', 'accepted', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)
+ # Deleting field 'User.openidurl'
+ db.delete_column('im_user', 'openidurl')
# Deleting field 'Invitation.is_consumed'
db.delete_column('im_invitation', 'is_consumed')
models = {
'im.invitation': {
'Meta': {'object_name': 'Invitation'},
+ 'accepted': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
'consumed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.User']"}),
+ 'is_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_consumed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255'})
'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.IntegerField', [], {'default': '4'}),
+ 'openidurl': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'provider': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'realname': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
from pithos.im.interface import get_quota, set_quota
+from hashlib import new as newhasher
class User(models.Model):
ACCOUNT_STATE = (
is_verified = models.BooleanField('Verified?', default=False)
+ openidurl = models.CharField('OpenID url', max_length=255, default='')
+
@property
def quota(self):
return get_quota(self.uniq)
@property
def invitation(self):
- return Invitation.objects.get(uniq=self.uniq)
-
+ try:
+ return Invitation.objects.get(uniq=self.uniq)
+ except Invitation.DoesNotExist:
+ return None
+
def save(self, update_timestamps=True, **kwargs):
if update_timestamps:
if not self.id:
self.created = datetime.now()
self.updated = datetime.now()
+
super(User, self).save(**kwargs)
+
+ #invitation consume
+ if self.invitation and not self.invitation.is_consumed:
+ self.invitation.consume()
def renew_token(self):
md5 = hashlib.md5()
realname = models.CharField('Real name', max_length=255)
uniq = models.CharField('Unique ID', max_length=255)
code = models.BigIntegerField('Invitation code', db_index=True)
+ #obsolete: we keep it just for transfering the data
+ is_accepted = models.BooleanField('Accepted?', default=False)
is_consumed = models.BooleanField('Consumed?', default=False)
created = models.DateTimeField('Creation date', auto_now_add=True)
+ #obsolete: we keep it just for transfering the data
+ accepted = models.DateTimeField('Acceptance date', null=True, blank=True)
consumed = models.DateTimeField('Consumption date', null=True, blank=True)
+ def consume(self):
+ self.is_consumed = True
+ self.consumed = datetime.now()
+ self.save()
+
def __unicode__(self):
return '%s -> %s [%d]' % (self.inviter, self.uniq, self.code)
from urllib import unquote
+from hashlib import new as newhasher
+
def login(request):
username = request.POST.get('username')
password = request.POST.get('password')
except User.DoesNotExist:
return HttpResponseBadRequest('No such user')
+ hasher = newhasher('sha256')
+ hasher.update(password)
+ password = hasher.hexdigest()
+
if not password or user.password != password:
return HttpResponseBadRequest('Wrong password')
return HttpResponseBadRequest('Unverified account')
next = request.POST.get('next')
-
return prepare_response(request, user, next)
-
-#def activate(request):
-# token = request.GET.get('auth')
-# next = request.GET.get('next')
-# try:
-# user = User.objects.get(auth_token=token)
-# except User.DoesNotExist:
-# return HttpResponseBadRequest('No such user')
-#
-# user.state = 'ACTIVE'
-# user.save()
-# return prepare_response(request, user, next, renew=True)
+
+def activate(request):
+ token = request.GET.get('auth')
+ next = request.GET.get('next')
+ try:
+ user = User.objects.get(auth_token=token)
+ except User.DoesNotExist:
+ return HttpResponseBadRequest('No such user')
+
+ user.state = 'ACTIVE'
+ user.save()
+ return prepare_response(request, user, next, renew=True)
def reset_password(request):
if request.method == 'GET':
from pithos.im.models import User
-
def get_or_create_user(uniq, realname, affiliation, level):
"""Find or register a user into the internal database
and issue a token for subsequent requests.
'realname': realname,
'affiliation': affiliation,
'level': level,
- 'invitations': settings.INVITATIONS_PER_LEVEL[level]
+ 'invitations': settings.INVITATIONS_PER_LEVEL[level],
+ 'state':'PENDING',
})
if created:
user.renew_token()
</div>
</fieldset>
<div>
- <a href="{% url pithos.im.views.local_create %}">Sign up</a>
+ <a href="{% url pithos.im.views.register 'local' %}">Sign up</a>
</div>
<div>
<a href="{% url pithos.im.views.reclaim_password %}">Forgot your password?</a>
--- /dev/null
+{% extends "admin_base.html" %}
+
+{% load formatters %}
+
+{% block body %}
+
+<div class="row">
+ <div class="offset10 span3">
+ <form method="get">
+ <div class="input">
+ <input class="span3" name="filter" type="search" placeholder="search" value="{{ filter }}">
+ </div>
+ </form>
+ </div>
+</div>
+
+<table class="zebra-striped id-sorted">
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>Uniq</th>
+ <th>Real Name</th>
+ <th>Affiliation</th>
+ <th>Email</th>
+ <th>Inviter</th>
+ <th>Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for user in users %}
+ <tr>
+ <td>{{ user.id }}</td>
+ <td>{{ user.uniq }}</td>
+ <td>{{ user.realname }}</td>
+ <td>{{ user.affiliation }}</td>
+ <td>{{ user.email }}</td>
+ <td>{{ user.inviter.realname }}</td>
+ <td>
+ <form action="{% url pithos.im.views.users_activate user.id %}" method="post">
+ <input type="hidden" name="page" value="{{ page }}">
+ <button type="submit" class="btn primary">Activate</button>
+ </form>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+{% if pages|length > 1 %}
+<div class="pagination">
+ <ul>
+ {% if prev %}
+ <li class="prev"><a href="?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}">← Previous</a></li>
+ {% else %}
+ <li class="prev disabled"><a href="#">← Previous</a></li>
+ {% endif %}
+
+ {% for p in pages %}
+ <li{% if page == p %} class="active"{% endif %}><a href="?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}">{{ p }}</a></li>
+ {% endfor %}
+
+ {% if next %}
+ <li class="next"><a href="?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}">→ Next</a></li>
+ {% else %}
+ <li class="next disabled"><a href="#">→ Next</a></li>
+ {% endif %}
+ </ul>
+</div>
+{% endif %}
+
+<br /><br />
+{% endblock body %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title%}
+ <h1>Welcome</h1>{{provider}}
+{% endblock title%}
+
+{% block body %}
+<form action={%url pithos.im.views.register provider%} method="post">
+ {{ formset.as_p }}
+<div>
+ <button type="submit" class="btn primary">Register</button>
+</div>
+<input type="hidden" name="provider" value="{{ provider }}">
+<input type="hidden" name="code" value="{{ code }}">
+<input type="hidden" name="next" value="{{ next }}">
+
+</form>
+{% endblock body %}
\ No newline at end of file
--- /dev/null
+{% extends "base.html" %}
+
+{% block title%}
+ <h1>Welcome</h1>
+{% endblock title%}
+
+{% block body %}
+<form action={%url pithos.im.views.signup %} method="post">
+ <p>Select an Identity Provider:</p>
+ {% for choice in im_modules%}
+ <div class="row">
+ <div class="span8">
+ <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice }}" />
+ <label for="choice{{ forloop.counter }}"><img src="/im/static/{{ choice }}.png" width="80"></label>
+ </div>
+ </div>
+ {% endfor %}
+<div>
+ {% if inv %}
+ <input type=hidden name="code" value={{ inv.code }} />
+ {% endif %}
+ <button type="submit" class="btn primary">Signup</button>
+</div>
+<input type="hidden" name="provider" value="{{ provider }}">
+<input type="hidden" name="code" value="{{ code }}">
+<input type="hidden" name="next" value="{{ next }}">
+</form>
+{% endblock body %}
\ No newline at end of file
<div class="actions">
<input type="hidden" name="next" value="{{ next }}">
+ <input type="hidden" name="auth" value="{{ user.auth_token }}">
<button type="submit" class="btn primary">Verify</button>
</div>
(r'^profile/edit/?$', 'users_edit'),
(r'^signup/?$', 'signup'),
- (r'^local/create/?$', 'local_create'),
- (r'^openid/create/?$', 'openid_create'),
-)
-
-
-urlpatterns += patterns('',
- (r'^account/', include('django_authopenid.urls')),
+ (r'^register/(\w+)?$', 'register'),
+ #(r'^signup/complete/?$', 'signup_complete'),
+ #(r'^local/create/?$', 'local_create'),
)
urlpatterns += patterns('pithos.im.target',
)
urlpatterns += patterns('pithos.im.target',
(r'^local/?$', 'local.login'),
-# (r'^local/activate/?$', 'local.activate'),
+ (r'^local/activate/?$', 'local.activate'),
(r'^local/reset/?$', 'local.reset_password')
)
-#if 'invitation' in settings.IM_STANDARD_MODULES:
-# urlpatterns += patterns('pithos.im.views',
-# (r'^invite/?$', 'invite'),
-# )
+if settings.INVITATIONS_ENABLED:
+ urlpatterns += patterns('pithos.im.views',
+ (r'^invite/?$', 'invite'),
+ )
# urlpatterns += patterns('pithos.im.target',
# (r'^login/invitation/?$', 'invitation.login')
# )
import logging
import socket
import csv
+import sys
from datetime import datetime
from functools import wraps
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
from django.shortcuts import redirect
from django.template.loader import render_to_string
+from django.shortcuts import render_to_response
from django.utils.http import urlencode
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
-from django import forms
+from django.forms import Form
+from django.forms.formsets import formset_factory
+from openid.consumer.consumer import Consumer, \
+ SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
-from django_authopenid.forms import *
+from hashlib import new as newhasher
from urllib import quote
+from pithos.im.openid_store import PithosOpenIDStore
from pithos.im.models import User, Invitation
from pithos.im.util import isoformat
-
+from pithos.im.forms import *
def render_response(template, tab=None, status=200, **kwargs):
if tab is None:
send_mail('Pithos account activation', message, sender, [user.email])
logging.info('Sent activation %s', user)
-def local_create(request):
- if request.method == 'GET':
- provider = request.GET.get('provider', None)
- if not provider:
- return HttpResponseBadRequest('No provider')
- code = request.GET.get('code', None)
- kwargs = {'provider':provider}
- if code:
- try:
- invitation = Invitation.objects.get(code = code)
- kwargs['inv']=invitation
- except Invitation.DoesNotExist:
- return HttpResponseBadRequest('Wrong invitation code')
- return render_response('local_create.html', **kwargs)
- elif request.method == 'POST':
- username = request.POST.get('uniq')
- realname = request.POST.get('realname')
- email = request.POST.get('email')
- password = request.POST.get('password')
- retype_password = request.POST.get('retype_passwords')
- status = 'success'
- cookie_value = None
- if not username:
- status = 'error'
- message = 'No username provided'
- elif not password:
- status = 'error'
- message = 'No password provided'
- elif not retype_password:
- status = 'error'
- message = 'Need to enter password twice'
- elif password != retype_password:
- status = 'error'
- message = 'Passwords do not match'
- elif not email:
- status = 'error'
- message = 'No email provided'
-
- if status == 'success':
- try:
- user = User.objects.get(uniq=username)
- status = 'error'
- message = 'Username is not available'
- except User.DoesNotExist:
- user = User()
- user.uniq = username
- user.realname = realname
- user.email = request.POST.get('email')
- user.password = request.POST.get('password')
- user.is_admin = False
- user.quota = 0
- user.state = 'ACTIVE' if is_preaccepted(user) else 'PENDING'
- if user.invitation:
- user.invitation.is_consumed = True
- user.level = 1
- user.renew_token()
- try:
- send_verification(request.build_absolute_uri('/').rstrip('/'), user)
- message = _('Verification sent to %s' % user.email)
- user.save()
- except (SMTPException, socket.error) as e:
- print e
- status = 'error'
- name = 'strerror'
- message = getattr(e, name) if hasattr(e, name) else e
-
- html = render_to_string('local_create.html', {
- 'status': status,
- 'message': message})
- response = HttpResponse(html)
- return response
-
def send_password(baseurl, user):
url = settings.PASSWORD_RESET_TARGET % (baseurl,
quote(user.uniq),
return render_response('reclaim.html')
elif request.method == 'POST':
username = request.POST.get('uniq')
- username = '%s@local' % username
try:
user = User.objects.get(uniq=username)
try:
@requires_login
def users_profile(request):
next = request.GET.get('next')
- user = User.objects.get(uniq=request.user)
+ try:
+ user = User.objects.get(uniq=request.user)
+ except User.DoesNotExist:
+ user = User.objects.get(auth_token=request.GET.get('auth', None))
states = [x[0] for x in User.ACCOUNT_STATE]
return render_response('users_profile.html',
user=user,
@requires_login
def users_edit(request):
- user = User.objects.get(uniq=request.user)
+ try:
+ user = User.objects.get(uniq=request.user)
+ except User.DoesNotExist:
+ token = request.POST.get('auth', None)
+ users = User.objects.all()
+ user = User.objects.get(auth_token=token)
user.realname = request.POST.get('realname')
user.affiliation = request.POST.get('affiliation')
user.is_verified = True
'status': status,
'message': message})
return HttpResponse(html)
+
+def signup(request):
+ if request.method == 'GET':
+ kwargs = {'im_modules':settings.IM_MODULES,
+ 'next':request.GET.get('next', ''),
+ 'code':request.GET.get('code', '')}
+ return render_response('signup.html', **kwargs)
+ elif request.method == 'POST':
+ provider = request.POST.get('choice')
+ if not provider:
+ return on_failure(_('No provider selected'), template='signup.html')
+
+ kwargs = {'code':request.POST.get('code', ''),
+ 'next':request.POST.get('next', '')}
+ url = '%s%s?' %(reverse('pithos.im.views.register'), provider)
+ for k,v in kwargs.items():
+ if v:
+ url = '%s%s=%s&' %(url, k, v)
+ return redirect(url)
+
+def render_registration(provider, code='', next=''):
+ initial_data = {'provider':provider}
+ if settings.INVITATIONS_ENABLED and code:
+ try:
+ print '#', type(code), code
+ invitation = Invitation.objects.get(code=code)
+ if invitation.is_consumed:
+ return HttpResponseBadRequest('Invitation has beeen used')
+ initial_data.update({'uniq':invitation.uniq,
+ 'email':invitation.uniq,
+ 'realname':invitation.realname})
+ try:
+ inviter = User.objects.get(uniq=invitation.inviter)
+ initial_data['inviter'] = inviter.realname
+ except User.DoesNotExist:
+ pass
+ except Invitation.DoesNotExist:
+ return on_failure(_('Wrong invitation code'), template='register.html')
+
+ prefix = 'Invited' if code else ''
+ formclassname = '%s%sRegisterForm' %(prefix, provider.capitalize())
+ formclass_ = getattr(sys.modules['pithos.im.forms'], formclassname)
+ RegisterFormSet = formset_factory(formclass_, extra=0)
+ formset = RegisterFormSet(initial=[initial_data])
+ return render_response('register.html',
+ formset=formset,
+ next=next,
+ filter=filter,
+ code=code)
def is_preaccepted(user):
- return True if settings.INVITATIONS_ENABLED and user.invitation else False
+ if user.invitation and not user.invitation.is_consumed:
+ return True
+
+ return False
-def signup(request):
+def should_send_verification():
+ if not settings.INVITATIONS_ENABLED:
+ return True
+ return False
+
+def register(request, provider):
+ print '---', request
+ code = request.GET.get('code')
+ next = request.GET.get('next')
if request.method == 'GET':
- kwargs = {'im_modules':settings.IM_MODULES}
- if settings.INVITATIONS_ENABLED:
- code = request.GET.get('code')
- if not code:
- return HttpResponseBadRequest('No code')
- try:
- invitation = Invitation.objects.get(code=code)
- if invitation.is_consumed:
- return HttpResponseBadRequest('Invitation has beeen used')
- except Invitation.DoesNotExist:
- return HttpResponseBadRequest('Wrong invitation code')
- kwargs['inv'] = invitation
- return render_response('signup.html', **kwargs)
+ code = request.GET.get('code', '')
+ next = request.GET.get('next', '')
+ if provider not in settings.IM_MODULES:
+ return on_failure(_('Invalid provider'))
+ return render_registration(provider, code, next)
elif request.method == 'POST':
- choice = request.POST.get('choice')
- if not choice:
- return HttpResponseBadRequest('No provider selected')
+ provider = request.POST.get('form-0-provider')
+ inviter = request.POST.get('form-0-inviter')
+
+ #instantiate the form
+ prefix = 'Invited' if inviter else ''
+ formclassname = '%sRegisterForm' %(provider.capitalize())
+ formclass_ = getattr(sys.modules['pithos.im.forms'], formclassname)
+ RegisterFormSet = formset_factory(formclass_, extra=0)
+ formset = RegisterFormSet(request.POST)
+ if not formset.is_valid():
+ return render_to_response('register.html',
+ {'formset':formset,
+ 'code':code,
+ 'next':next})
- provider = choice
+ user = User()
+ for form in formset.forms:
+ for field in form.fields:
+ if hasattr(user, field):
+ setattr(user, field, form.cleaned_data[field])
+ break
- code = request.POST.get('code')
+ if user.openidurl:
+ redirect_url = reverse('pithos.im.views.create')
+ return ask_openid(request,
+ user.openidurl,
+ redirect_url,
+ 'signup')
- if provider == 'local':
- url = reverse('pithos.im.views.local.create')
- if settings.INVITATIONS_ENABLED and code:
- url = '%s?code=%s&provider=%s' % (url, code, provider)
- return redirect(url)
- elif provider == 'twitter':
- url = reverse('pithos.im.views.openid_create')
+ #save hashed password
+ if user.password:
+ hasher = newhasher('sha256')
+ hasher.update(user.password)
+ user.password = hasher.hexdigest()
+
+ user.renew_token()
+
+ if is_preaccepted(user):
+ user.state = 'ACTIVE'
+ user.save()
+ url = reverse('pithos.im.views.index')
return redirect(url)
+
+ status = 'success'
+ if should_send_verification():
+ try:
+ send_verification(request.build_absolute_uri('/').rstrip('/'), user)
+ message = _('Verification sent to %s' % user.email)
+ user.save()
+ except (SMTPException, socket.error) as e:
+ status = 'error'
+ name = 'strerror'
+ message = getattr(e, name) if hasattr(e, name) else e
+ else:
+ user.save()
+ message = _('Registration completed. You will receive an email upon your account\'s activation')
+
+ return info(status, message)
+
+#def discover_extensions(openid_url):
+# service = discover(openid_url)
+# use_ax = False
+# use_sreg = False
+# for endpoint in service[1]:
+# if not use_sreg:
+# use_sreg = sreg.supportsSReg(endpoint)
+# if not use_ax:
+# use_ax = endpoint.usesExtension("http://openid.net/srv/ax/1.0")
+# if use_ax and use_sreg: break
+# return use_ax, use_sreg
+#
+#def ask_openid(request, openid_url, redirect_to, on_failure=None):
+# """ basic function to ask openid and return response """
+# on_failure = on_failure or signin_failure
+# sreg_req = None
+# ax_req = None
+#
+# trust_root = getattr(
+# settings, 'OPENID_TRUST_ROOT', request.build_absolute_uri() + '/'
+# )
+# request.session = {}
+# consumer = Consumer(request.session, PithosOpenIDStore())
+# try:
+# auth_request = consumer.begin(openid_url)
+# except DiscoveryFailure:
+# msg = _("The OpenID %s was invalid") % openid_url
+# return on_failure(request, msg)
+#
+# get capabilities
+# use_ax, use_sreg = discover_extensions(openid_url)
+# if use_sreg:
+# set sreg extension
+# we always ask for nickname and email
+# sreg_attrs = getattr(settings, 'OPENID_SREG', {})
+# sreg_attrs.update({ "optional": ['nickname', 'email'] })
+# sreg_req = sreg.SRegRequest(**sreg_attrs)
+# if use_ax:
+# set ax extension
+# we always ask for nickname and email
+# ax_req = ax.FetchRequest()
+# ax_req.add(ax.AttrInfo('http://schema.openid.net/contact/email',
+# alias='email', required=True))
+# ax_req.add(ax.AttrInfo('http://schema.openid.net/namePerson/friendly',
+# alias='nickname', required=True))
+#
+# add custom ax attrs
+# ax_attrs = getattr(settings, 'OPENID_AX', [])
+# for attr in ax_attrs:
+# if len(attr) == 2:
+# ax_req.add(ax.AttrInfo(attr[0], required=alias[1]))
+# else:
+# ax_req.add(ax.AttrInfo(attr[0]))
+#
+# if sreg_req is not None:
+# auth_request.addExtension(sreg_req)
+# if ax_req is not None:
+# auth_request.addExtension(ax_req)
+#
+# redirect_url = auth_request.redirectURL(trust_root, redirect_to)
+# return HttpResponseRedirect(redirect_url)
+
+def info(status, message, template='base.html'):
+ html = render_to_string(template, {
+ 'status': status,
+ 'message': message})
+ response = HttpResponse(html)
+ return response
-def openid_create(request):
- form1 = OpenidSigninForm()
- kwargs = {'form1':form1}
- return render_response('openid_create.html')
\ No newline at end of file
+def on_success(message, template='base.html'):
+ return info('success', message)
+
+def on_failure(message, template='base.html'):
+ return info('error', message)
\ No newline at end of file