change invitations mechanism
authorSofia Papagiannaki <papagian@gmail.com>
Tue, 6 Dec 2011 09:33:13 +0000 (11:33 +0200)
committerSofia Papagiannaki <papagian@gmail.com>
Tue, 6 Dec 2011 09:33:13 +0000 (11:33 +0200)
Ref #1689

pithos/im/migrations/0003_auto__add_field_user_provider__del_field_invitation_is_accepted__del_f.py [new file with mode: 0644]
pithos/im/models.py
pithos/im/target/local.py
pithos/im/templates/admin.html
pithos/im/templates/admin_base.html
pithos/im/templates/index.html
pithos/im/templates/invitations_list.html
pithos/im/templates/local_create.html
pithos/im/urls.py
pithos/im/views.py
pithos/settings.d/20-im.conf

diff --git a/pithos/im/migrations/0003_auto__add_field_user_provider__del_field_invitation_is_accepted__del_f.py b/pithos/im/migrations/0003_auto__add_field_user_provider__del_field_invitation_is_accepted__del_f.py
new file mode 100644 (file)
index 0000000..d57045e
--- /dev/null
@@ -0,0 +1,79 @@
+# encoding: 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 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 'Invitation.is_consumed'
+        db.add_column('im_invitation', 'is_consumed', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
+
+        # Adding field 'Invitation.consumed'
+        db.add_column('im_invitation', 'consumed', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)
+
+
+    def backwards(self, orm):
+        
+        # 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 'Invitation.is_consumed'
+        db.delete_column('im_invitation', 'is_consumed')
+
+        # Deleting field 'Invitation.consumed'
+        db.delete_column('im_invitation', 'consumed')
+
+
+    models = {
+        'im.invitation': {
+            'Meta': {'object_name': 'Invitation'},
+            '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_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'})
+        },
+        'im.user': {
+            'Meta': {'object_name': 'User'},
+            'affiliation': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
+            'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+            'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {}),
+            'email': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'invitations': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            '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'}),
+            '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'}),
+            'state': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '16'}),
+            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
+            'updated': ('django.db.models.fields.DateTimeField', [], {})
+        }
+    }
+
+    complete_apps = ['im']
index 58f1a68..cf2e5fa 100644 (file)
@@ -49,7 +49,8 @@ class User(models.Model):
         ('ACTIVE', 'Active'),
         ('DELETED', 'Deleted'),
         ('SUSPENDED', 'Suspended'),
-        ('UNVERIFIED', 'Unverified')
+        ('UNVERIFIED', 'Unverified'),
+        ('PENDING', 'Pending')
     )
     
     uniq = models.CharField('Unique ID', max_length=255, null=True)
@@ -57,8 +58,9 @@ class User(models.Model):
     realname = models.CharField('Real Name', max_length=255, default='')
     email = models.CharField('Email', max_length=255, default='')
     affiliation = models.CharField('Affiliation', max_length=255, default='')
+    provider = models.CharField('Provider', max_length=255, default='')
     state = models.CharField('Account state', choices=ACCOUNT_STATE,
-                                max_length=16, default='ACTIVE')
+                                max_length=16, default='PENDING')
     
     #for invitations
     level = models.IntegerField('Inviter level', default=4)
@@ -89,6 +91,10 @@ class User(models.Model):
     def quota(self, value):
         set_quota(self.uniq, value)
     
+    @property
+    def invitation(self):
+        return Invitation.objects.get(uniq=self.uniq)
+   
     def save(self, update_timestamps=True, **kwargs):
         if update_timestamps:
             if not self.id:
@@ -110,16 +116,15 @@ class User(models.Model):
     def __unicode__(self):
         return self.uniq
 
-
 class Invitation(models.Model):
     inviter = models.ForeignKey(User, related_name='invitations_sent',
                                 null=True)
     realname = models.CharField('Real name', max_length=255)
-    uniq = models.CharField('Real name', max_length=255)
+    uniq = models.CharField('Unique ID', max_length=255)
     code = models.BigIntegerField('Invitation code', db_index=True)
