Commits

Jesper Nøhr committed abe924e

piston: authentication (basic, against django), testcase for creating repos

  • Participants
  • Parent commits 7e872e4

Comments (0)

Files changed (3)

piston/authentication.py

+from django.http import HttpResponse
+from django.contrib.auth.models import User
+
+def django_auth(username, password):
+    try:
+        user = User.objects.get(username=username)
+        if user.check_password(password):
+            return user
+        else:
+            return False
+    except User.DoesNotExist:
+        return False
+
+class HttpBasicAuthentication(object):
+    def __init__(self, auth_func=django_auth, realm='Bitbucket.org API'):
+        self.auth_func = auth_func
+        self.realm = realm
+
+    def is_authenticated(self, request):
+        auth_string = request.META.get('HTTP_AUTHORIZATION', None)
+
+        if not auth_string:
+            return False
+            
+        (authmeth, auth) = auth_string.split(" ", 1)
+        
+        if not authmeth.lower() == 'basic':
+            return False
+            
+        auth = auth.strip().decode('base64')
+        (username, password) = auth.split(':', 1)
+        
+        request.user = self.auth_func(username, password)
+        
+        return not request.user is False
+        
+    def challenge(self):
+        resp = HttpResponse("Authorization Required")
+        resp['WWW-Authenticate'] = 'Basic realm="%s"' % self.realm
+        resp.status_code = 401
+        return resp
+        

piston/handler.py

 class BaseHandler(object):
     __metaclass__ = HandlerType
 
+    def flatten_dict(self, dct):
+        return dict([ (str(k), dct.get(k)) for k in dct.keys() ])
+
     def has_model(self):
         return hasattr(self, 'model')
 
     def read(self, request, *a, **kwa):
         if not self.has_model():
-            return NotImplementedError
+            raise NotImplementedError
 
         return self.model.objects.filter(*a, **kwa)
+        
+    def create(self, request, *a, **kwa):
+        if not self.has_model():
+            raise NotImplementedError
+    
+        attrs = self.flatten_dict(request.POST)
+
+        try:
+            inst = self.model.objects.get(**attrs)
+            raise ValueError("Already exists.")
+        except self.model.DoesNotExist:
+            inst = self.model(attrs)
+            inst.save()
+
+            return inst        
+                        
+    def update(self, request, *a, **kwa):
+        if not self.has_model():
+            raise NotImplementedError
+            
+        inst = self.model.objects.get(*a, **kwa)
+        print "must update instance", inst, "with", request.POST

piston/resource.py

 from emitters import Emitter
 from handler import typemapper
 
+class NoAuthentication(object):
+    def is_authenticated(self, request):
+        return True
+
 class Resource(object):
     callmap = { 'GET': 'read', 'POST': 'create', 
                 'PUT': 'update', 'DELETE': 'delete' }
             raise AttributeError, "Handler not callable."
 
         self.handler = handler()
-        self.authentication = authentication
+
+        if not authentication:
+            self.authentication = NoAuthentication()
+        else:
+            self.authentication = authentication
         
     def __call__(self, request, *args, **kwargs):
+
+        if not self.authentication.is_authenticated(request):
+            return self.authentication.challenge()
+
         rm = request.method.upper()        
         meth = getattr(self.handler, Resource.callmap.get(rm), None)
         format = request.GET.get('format', 'json')