From bf629e5a4d1a51f938c84d35d768830158ad5ebd Mon Sep 17 00:00:00 2001 From: Joseph Kocherhans Date: Wed, 28 Jun 2006 03:57:40 +0000 Subject: [PATCH] generic-auth: Initial implementation and tests for the new has_permission function git-svn-id: http://code.djangoproject.com/svn/django/branches/generic-auth@3222 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/auth/__init__.py | 27 ++++++++++ .../regressiontests/authorization/__init__.py | 0 tests/regressiontests/authorization/models.py | 50 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 tests/regressiontests/authorization/__init__.py create mode 100644 tests/regressiontests/authorization/models.py diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index ac7b40aca6..41adadabcd 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -1,2 +1,29 @@ LOGIN_URL = '/accounts/login/' REDIRECT_FIELD_NAME = 'next' + +class NoMatchFound(Exception): pass + +class HasPermission(object): + """ + Function that supports multiple implementations via a type registry. The + implemetation called depends on the argument types. + """ + def __init__(self): + self.registry = {} + + def __call__(self, user, permission, obj=None): + # TODO: this isn't very robust. Only matches on exact types. Support + # for matching subclasses and caching registry hits would be helpful, + # but we'll add that later + types = (type(user), type(permission), type(obj)) + func = self.registry.get(types) + if func is not None: + return func(user, permission, obj) + else: + raise NoMatchFound, "%s\n%s" % (self.registry, types) + + def register(self, user_type, permission_type, obj_type, func): + types = (user_type, permission_type, obj_type) + self.registry[types] = func + +has_permission = HasPermission() diff --git a/tests/regressiontests/authorization/__init__.py b/tests/regressiontests/authorization/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regressiontests/authorization/models.py b/tests/regressiontests/authorization/models.py new file mode 100644 index 0000000000..8a54b45f99 --- /dev/null +++ b/tests/regressiontests/authorization/models.py @@ -0,0 +1,50 @@ +from django.db import models + +class TestModel(models.Model): + name = models.CharField(maxlength=255) + + class Admin: + pass + +API_TESTS = """ +# Let's create a default implementation of has_permission. For now, It should +# just call user.has_permission(permission) for the given django.contrib.auth.models.User. +# Eventually the user.has_permission implementation should be extracted here. +>>> from django.contrib.auth import has_permission +>>> def user_has_permission(user, permission, object=None): +... return user.has_perm(permission) + +# Then let's register that function to be called when we get an instance of +# django.contrib.auth.models.User and a string as the permission. We use str +# as the permission type for convenience. It would be annoying to grab the +# actual Permission object instead of just using the codename. This feels kind +# of limiting, but can be revisited later. +>>> from django.contrib.auth.models import User +>>> has_permission.register(User, str, TestModel, user_has_permission) + +# Now make sure it works. +>>> admin = User(username='admin', password='test', email='test@example.com', is_superuser=True) +>>> admin.save() +>>> has_permission(admin, 'testmodel.add', TestModel()) +True + +# Now let's create an implemetation for AnonymousUsers... it should always +# return False. +>>> def anon_has_permission(user, permission, object=None): +... return False + +# Register it like before, but for AnonymousUser rather than User. +>>> from django.contrib.auth.models import AnonymousUser +>>> has_permission.register(AnonymousUser, str, TestModel, anon_has_permission) + +# And make sure it works. +>>> anonymous = AnonymousUser() +>>> has_permission(anonymous, 'testmodel.add', TestModel()) +False + +# Let's double check that the function we registered for User still works (we're +# not just replacing the implementation of has_permission) +>>> has_permission(admin, 'testmodel.add', TestModel()) +True + +"""