-    is_accepted = models.BooleanField('Accepted?', default=False)
+    is_consumed = models.BooleanField('Consumed?', default=False)
     created = models.DateTimeField('Creation date', auto_now_add=True)
-    accepted = models.DateTimeField('Acceptance date', null=True, blank=True)
+    consumed = models.DateTimeField('Consumption date', null=True, blank=True)
     
     def __unicode__(self):
         return '%s -> %s [%d]' % (self.inviter, self.uniq, self.code)
index 832881a..1f9685b 100644 (file)
@@ -41,13 +41,13 @@ from pithos.im.models import User
 from urllib import unquote
 
 def login(request):
-    username = '%s@local' % request.POST.get('username')
+    username = request.POST.get('username')
     password = request.POST.get('password')
     
     if not username:
         return HttpResponseBadRequest('No user')
     
-    if not username:
+    if not password:
         return HttpResponseBadRequest('No password')
     
     try:
@@ -65,17 +65,17 @@ def login(request):
     
     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':
index ae3cee4..754e114 100644 (file)
@@ -2,7 +2,7 @@
 
 {% block body %}
 <ul class="unstyled">
-  <li><strong>{{ stats.users }}</strong> Users</li>
-  <li><strong>{{ stats.invitations }}</strong> Invitation{{ stats.invitations|pluralize }} sent (<strong>{{ stats.invitations_accepted }}</strong> accepted)</li>
+  <li><strong>{{ stats.users }}</strong> User{{ stats.users|pluralize }} (<strong>{{ stats.pending }}</strong> pending)</li>
+  <li><strong>{{ stats.invitations }}</strong> Invitation{{ stats.invitations|pluralize }} sent (<strong>{{ stats.invitations_consumed }}</strong> consumed)</li>
 </ul>
 {% endblock body %}
index 21d62ae..a86c33f 100644 (file)
@@ -8,6 +8,9 @@
   <li{% ifequal tab "users" %} class="active"{% endifequal %}>
     <a href="{% url pithos.im.views.users_list %}">Users</a>
   </li>
+  <li{% ifequal tab "pending" %} class="active"{% endifequal %}>
+    <a href="{% url pithos.im.views.pending_users %}">Pending Users</a>
+  </li>
   <li{% ifequal tab "invitations" %} class="active"{% endifequal %}>
     <a href="{% url pithos.im.views.invitations_list %}">Invitations</a>
   </li>
index 8d994e3..9e5c8ca 100644 (file)
@@ -7,7 +7,7 @@
     
 {% block body%}
     <div class="row">
-    {% if "local" in standard_modules %}
+    {% if "local" in im_modules %}
       <div class="span4">
         <h4>Local account</h4>
         <form action="{% url pithos.im.target.local.login %}" method="post" class="form-stacked">
         </form>
       </div>
     {% endif %}
-    {% if "invitation" in standard_modules %}
-      <div class="span4">
-        <h4>Invitation</h4>
-        <form action="{% url pithos.im.target.invitation.login %}" class="form-stacked">
-          <fieldset>
-            <div class="clearfix">
-              <label for="code">Code:</label>
-              <div class="input">
-                <input class="span3" id="user-code" name="code" type="text" />
-              </div>
-            </div>
-          </fieldset>
-          <div class="">
-            <input type="hidden" name="next" value="{{ next }}">
-            <button type="submit" class="btn primary">Go</button>
-          </div>
-        </form>
-      </div>
-    {% endif %}
     {% if other_modules %}
       <div class="span8">
         <h4>Other provider</h4>
index 9e662a0..e54b408 100644 (file)
@@ -23,9 +23,9 @@
       <th>Code</th>
       <th>Inviter Uniq</th>
       <th>Inviter Real Name</th>
-      <th>Is_accepted</th>
+      <th>Is consumed</th>
       <th>Created</th>
-      <th>Accepted</th>
+      <th>Consumed</th>
     </tr>
   </thead>
   <tbody>
@@ -37,9 +37,9 @@
       <td>{{ inv.code }}</td>
       <td>{{ inv.inviter.uniq }}</td>
       <td>{{ inv.inviter.realname }}</td>
