Skip to content

Commit

Permalink
Merge branch 'master' of github.com:benzkji/django-separate-users
Browse files Browse the repository at this point in the history
  • Loading branch information
benzkji committed Nov 6, 2017
2 parents 7cb17d9 + 893294e commit 5977355
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 43 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# django-separate-users
separate staff and non staff users with two proxy models (FrontendUser and Editor).

Separate staff and non staff users with two proxy models (FrontendUser and Editor).
Nothing fancy, but as I ended up doing this again and again, this is a simple plug and forget
solution, that I'll probably use in many projects from now on.

- minimal requirement are the `is_staff` and `is_superuser` fields on your user model
- staff users can be given the right to edit non staff users (currently not possible, or everyone can make everyone a superuser)
- fieldsets for staff and non staff users can be defined via settings (not yet)
- better admin list views (filters, is_active, etc)

NOTE / WARNING: With django<1.11, it's not possible to run this app with as custom
[//]: # (NOTE / WARNING: With django<1.11, it's not possible to run this app with as custom
`settings.AUTH_USER_MODEL`. See https://stackoverflow.com/questions/46935758/djangos-get-user-model-only-in-1-11-during-import-time
t)

NOTE: Custom user models are not supported (yet).

## Usage

Expand Down
10 changes: 9 additions & 1 deletion separate_users/management/commands/fix_proxy_permissions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import sys

from django.contrib.auth.management import _get_all_permissions
Expand All @@ -10,6 +11,7 @@
# where this comes from: https://gist.github.com/magopian/7543724#gistcomment-2185491
# as django adds permissions for proxy models in another app for the proxies parent
# also, epic: https://code.djangoproject.com/ticket/11154
# also: https://stackoverflow.com/questions/38391729/how-to-retrieve-all-permissions-of-a-specific-model-in-django
class Command(BaseCommand):
help = "Fix permissions for proxy models."

Expand All @@ -21,7 +23,13 @@ def handle(self, *args, **options):
app_label=opts.app_label,
model=opts.object_name.lower())

for codename, name in _get_all_permissions(opts):
argspecs = inspect.getargspec(_get_all_permissions)
if len(argspecs[0]) == 2:
# django < 1.10
all_permissions = _get_all_permissions(opts, ctype)
else:
all_permissions = _get_all_permissions(opts)
for codename, name in all_permissions:
sys.stdout.write(' --{}\n'.format(codename))
p, created = Permission.objects.get_or_create(
codename=codename,
Expand Down
1 change: 1 addition & 0 deletions separate_users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def save(self, *args, **kwargs):
self.is_staff = False
super(FrontendUser, self).save(*args, **kwargs)


class Editor(SeparateUserBase, UserModel):

objects = EditorManager()
Expand Down
25 changes: 12 additions & 13 deletions separate_users/tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,6 @@
'migrations', 'fixtures', 'admin$', 'django_extensions',
]

EXTERNAL_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions',
'django.contrib.staticfiles',
'django.contrib.sitemaps',
'django.contrib.sites',
)

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
Expand All @@ -79,11 +68,21 @@
},
]

EXTERNAL_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions',
'django.contrib.staticfiles',
'django.contrib.sitemaps',
'django.contrib.sites',
]

INTERNAL_APPS = (
INTERNAL_APPS = [
'separate_users',
'separate_users.tests.test_app',
)
]

MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
Expand Down
10 changes: 10 additions & 0 deletions separate_users/tests/settings_custom_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .settings import *
# TODO: it doesnt work!

AUTH_USER_MODEL = 'test_app_custom_user.CustomUser'

del(INSTALLED_APPS[INSTALLED_APPS.index('separate_users.tests.test_app')])

print INSTALLED_APPS

INSTALLED_APPS.insert(0, 'separate_users.tests.test_app_custom_user')
20 changes: 15 additions & 5 deletions separate_users/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
from django.test import override_settings
# from django.test import override_settings
from django.test.testcases import TestCase
from django.urls import reverse
try:
from django.urls import reverse
except ImportError:
from django.core.urlresolvers import reverse

