From 290f9c5c2a175bf5dd3428ea1d6bf34a8773cbdd Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 11:51:51 +0100 Subject: [PATCH 1/7] Added travis configuration --- .travis.yml | 17 +++++++++++++++++ README.md | 2 ++ 2 files changed, 19 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2cd4578 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python + +python: + - "2.7" + +env: + - DJANGO="django==1.5.1 --use-mirrors" + - DJANGO="django==1.4.5 --use-mirrors" + - DJANGO="django==1.3.7 --use-mirrors" + +install: + - pip install $DJANGO + - pip install milkman + - export PYTHONPATH=. + +script: + - python manage.py test diff --git a/README.md b/README.md index 23c2495..34cc4c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Django User Roles ================= +[![build-status-image]][travis] + Simple role-based user permissions for Django. django-user-roles is a simple, reusable app that allows you to create a set of user roles, which can be used to control which views each type of user has permission to view, and to customize how the site is presented to different types of user. From ce0e821a291a6785f1ab14daf573c7e15521b527 Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 13:24:30 +0100 Subject: [PATCH 2/7] Fixed issue where tests would not run in never versions of Django --- .travis.yml | 2 +- userroles/utils.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2cd4578..e00e246 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ install: - export PYTHONPATH=. script: - - python manage.py test + - python manage.py test userroles diff --git a/userroles/utils.py b/userroles/utils.py index 9961077..b730312 100644 --- a/userroles/utils.py +++ b/userroles/utils.py @@ -5,6 +5,7 @@ from django.db.models import loading from django.test import TestCase from django.core.management.commands import syncdb +from optparse import NO_DEFAULT NO_SETTING = ('!', None) @@ -31,7 +32,15 @@ def set(self, **kwargs): def syncdb(self): loading.cache.loaded = False # Use this, rather than call_command, or 'south' will screw with us. - syncdb.Command().execute(verbosity=0) + command = syncdb.Command() + defaults = {} + for opt in command.option_list: + if opt.default is NO_DEFAULT: + defaults[opt.dest] = None + else: + defaults[opt.dest] = opt.default + defaults['verbosity'] = 0 + command.execute(*[], **defaults) def revert(self): for k, v in self._original_settings.iteritems(): From 2d9f831e086837033bca1676f7f1e745495d1159 Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 13:39:40 +0100 Subject: [PATCH 3/7] Fixed unit test that was failing in 1.5.1 where setting a user role without a profile object wouldn't stick --- userroles/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/userroles/models.py b/userroles/models.py index f0f6390..7f2b325 100644 --- a/userroles/models.py +++ b/userroles/models.py @@ -50,3 +50,4 @@ def set_user_role(user, role, profile=None): profile.name = role.name profile.save() + user.role = profile From 643d27d58337e4eec3b791b0db1e43d312123081 Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 15:13:59 +0100 Subject: [PATCH 4/7] Should now support custom models safely without breaking older versions --- testproject/settings.py | 3 +++ userroles/models.py | 10 ++++++++-- userroles/testapp/models.py | 25 +++++++++++++++++++++++++ userroles/tests.py | 17 +++++++++++++---- userroles/utils.py | 1 + 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/testproject/settings.py b/testproject/settings.py index ab820ca..5b245e6 100644 --- a/testproject/settings.py +++ b/testproject/settings.py @@ -121,5 +121,8 @@ 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', + 'userroles.testapp', 'userroles', ) + +AUTH_USER_MODEL = 'testapp.TestUser' diff --git a/userroles/models.py b/userroles/models.py index 7f2b325..36b7495 100644 --- a/userroles/models.py +++ b/userroles/models.py @@ -1,10 +1,16 @@ -from django.contrib.auth.models import User +import django.contrib.auth from django.db import models from userroles import roles +from django.conf import settings + +if hasattr(django.contrib.auth, 'get_user_model'): + user_model = settings.AUTH_USER_MODEL +else: + user_model = 'auth.User' class UserRole(models.Model): - user = models.OneToOneField(User, related_name='role') + user = models.OneToOneField(user_model, related_name='role') name = models.CharField(max_length=100, choices=roles.choices) child = models.CharField(max_length=100, blank=True) _valid_roles = roles diff --git a/userroles/testapp/models.py b/userroles/testapp/models.py index aba3dd6..a3c17f9 100644 --- a/userroles/testapp/models.py +++ b/userroles/testapp/models.py @@ -1,6 +1,31 @@ from django.db import models from userroles.models import UserRole +from django.contrib.auth.models import AbstractBaseUser, UserManager class TestModeratorProfile(UserRole): stars = models.IntegerField() + + +class TestUser(AbstractBaseUser): + username = models.CharField(max_length=255, unique=True, db_index=True) + email = models.EmailField(max_length=255, unique=True) + first_name = models.CharField(max_length=255) + surname = models.CharField(max_length=255) + is_active = models.BooleanField(default=True) + + USERNAME_FIELD = 'username' + REQUIRED_FIELDS = ['email', 'first_name', 'surname'] + + objects = UserManager() + + def get_full_name(self): + #This is a required method + return self.first_name + ' ' + self.surname + + def get_short_name(self): + #This is a required method + return self.email + + def __unicode__(self): + return self.email diff --git a/userroles/tests.py b/userroles/tests.py index becdb86..b10df29 100644 --- a/userroles/tests.py +++ b/userroles/tests.py @@ -3,9 +3,10 @@ from django.conf import settings from django.contrib.auth.models import User +import django.contrib.auth from milkman.dairy import milkman from userroles.models import set_user_role, UserRole -from userroles.testapp.models import TestModeratorProfile +from userroles.testapp.models import TestModeratorProfile, TestUser from userroles.utils import SettingsTestCase from userroles import Roles @@ -22,6 +23,13 @@ roles = Roles(roles_config) +# Handle older versions of Django +if hasattr(django.contrib.auth, 'get_user_model'): + get_user_model = django.contrib.auth.get_user_model +else: + def get_user_model(): + return User + class TestCase(SettingsTestCase): def setUp(self): @@ -29,7 +37,8 @@ def setUp(self): self.settings( INSTALLED_APPS=installed_apps_config, ROOT_URLCONF='userroles.testapp.urls', - USER_ROLES=roles_config + USER_ROLES=roles_config, + AUTH_USER_MODEL='testapp.TestUser' ) self.restore_roles = UserRole._valid_roles UserRole._valid_roles = roles @@ -69,7 +78,7 @@ class UserRoleTests(TestCase): def setUp(self): super(UserRoleTests, self).setUp() - self.user = milkman.deliver(User) + self.user = milkman.deliver(get_user_model()) set_user_role(self.user, roles.manager) def test_role_comparison(self): @@ -144,7 +153,7 @@ def test_set_role_with_profile(self): class ViewTests(TestCase): def setUp(self): super(ViewTests, self).setUp() - self.user = milkman.deliver(User) + self.user = milkman.deliver(get_user_model()) self.user.set_password('password') self.user.save() self.client.login(username=self.user.username, password='password') diff --git a/userroles/utils.py b/userroles/utils.py index b730312..82152cb 100644 --- a/userroles/utils.py +++ b/userroles/utils.py @@ -40,6 +40,7 @@ def syncdb(self): else: defaults[opt.dest] = opt.default defaults['verbosity'] = 0 + defaults['interactive'] = False command.execute(*[], **defaults) def revert(self): From f31937f377876eb072326f6b1ae1510a046741dc Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 15:22:17 +0100 Subject: [PATCH 5/7] Corrected bad import on old versions of django --- userroles/testapp/models.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/userroles/testapp/models.py b/userroles/testapp/models.py index a3c17f9..daa65e0 100644 --- a/userroles/testapp/models.py +++ b/userroles/testapp/models.py @@ -1,6 +1,14 @@ from django.db import models from userroles.models import UserRole -from django.contrib.auth.models import AbstractBaseUser, UserManager +import django.contrib.auth.models + +if hasattr(django.contrib.auth.models, 'AbstractBaseUser'): + from django.contrib.auth.models import AbstractBaseUser, UserManager +else: + class AbstractBaseUser(object): + pass + class UserManager(object): + pass class TestModeratorProfile(UserRole): From 9e83ae0f2a21d03f5f0b319d0738d90a249843a1 Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 16:40:44 +0100 Subject: [PATCH 6/7] Tidied up the code slightly --- userroles/decorators.py | 1 + userroles/models.py | 3 ++- userroles/testapp/models.py | 2 ++ userroles/tests.py | 5 +++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/userroles/decorators.py b/userroles/decorators.py index 94bec4b..52f53a8 100644 --- a/userroles/decorators.py +++ b/userroles/decorators.py @@ -1,6 +1,7 @@ from django.contrib.auth.decorators import user_passes_test from userroles.models import UserRole + def role_required(*roles): """ Decorator for views that checks whether a user has a particular role, diff --git a/userroles/models.py b/userroles/models.py index 36b7495..139250f 100644 --- a/userroles/models.py +++ b/userroles/models.py @@ -3,6 +3,7 @@ from userroles import roles from django.conf import settings + if hasattr(django.contrib.auth, 'get_user_model'): user_model = settings.AUTH_USER_MODEL else: @@ -31,7 +32,7 @@ def __getattr__(self, name): return self == role raise AttributeError("'%s' object has no attribute '%s'" % - (self.__class__.__name__, name)) + (self.__class__.__name__, name)) def __unicode__(self): return self.name diff --git a/userroles/testapp/models.py b/userroles/testapp/models.py index daa65e0..292f0f7 100644 --- a/userroles/testapp/models.py +++ b/userroles/testapp/models.py @@ -2,11 +2,13 @@ from userroles.models import UserRole import django.contrib.auth.models + if hasattr(django.contrib.auth.models, 'AbstractBaseUser'): from django.contrib.auth.models import AbstractBaseUser, UserManager else: class AbstractBaseUser(object): pass + class UserManager(object): pass diff --git a/userroles/tests.py b/userroles/tests.py index b10df29..8c3a47c 100644 --- a/userroles/tests.py +++ b/userroles/tests.py @@ -6,7 +6,7 @@ import django.contrib.auth from milkman.dairy import milkman from userroles.models import set_user_role, UserRole -from userroles.testapp.models import TestModeratorProfile, TestUser +from userroles.testapp.models import TestModeratorProfile from userroles.utils import SettingsTestCase from userroles import Roles @@ -122,7 +122,8 @@ def test_set_role_with_profile(self): """ Set a role that takes a profile. """ - set_user_role(self.user, roles.moderator, TestModeratorProfile(stars=5)) + set_user_role(self.user, roles.moderator, + TestModeratorProfile(stars=5)) self.assertTrue(self.user.role.is_moderator) self.assertEquals(self.user.role.profile.stars, 5) From 77cc815377f32e1fdc985ea1a26078a9793d63f6 Mon Sep 17 00:00:00 2001 From: Tony Aldridge Date: Tue, 28 May 2013 16:51:14 +0100 Subject: [PATCH 7/7] Updated version number --- userroles/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userroles/__init__.py b/userroles/__init__.py index dc50f8f..f9d0ac0 100644 --- a/userroles/__init__.py +++ b/userroles/__init__.py @@ -3,7 +3,7 @@ from django.utils import importlib -__version__ = '0.1.0' +__version__ = '0.2.0' _IMPORT_FAILED = "Could not import role profile '%s'"