-      <td>{{ inv.is_accepted }}</td>
+      <td>{{ inv.is_consumed }}</td>
       <td>{{ inv.created }}</td>
-      <td>{{ inv.accepted }}</td>
+      <td>{{ inv.consumed }}</td>
     </tr>
     {% endfor %}
   </tbody>
index fe77b83..503711c 100644 (file)
@@ -6,10 +6,11 @@
 
 {% block body %}
 <form action="{% url pithos.im.views.local_create %}" method="post">
+{% if provider == 'local'%}
   <div class="clearfix">
     <label for="user-uniq">Username</label>
     <div class="input">
-      <input class="span4" id="user-uniq" name="uniq" type="text" />
+      <input class="span4" id="user-uniq" name="uniq" {%if inv %} value={{ inv.uniq }} {% endif %} type="text" />
     </div>
   </div>
   
   </div>
   
   <div class="clearfix">
+    <label for="user-password">Confirm Password</label>
+    <div class="input">
+      <input class="span4" id="user-retype-password" name="retype_password" type="password" />
+    </div>
+  </div>
+
+  <div class="clearfix">
     <label for="user-realname">Real Name</label>
     <div class="input">
-      <input class="span4" id="user-realname" name="realname" type="text" />
+      <input class="span4" id="user-realname" name="realname" {%if inv %} value={{ inv.realname }} {% endif %} type="text" />
     </div>
   </div>
   
       <input class="span4" id="user-email" name="email" type="text" />
     </div>
   </div>
-  
+{% endif %}
+
+{% if provider == 'twitter' %}
+    <div class="clearfix">
+        <label for="user-uniq">Twitter </label>
+        <div class="input">
+            <input class="span4" id="user-uniq" name="uniq" {%if inv %} value={{ inv.uniq }} {% endif %} type="text" />
+        </div>
+    </div>
+{% endif %}
+
   <div class="actions">
     <button type="submit" class="btn primary">Create</button>
     <button type="reset" class="btn">Reset</button>
index 3dc41e6..05f32bd 100644 (file)
@@ -32,8 +32,7 @@
 # or implied, of GRNET S.A.
 
 from django.conf import settings
