commit 4f8e7c6dbf3f01962a9fe6df377c9ec1ca36d52c
Author: Georgios Gousios <gousiosg@gmail.com>
Date:   Tue Aug 23 14:36:16 2011 +0300

    API method and test to resend invitations

diff --git a/aai/middleware.py b/aai/middleware.py
index 4d5d160..1eff28d 100644
--- a/aai/middleware.py
+++ b/aai/middleware.py
@@ -34,7 +34,7 @@ from synnefo.db.models import SynnefoUser
 from synnefo.aai.shibboleth import Tokens, register_shibboleth_user
 import time
 
-DONT_CHECK = getattr(settings, "AAI_SKIP_AUTH_URLS", ['/api', '/invitations/login'])
+DONT_CHECK = getattr(settings, "AAI_SKIP_AUTH_URLS", ['/api', '/invitations/'])
 
 class SynnefoAuthMiddleware(object):
 
diff --git a/invitations/invitations.py b/invitations/invitations.py
index 4104c90..2c8c0e7 100644
--- a/invitations/invitations.py
+++ b/invitations/invitations.py
@@ -33,11 +33,12 @@ from datetime import timedelta
 import datetime
 import base64
 import urllib
+import re
 
 from django.conf import settings
 from django.core.exceptions import ValidationError
 from django.db import transaction
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest, HttpResponseServerError
 from django.template.context import RequestContext
 from django.template.loader import render_to_string
 from django.core.validators import validate_email
@@ -128,6 +129,7 @@ def invitations_for_user(request):
         invitation['target'] = inv.target.uniq
         invitation['accepted'] = inv.accepted
         invitation['sent'] = inv.created
+        invitation['id'] = inv.id
 
         invitations.append(invitation)
 
@@ -267,6 +269,38 @@ def enconde_inv_url(invitation):
 
     return url
 
+
+def resend(request):
+    """
+    Resend an invitation that has been already sent
+    """
+
+    if not request.method == 'POST':
+        return method_not_allowed(request)
+
+    invid = request.POST["invid"]
+
+    matcher = re.compile('^[0-9]+$')
+
+    # XXX: Assumes numeric DB keys
+    if not matcher.match(invid):
+        return HttpResponseBadRequest("Invalid content for parameter [invid]")
+
+    try:
+        inv = Invitations.objects.get(id = invid)
+    except Exception:
+        return HttpResponseBadRequest("Invitation to resend does not exist")
+
+    if not request.user == inv.source:
+        return HttpResponseBadRequest("Invitation does not belong to user")
+
+    try:
+        send_invitation(inv)
+    except Exception:
+        return HttpResponseServerError("Error sending invitation email")
+
+    return HttpResponse("Invitation has been resent")
+
 def get_invitee_level(source):
     return get_user_inv_level(source) + 1
 
diff --git a/invitations/tests.py b/invitations/tests.py
index a1e6ae3..dc4806c 100644
--- a/invitations/tests.py
+++ b/invitations/tests.py
@@ -89,6 +89,7 @@ class InvitationsTestCase(TestCase):
         self.assertEqual(inv.target.max_invitations,
                          settings.INVITATIONS_PER_LEVEL[1])
 
+
     def test_invitation_login(self):
         """
             Basic login by invitation checks
@@ -167,6 +168,29 @@ class InvitationsTestCase(TestCase):
             self.assertTrue(False)
 
 
+    def test_resend_invitation(self):
+        """
+        Tests the resend invitation method
+        """
+        inv = self._add_invitation()
+
+        resp = self.client.post("/invitations/resend",
+                                {'invid':inv.id},
+                                **{'HTTP_X_AUTH_TOKEN': self.token})
+        self.assertEquals(resp.status_code, 200)
+
+
+        resp = self.client.post("/invitations/resend",
+                                {'invid':'1;delete from db_invitations;'},
+                                **{'HTTP_X_AUTH_TOKEN': self.token})
+        self.assertEquals(resp.status_code, 400)
+
+        resp = self.client.post("/invitations/resend",
+                                {'invid':inv.id},
+                                **{'HTTP_X_AUTH_TOKEN': inv.target.auth_token})
+        self.assertEquals(resp.status_code, 400)
+
+
     def _add_invitation(self):
         source = SynnefoUser.objects.filter(auth_token = self.token)[0]
         invitations.add_invitation(source, "Test", "test@gmail.com")
diff --git a/invitations/urls.py b/invitations/urls.py
index dbdc60e..c768d97 100644
--- a/invitations/urls.py
+++ b/invitations/urls.py
@@ -34,5 +34,6 @@ import os
 urlpatterns = patterns('',
     url(r'^$', 'synnefo.invitations.invitations.inv_demux', name="invitations"),
     (r'^static/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.dirname(__file__), 'static')}),
-    (r'^login/?$', 'synnefo.invitations.invitations.login')
+    (r'^login/?$', 'synnefo.invitations.invitations.login'),
+    (r'^resend/?$', 'synnefo.invitations.invitations.resend'),
 )
