Ajout du support api-key master
authorCyril Robert <Cyril Robert crobert@inverse.ca>
Thu, 25 Mar 2010 20:33:22 +0000 (16:33 -0400)
committerCyril Robert <Cyril Robert crobert@inverse.ca>
Thu, 25 Mar 2010 20:33:22 +0000 (16:33 -0400)
serveur/authentification/__init__.py [new file with mode: 0644]
serveur/authentification/admin.py [new file with mode: 0644]
serveur/authentification/handlers.py [new file with mode: 0644]
serveur/authentification/models.py [new file with mode: 0644]
serveur/authentification/tests.py [new file with mode: 0644]
serveur/authentification/views.py [new file with mode: 0644]
serveur/handlers.py [deleted file]
serveur/settings.py
serveur/urls.py

diff --git a/serveur/authentification/__init__.py b/serveur/authentification/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/serveur/authentification/admin.py b/serveur/authentification/admin.py
new file mode 100644 (file)
index 0000000..1afd1bc
--- /dev/null
@@ -0,0 +1,9 @@
+# -*- encoding: utf-8 -*-
+
+from django.contrib import admin
+from models import Token
+
+class TokenAdmin (admin.ModelAdmin):
+    readonly_fields = ("key",)
+
+admin.site.register(Token, TokenAdmin)
diff --git a/serveur/authentification/handlers.py b/serveur/authentification/handlers.py
new file mode 100644 (file)
index 0000000..9e62095
--- /dev/null
@@ -0,0 +1,244 @@
+# -*- encoding: utf-8 -*-
+from auf_roa_authentification_backend.models import AufUser
+from django.db import models
+from django.http import Http404,HttpResponseForbidden
+from django.shortcuts import get_object_or_404, _get_queryset
+
+from piston.handler import BaseHandler
+from piston.utils import rc
+
+from models import Token
+
+class ROAHandler(BaseHandler):
+
+    def flatten_dict(self, dct):
+        return dict([ (str(k), dct.get(k)) for k in dct.keys() \
+            if (k, dct.get(k)) != (u'id', u'None')])
+
+    @staticmethod
+    def _get_object(model, *args, **kwargs):
+        return get_object_or_404(model, id=kwargs['id'])
+
+    def has_valid_key(self, request):
+        valid = False
+
+        tk = request.GET.get ("api-key", "").strip ()
+        if len (tk) > 0:
+            try:
+                Token.objects.get (key = tk, active = True)
+                valid = True
+            except:
+                pass
+
+        return valid
+
+    def read(self, request, *args, **kwargs):
+        """
+        Retrieves an object or a list of objects.
+        """
+        r = rc.NOT_IMPLEMENTED
+
+        if self.has_model():
+            if self.has_valid_key (request):
+                # Returns a single object
+                if kwargs.values() != [None]:
+                    r = [self._get_object(self.model, *args, **kwargs)]
+                # Prepare quesryset
+                else:
+                    queryset = _get_queryset(self.model)
+            
+                    # Filtering
+                    filters, excludes = {}, {}
+                    for k, v in request.GET.iteritems():
+                        if k.startswith('filter_'):
+                            filters[k[7:]] = v
+                        if k.startswith('exclude_'):
+                            excludes[k[8:]] = v
+
+                    if len(filters) == 0:
+                        r = HttpResponseForbidden('Listing forbidden.')
+                    else:
+                        # Apply filters
+                        queryset = queryset.filter(*filters.items())\
+                                .exclude(*excludes.items())
+                
+                        # Ordering (test custom parameters' name)
+                        if 'order' in request.GET:
+                            order_bys = request.GET['order'].split(',')
+                            queryset = queryset.order_by(*order_bys)
+            
+                        # Slicing
+                        limit_start = int(request.GET.get('limit_start', 0))
+                        limit_stop = request.GET.get('limit_stop', False) \
+                                and int(request.GET['limit_stop']) or None
+                        queryset = queryset[limit_start:limit_stop]
+                
+                        obj_list = list(queryset)
+                        if not obj_list:
+                            r = None
+                            raise Http404('No %s matches the given query.' \
+                                    % queryset.model._meta.object_name)
+                        r = queryset
+            else:
+                r = HttpResponseForbidden('API Key invalid.')
+
+        return r
+        
+    def create(self, request, *args, **kwargs):
+        """
+        Creates an object given request args, returned as a list.
+        """
+        # Désactivé
+        return rc.NOT_IMPLEMENTED
+
+        if not self.has_model():
+            return rc.NOT_IMPLEMENTED
+        
+        data = request.POST.copy()
+        keys = data.keys()
+        
+        values = {}
+        for field in self.model._meta.local_fields:
+            field_value = data.get(field.name, None)
+            
+            if field_value not in (u'', u'None'):
+                
+                # Handle FK fields
+                if field.rel and isinstance(field.rel, models.ManyToOneRel):
+                    field_value = data.get(field.attname, None)
+                    if field_value not in (u'', u'None'):
+                        values[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
+                    else:
+                        values[field.attname] = None
+                
+                # Handle all other fields
+                else:
+                    if isinstance(field, models.fields.BooleanField):
+                        field_value = field.to_python(field_value)
+                    elif isinstance(field, models.fields.FloatField):
+                        if field_value is not None:
+                            field_value = float(field_value)
+                    values[field.name] = field_value
+
+        object = self.model.objects.create(**values)
+        
+        response = [self.model.objects.get(id=object.id)]
+        #response = [object]
+        return response
+
+    def update(self, request, *args, **kwargs):
+        """
+        Modifies an object given request args, returned as a list.
+        """
+        # Désactivé
+        return rc.NOT_IMPLEMENTED
+
+        if not self.has_model():
+            return rc.NOT_IMPLEMENTED
+        
+        data = request.PUT.copy()
+        object = self._get_object(self.model, *args, **kwargs)
+        
+        for field in self.model._meta.local_fields:
+            field_name = field.name
+            
+            # Handle FK fields
+            if field.rel and isinstance(field.rel, models.ManyToOneRel):
+                field_value = data.get(field.attname, None)
+                if field_value not in (u'', u'None', None):
+                    field_value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
+                else:
+                    field_value = None
+                setattr(object, field.attname, field_value)
+            
+            # Handle all other fields
+            elif field_name in data:
+                field_value = data[field_name]
+                if field_value in (u'', u'None'):
+                    field_value = None
+                if isinstance(field, models.fields.BooleanField) \
+                or isinstance(field, models.fields.NullBooleanField) \
+                or isinstance(field, models.fields.IntegerField):
+                    field_value = field.to_python(field_value)
+                elif isinstance(field, models.fields.FloatField):
+                    if field_value is not None:
+                        field_value = float(field_value)
+                elif isinstance(field, models.fields.CharField):
+                    if field_value is None:
+                        field_value = u''
+                setattr(object, field_name, field_value)
+        
+        object.save()
+        
+        response = [self.model.objects.get(id=object.id)]
+        #response = [object]
+        return response
+
+    def delete(self, request, *args, **kwargs):
+        """
+        Deletes an object.
+        """
+        # Désactivé
+        return rc.NOT_IMPLEMENTED
+
+        if not self.has_model():
+            raise NotImplementedError
+        
+        try:
+            object = self._get_object(self.model, *args, **kwargs)
+            object.delete()
+
+            return rc.DELETED
+        except self.model.MultipleObjectsReturned:
+            return rc.DUPLICATE_ENTRY
+        except self.model.DoesNotExist:
+            return rc.NOT_HERE
+
+
+class ROACountHandler(BaseHandler):
+    allowed_methods = ('GET', )
+
+    def read(self, request, *args, **kwargs):
+        """
+        Retrieves the number of objects.
+        """
+        if not self.has_model():
+            return rc.NOT_IMPLEMENTED
+        
+        # Initialization
+        queryset = _get_queryset(self.model)
+        
+        # Filtering
+        filters, excludes = {}, {}
+        for k, v in request.GET.iteritems():
+            if k.startswith('filter_'):
+                filters[k[7:]] = v
+            if k.startswith('exclude_'):
+                excludes[k[8:]] = v
+        queryset = queryset.filter(*filters.items()).exclude(*excludes.items())
+        
+        # Ordering
+        if 'order_by' in request.GET:
+            order_bys = request.GET['order_by'].split(',')
+            queryset = queryset.order_by(*order_bys)
+        
+        # Counting
+        counter = queryset.count()
+        return counter
+
+
+class ROAWithSlugHandler(ROAHandler):
+    
+    @staticmethod
+    def _get_object(model, *args, **kwargs):
+        """Returns an object from a slug.
+        
+        Useful when the slug is a combination of many fields.
+        """
+        id, slug = kwargs['object_slug'].split('-', 1)
+        object = get_object_or_404(model, id=id, slug=slug)
+        return object
+
+class UserHandler(ROAHandler):
+    model = AufUser
+    list_fields = ['email', 'first_name', 'last_name']
diff --git a/serveur/authentification/models.py b/serveur/authentification/models.py
new file mode 100644 (file)
index 0000000..1a8ea38
--- /dev/null
@@ -0,0 +1,24 @@
+# -*- encoding: utf-8 -*-
+from django.db import models
+import random
+
+class Token (models.Model):
+    key = models.CharField (max_length = 128, unique = True, 
+            default = lambda: Token.gen())
+    app = models.CharField (max_length = 128)
+    active = models.BooleanField (default = True)
+
+    @staticmethod
+    def gen ():
+        token = "%032x" % random.getrandbits (128)
+
+        while True:
+            try:
+                Token.objects.get (key = token)
+                token = "%032x" % random.getrandbits (128)
+            except: break
+
+        return token
+
+    def __unicode__ (self):
+        return "<Token: %s, %s>" % (self.key, self.app)
diff --git a/serveur/authentification/tests.py b/serveur/authentification/tests.py
new file mode 100644 (file)
index 0000000..2247054
--- /dev/null
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/serveur/authentification/views.py b/serveur/authentification/views.py
new file mode 100644 (file)
index 0000000..60f00ef
--- /dev/null
@@ -0,0 +1 @@
+# Create your views here.
diff --git a/serveur/handlers.py b/serveur/handlers.py
deleted file mode 100644 (file)
index 3332cf0..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-from auf_roa_authentification_backend.models import AufUser
-from django.db import models
-from django.http import Http404,HttpResponseForbidden
-from django.shortcuts import get_object_or_404, _get_queryset
-
-from piston.handler import BaseHandler
-from piston.utils import rc
-
-class ROAHandler(BaseHandler):
-
-    def flatten_dict(self, dct):
-        return dict([ (str(k), dct.get(k)) for k in dct.keys() \
-            if (k, dct.get(k)) != (u'id', u'None')])
-
-    @staticmethod
-    def _get_object(model, *args, **kwargs):
-        return get_object_or_404(model, id=kwargs['id'])
-        
-    def read(self, request, *args, **kwargs):
-        """
-        Retrieves an object or a list of objects.
-        """
-        if not self.has_model():
-            return rc.NOT_IMPLEMENTED
-        
-        if kwargs.values() != [None]:
-            # Returns a single object
-            return [self._get_object(self.model, *args, **kwargs)]
-        
-        # Initialization
-        queryset = _get_queryset(self.model)
-        
-        # Filtering
-        filters, excludes = {}, {}
-        for k, v in request.GET.iteritems():
-            if k.startswith('filter_'):
-                filters[k[7:]] = v
-            if k.startswith('exclude_'):
-                excludes[k[8:]] = v
-
-        if len(filters) == 0:
-            return HttpResponseForbidden('Listing forbidden.')
-
-        queryset = queryset.filter(*filters.items()).exclude(*excludes.items())
-        
-        # Ordering (test custom parameters' name)
-        if 'order' in request.GET:
-            order_bys = request.GET['order'].split(',')
-            queryset = queryset.order_by(*order_bys)
-        
-        # Slicing
-        limit_start = int(request.GET.get('limit_start', 0))
-        limit_stop = request.GET.get('limit_stop', False) and int(request.GET['limit_stop']) or None
-        queryset = queryset[limit_start:limit_stop]
-        
-        obj_list = list(queryset)
-        if not obj_list:
-            raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
-        return queryset
-        
-    def create(self, request, *args, **kwargs):
-        """
-        Creates an object given request args, returned as a list.
-        """
-        # Désactivé
-        return rc.NOT_IMPLEMENTED
-
-        if not self.has_model():
-            return rc.NOT_IMPLEMENTED
-        
-        data = request.POST.copy()
-        keys = data.keys()
-        
-        values = {}
-        for field in self.model._meta.local_fields:
-            field_value = data.get(field.name, None)
-            
-            if field_value not in (u'', u'None'):
-                
-                # Handle FK fields
-                if field.rel and isinstance(field.rel, models.ManyToOneRel):
-                    field_value = data.get(field.attname, None)
-                    if field_value not in (u'', u'None'):
-                        values[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
-                    else:
-                        values[field.attname] = None
-                
-                # Handle all other fields
-                else:
-                    if isinstance(field, models.fields.BooleanField):
-                        field_value = field.to_python(field_value)
-                    elif isinstance(field, models.fields.FloatField):
-                        if field_value is not None:
-                            field_value = float(field_value)
-                    values[field.name] = field_value
-
-        object = self.model.objects.create(**values)
-        
-        response = [self.model.objects.get(id=object.id)]
-        #response = [object]
-        return response
-
-    def update(self, request, *args, **kwargs):
-        """
-        Modifies an object given request args, returned as a list.
-        """
-        # Désactivé
-        return rc.NOT_IMPLEMENTED
-
-        if not self.has_model():
-            return rc.NOT_IMPLEMENTED
-        
-        data = request.PUT.copy()
-        object = self._get_object(self.model, *args, **kwargs)
-        
-        for field in self.model._meta.local_fields:
-            field_name = field.name
-            
-            # Handle FK fields
-            if field.rel and isinstance(field.rel, models.ManyToOneRel):
-                field_value = data.get(field.attname, None)
-                if field_value not in (u'', u'None', None):
-                    field_value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
-                else:
-                    field_value = None
-                setattr(object, field.attname, field_value)
-            
-            # Handle all other fields
-            elif field_name in data:
-                field_value = data[field_name]
-                if field_value in (u'', u'None'):
-                    field_value = None
-                if isinstance(field, models.fields.BooleanField) \
-                or isinstance(field, models.fields.NullBooleanField) \
-                or isinstance(field, models.fields.IntegerField):
-                    field_value = field.to_python(field_value)
-                elif isinstance(field, models.fields.FloatField):
-                    if field_value is not None:
-                        field_value = float(field_value)
-                elif isinstance(field, models.fields.CharField):
-                    if field_value is None:
-                        field_value = u''
-                setattr(object, field_name, field_value)
-        
-        object.save()
-        
-        response = [self.model.objects.get(id=object.id)]
-        #response = [object]
-        return response
-
-    def delete(self, request, *args, **kwargs):
-        """
-        Deletes an object.
-        """
-        # Désactivé
-        return rc.NOT_IMPLEMENTED
-
-        if not self.has_model():
-            raise NotImplementedError
-        
-        try:
-            object = self._get_object(self.model, *args, **kwargs)
-            object.delete()
-
-            return rc.DELETED
-        except self.model.MultipleObjectsReturned:
-            return rc.DUPLICATE_ENTRY
-        except self.model.DoesNotExist:
-            return rc.NOT_HERE
-
-
-class ROACountHandler(BaseHandler):
-    allowed_methods = ('GET', )
-
-    def read(self, request, *args, **kwargs):
-        """
-        Retrieves the number of objects.
-        """
-        if not self.has_model():
-            return rc.NOT_IMPLEMENTED
-        
-        # Initialization
-        queryset = _get_queryset(self.model)
-        
-        # Filtering
-        filters, excludes = {}, {}
-        for k, v in request.GET.iteritems():
-            if k.startswith('filter_'):
-                filters[k[7:]] = v
-            if k.startswith('exclude_'):
-                excludes[k[8:]] = v
-        queryset = queryset.filter(*filters.items()).exclude(*excludes.items())
-        
-        # Ordering
-        if 'order_by' in request.GET:
-            order_bys = request.GET['order_by'].split(',')
-            queryset = queryset.order_by(*order_bys)
-        
-        # Counting
-        counter = queryset.count()
-        return counter
-
-
-class ROAWithSlugHandler(ROAHandler):
-    
-    @staticmethod
-    def _get_object(model, *args, **kwargs):
-        """Returns an object from a slug.
-        
-        Useful when the slug is a combination of many fields.
-        """
-        id, slug = kwargs['object_slug'].split('-', 1)
-        object = get_object_or_404(model, id=id, slug=slug)
-        return object
-
-class UserHandler(ROAHandler):
-    model = AufUser
-    list_fields = ['email', 'first_name', 'last_name']
index a3f13bd..4320a6b 100644 (file)
@@ -64,11 +64,11 @@ TEMPLATE_DIRS = (
 )
 
 INSTALLED_APPS = (
-#    'django.contrib.auth',
+    'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.sites',
     'django.contrib.admin',
     'django_roa',
-    'serveur'
+    'serveur.authentification'
 )
index d3018b8..5ff34f3 100644 (file)
@@ -1,5 +1,5 @@
 from django.conf.urls.defaults import *
-from handlers import UserHandler#, MessageHandler, PermissionHandler, GroupHandler
+from authentification.handlers import UserHandler
 from piston.resource import Resource
 
 # Uncomment the next two lines to enable the admin:
@@ -20,7 +20,7 @@ urlpatterns = patterns('',
     # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
 
     # Uncomment the next line to enable the admin:
-    # (r'^admin/', include(admin.site.urls)),
+    (r'^admin/', include(admin.site.urls)),
 
     # Auth application
     url(r'^auth/user/?(?P<id>\d+)?/?$', users),