-from django.conf.urls.defaults import patterns
-
+from django.conf.urls.defaults import patterns, include
 
 urlpatterns = patterns('pithos.im.views',
     (r'^$', 'index'),
@@ -47,12 +46,23 @@ urlpatterns = patterns('pithos.im.views',
     (r'^admin/users/(\d+)/modify/?$', 'users_modify'),
     (r'^admin/users/(\d+)/delete/?$', 'users_delete'),
     (r'^admin/users/export/?$', 'users_export'),
+    (r'^admin/users/pending/?$', 'pending_users'),
+    (r'^admin/users/activate/(\d+)/?$', 'users_activate'),
     
     (r'^admin/invitations/?$', 'invitations_list'),
     (r'^admin/invitations/export/?$', 'invitations_export'),
     
     (r'^profile/?$', 'users_profile'),
     (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')),
 )
 
 urlpatterns += patterns('pithos.im.target',
@@ -64,31 +74,32 @@ urlpatterns += patterns('',
                                 {'document_root': settings.PROJECT_PATH + '/im/static'})
 )
 
-if 'local' in settings.IM_STANDARD_MODULES:
+
+if 'local' in settings.IM_MODULES:
     urlpatterns += patterns('pithos.im.views',
-        (r'^local/create/?$', 'local_create'),
+#        (r'^local/create/?$', 'local_create'),
         (r'^local/reclaim/?$', 'reclaim_password')
     )
     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'),
-    )
-    urlpatterns += patterns('pithos.im.target',
-        (r'^login/invitation/?$', 'invitation.login')
-    )
+#if 'invitation' in settings.IM_STANDARD_MODULES:
+#    urlpatterns += patterns('pithos.im.views',
+#        (r'^invite/?$', 'invite'),
+#    )
+#    urlpatterns += patterns('pithos.im.target',
+#        (r'^login/invitation/?$', 'invitation.login')
+#    )
 
-if 'shibboleth' in settings.IM_OTHER_MODULES:
+if 'shibboleth' in settings.IM_MODULES:
     urlpatterns += patterns('pithos.im.target',
         (r'^login/shibboleth/?$', 'shibboleth.login')
     )
 
-if 'twitter' in settings.IM_OTHER_MODULES:
+if 'twitter' in settings.IM_MODULES:
     urlpatterns += patterns('pithos.im.target',
         (r'^login/twitter/?$', 'twitter.login'),
         (r'^login/twitter/authenticated/?$', 'twitter.authenticated')
index 36d5aae..e269e12 100644 (file)
@@ -44,12 +44,15 @@ from smtplib import SMTPException
 
 from django.conf import settings
 from django.core.mail import send_mail
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
 from django.shortcuts import redirect
 from django.template.loader import render_to_string
 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_authopenid.forms import *
 
 from urllib import quote
 
@@ -91,8 +94,8 @@ def requires_admin(func):
 
 
 def index(request):
-    kwargs = {'standard_modules':settings.IM_STANDARD_MODULES,
-              'other_modules':settings.IM_OTHER_MODULES}
+    kwargs = {'im_modules':settings.IM_MODULES,
+              'other_modules':settings.IM_MODULES[1:]}
     return render_response('index.html',
                            next=request.GET.get('next', ''),
                            **kwargs)
@@ -102,10 +105,11 @@ def index(request):
 def admin(request):
     stats = {}
     stats['users'] = User.objects.count()
+    stats['pending'] = User.objects.filter(state = 'PENDING').count()
     
     invitations = Invitation.objects.all()
     stats['invitations'] = invitations.count()
-    stats['invitations_accepted'] = invitations.filter(is_accepted=True).count()
+    stats['invitations_consumed'] = invitations.filter(is_consumed=True).count()
     
     return render_response('admin.html', tab='home', stats=stats)
 
@@ -168,13 +172,84 @@ def users_modify(request, user_id):
     user.save()
     return redirect(users_info, user.id)
 
-
 @requires_admin
 def users_delete(request, user_id):
     user = User.objects.get(id=user_id)
     user.delete()
     return redirect(users_list)
 
+@requires_admin
+def pending_users(request):
+    users = User.objects.order_by('id')
+    
+    users = users.filter(state = 'PENDING')
+    
+    try:
+        page = int(request.GET.get('page', 1))
+    except ValueError:
+        page = 1
+    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
+    limit = offset + settings.ADMIN_PAGE_LIMIT
+    
+    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
+    prev = page - 1 if page > 1 else None
+    next = page + 1 if page < npages else None
+    return render_response('pending_users.html',
+                            users=users[offset:limit],
+                            filter=filter,
+                            pages=range(1, npages + 1),
+                            page=page,
+                            prev=prev,
+                            next=next)
+
+def send_greeting(baseurl, user):
+    url = baseurl
+    subject = _('Welcome to Pithos')
+    message = render_to_string('welcome.txt', {
+                'user': user,
+                'url': url,
+                'baseurl': baseurl,
+                'service': settings.SERVICE_NAME,
+                'support': settings.DEFAULT_CONTACT_EMAIL})
+    sender = settings.DEFAULT_FROM_EMAIL
+    send_mail(subject, message, sender, [user.email])
+    logging.info('Sent greeting %s', user)
+
+@requires_admin
+def users_activate(request, user_id):
+    user = User.objects.get(id=user_id)
+    user.state = 'ACTIVE'
+    status = 'success'
+    try:
+        send_greeting(request.build_absolute_uri('/').rstrip('/'), user)
+        message = _('Greeting 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
+    
+    users = User.objects.order_by('id')
+    users = users.filter(state = 'PENDING')
+    
+    try:
+        page = int(request.POST.get('page', 1))
+    except ValueError:
+        page = 1
+    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
+    limit = offset + settings.ADMIN_PAGE_LIMIT
+    
+    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
+    prev = page - 1 if page > 1 else None
+    next = page + 1 if page < npages else None
+    return render_response('pending_users.html',
+                            users=users[offset:limit],
+                            filter=filter,
+                            pages=range(1, npages + 1),
+                            page=page,
+                            prev=prev,
+                            next=next,
+                            message=message)
 
 def generate_invitation_code():
     while True:
@@ -187,7 +262,7 @@ def generate_invitation_code():
 
 
 def send_invitation(baseurl, inv):
-    url = settings.INVITATION_LOGIN_TARGET % (baseurl, inv.code, quote(baseurl))
+    url = settings.SIGNUP_TARGET % (baseurl, inv.code, quote(baseurl))
     subject = _('Invitation to Pithos')
     message = render_to_string('invitation.txt', {
                 'invitation': inv,
@@ -261,12 +336,24 @@ def send_verification(baseurl, user):
 
 def local_create(request):
     if request.method == 'GET':
-        return render_response('local_create.html')
+        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:
@@ -275,12 +362,17 @@ def local_create(request):
         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':
-            username = '%s@local' % username
             try:
                 user = User.objects.get(uniq=username)
                 status = 'error'
@@ -293,7 +385,9 @@ def local_create(request):
                 user.password = request.POST.get('password')
                 user.is_admin = False
                 user.quota = 0
-                user.state = 'UNVERIFIED'
+                user.state = 'ACTIVE' if is_preaccepted(user) else 'PENDING'
+                if user.invitation:
+                    user.invitation.is_consumed = True
                 user.level = 1
                 user.renew_token()
                 try:
@@ -301,6 +395,7 @@ def local_create(request):
                     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
@@ -443,7 +538,7 @@ def users_export(request):
 @requires_admin
 def users_create(request):
     if request.method == 'GET':
-        return render_response('users_create.html')
+        return render_response('users_local_create.html')
     if request.method == 'POST':
         user = User()
         user.uniq = request.POST.get('uniq')
@@ -452,6 +547,7 @@ def users_create(request):
         user.affiliation = request.POST.get('affiliation')
         user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
         user.renew_token()
+        user.provider = 'local'
         user.save()
         return redirect(users_info, user.id)
 
@@ -483,4 +579,44 @@ def users_edit(request):
             'status': status,
             'message': message})
     return HttpResponse(html)
-    
+
+def is_preaccepted(user):
+    return True if settings.INVITATIONS_ENABLED and user.invitation else False
+
+def signup(request):
+    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)    
+    elif request.method == 'POST':
+        choice = request.POST.get('choice')
+        if not choice:
+            return HttpResponseBadRequest('No provider selected')
+        
+        provider = choice
+        
+        code = request.POST.get('code')
+        
+        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')
+            return redirect(url)
+
+def openid_create(request):
+    form1 = OpenidSigninForm()
+    kwargs = {'form1':form1}  
+    return render_response('openid_create.html') 
\ No newline at end of file
index 2854bcd..98b18e1 100644 (file)
@@ -26,8 +26,8 @@ SERVICE_NAME = 'Pithos'
 DEFAULT_FROM_EMAIL = 'Pithos <no-reply@grnet.gr>'
 DEFAULT_CONTACT_EMAIL = 'support@pithos.grnet.gr'
 
-# Where users should login with their invitation code
-INVITATION_LOGIN_TARGET = '%s/im/login/invitation?code=%d&next=%s'
+# Where users should signup with their invitation code
+SIGNUP_TARGET = '%s/im/signup/?code=%d&next=%s'
 
 # Where users should activate their local account
 ACTIVATION_LOGIN_TARGET = '%s/im/local/activate/?auth=%s&next=%s'
@@ -36,8 +36,10 @@ ACTIVATION_LOGIN_TARGET = '%s/im/local/activate/?auth=%s&next=%s'
 PASSWORD_RESET_TARGET = '%s/im/local/reset/?username=%s&next=%s'
 
 # Identity Management enabled modules
-IM_STANDARD_MODULES = ['local', 'invitation']
-IM_OTHER_MODULES = ['twitter', 'shibboleth']
+IM_MODULES = ['local', 'twitter', 'shibboleth']
 
 # Force user profile verification
 FORCE_PROFILE_UPDATE = False
+
+#Enable invitations
+INVITATIONS_ENABLED = True