from separate_users.models import Editor, FrontendUser
from separate_users.tests.utils.django_utils import create_superuser
Expand All @@ -13,6 +16,7 @@ class AdminTestCase(TestCase):
TODO: check with custom User Model!
"""
def setUp(self):
self.auth_custom_user = 'test_app_custom_user.CustomUser'
self.superuser = create_superuser()
self.client.login(username='admin', password='secret')
self.frontenduser = FrontendUser.objects.create(username='frontend')
Expand All @@ -33,16 +37,22 @@ def test_editor_changelist(self):
self.changelist('editor')

# @override_settings(
# AUTH_USER_MODEL = 'test_app.CustomUser'
# AUTH_USER_MODEL = 'test_app_custom_user.CustomUser'
# )
# def test_frontend_user_changelist_custom_user(self):
# self.changelist('frontenduser')
#
# @override_settings(
# AUTH_USER_MODEL = 'test_app.CustomUser'
# AUTH_USER_MODEL = 'test_app_custom_user.CustomUser'
# )
# def test_editor_changelist_custom_user(self):
# self.changelist('editor')
# with self.modify_settings(INSTALLED_APPS={
# 'append': 'test_app_custom_user',
# 'remove': [
# 'test_app',
# ],
# }):
# self.changelist('editor')

def change(self, user_version, id):
url = reverse(
Expand Down
Empty file.
File renamed without changes.
5 changes: 5 additions & 0 deletions separate_users/tests/test_app_custom_user/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

admin.site.register(CustomUser, UserAdmin)
File renamed without changes.
6 changes: 6 additions & 0 deletions separate_users/tests/test_app_custom_user/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf import settings
from django.contrib.auth.models import AbstractUser


class CustomUser(AbstractUser):
pass
24 changes: 11 additions & 13 deletions separate_users/tests/test_compatibility.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
from time import sleep

from django.contrib.auth.models import User
from django.test import override_settings
from django.test.testcases import TestCase


Expand All @@ -10,23 +8,23 @@ class AdminTestCase(TestCase):
TODO: check for pre 1.11 ImproperlyConfigured etc.
TODO: check that MIGRATION_MODULES is configured (migration are written into this app!)
"""
username = 'admin'
password = 'admin'

def setUp(self):
pass

def tearDown(self):
pass

def test_improperly_pre_1_11_with_custom_user_model(self):
exit()
pass

@override_settings(
MIGRATION_MODULES = {}
)
def test_improperly_no_migration_modules(self):
exit()

def test_frontend_user_changeview(self):
exit()
"""
TOOD: trigger improperly configured!!? but how?
:return:
"""
from separate_users.models import FrontendUser
FrontendUser.objects.all()

def test_staff_user_changeview(self):
exit()
22 changes: 18 additions & 4 deletions separate_users/tests/test_permissions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.models import Permission
from django.core.urlresolvers import reverse
from django.test import Client
from django.test import TestCase
Expand All @@ -7,16 +8,29 @@
class PermissionsTestCase(TestCase):
"""
check if permissions are there, after management command was run.
check if not there initially - this will fail if django fixes the bug! nice to know.
"""
def setUp(self):
pass

def tearDown(self):
pass

def no_permissions_initially(self):
exit()
def test_no_permissions_initially(self):
"""
check if not there initially - this will fail if django fixes the bug! nice to know.
"""
self.assertEqual(self.permission_count('separate_users', 'add_frontenduser'), 0)
self.assertEqual(self.permission_count('separate_users', 'add_editor'), 0)

def test_permission_management_command(self):
exit()
from django.core.management import call_command
call_command('fix_proxy_permissions', )
self.assertEqual(self.permission_count('separate_users', 'add_frontenduser'), 1)
self.assertEqual(self.permission_count('separate_users', 'add_editor'), 1)

def permission_count(self, app_label, codename):
count = Permission.objects.filter(
content_type__app_label=app_label,
codename=codename,
).count()
return count
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def read(fname):
packages=find_packages(),
install_requires=(
# 'Django>=1.3,<1.5', # no need to limit while in development
'Django>=1.11',
'Django>=1.8',
),
include_package_data=True,
zip_safe=False,
Expand Down
8 changes: 4 additions & 4 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ deps =

[testenv:django18]
deps =
django>=1.8, <1.9
{[base]deps}
django>=1.8, <1.9

[testenv:django19]
deps =
django>=1.9, <1.10
{[base]deps}
django>=1.9, <1.10

[testenv:django110]
deps =
django>=1.10, <1.11
{[base]deps}
django>=1.10, <1.11

[testenv:django111]
deps =
{[base]deps}
django>=1.11, <1.12
{[base]deps}

0 comments on commit 5977355

Please sign in to comment.