Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'acl_per_page'. needs tests and docs
- Loading branch information
Showing
29 changed files
with
747 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
django>=1.5.1 | ||
coverage | ||
coveralls | ||
factory-boy==2.4.1 | ||
mock>=1.0.1 | ||
nose>=1.3.0 | ||
django-nose>=1.2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import factory | ||
from django.contrib.auth.models import User, Group, Permission | ||
from waliki.models import ACLRule | ||
|
||
|
||
class UserFactory(factory.django.DjangoModelFactory): | ||
username = factory.Sequence(lambda n: u'user{0}'.format(n)) | ||
password = 'pass' | ||
email = factory.LazyAttribute(lambda o: '%s@example.org' % o.username) | ||
|
||
class Meta: | ||
model = User | ||
|
||
@factory.post_generation | ||
def groups(self, create, extracted, **kwargs): | ||
if not create: | ||
# Simple build, do nothing. | ||
return | ||
|
||
if extracted: | ||
# A list of groups were passed in, use them | ||
for group in extracted: | ||
self.groups.add(group) | ||
|
||
|
||
class GroupFactory(factory.django.DjangoModelFactory): | ||
class Meta: | ||
model = Group | ||
|
||
name = factory.Sequence(lambda n: "Group #%s" % n) | ||
|
||
@factory.post_generation | ||
def users(self, create, extracted, **kwargs): | ||
if not create: | ||
# Simple build, do nothing. | ||
return | ||
|
||
if extracted: | ||
# A list of groups were passed in, use them | ||
for user in extracted: | ||
self.user_set.add(user) | ||
|
||
|
||
class ACLRuleFactory(factory.django.DjangoModelFactory): | ||
class Meta: | ||
model = ACLRule | ||
|
||
name = factory.Sequence(lambda n: u'Rule {0}'.format(n)) | ||
slug = factory.Sequence(lambda n: u'page{0}'.format(n)) | ||
|
||
@factory.post_generation | ||
def permissions(self, create, extracted, **kwargs): | ||
if not create: | ||
# Simple build, do nothing. | ||
return | ||
|
||
if extracted: | ||
# A list of groups were passed in, use them | ||
for perm in extracted: | ||
if not isinstance(perm, Permission): | ||
perm = Permission.objects.get(content_type__app_label='waliki', codename=perm) | ||
self.permissions.add(perm) | ||
|
||
@factory.post_generation | ||
def users(self, create, extracted, **kwargs): | ||
if not create: | ||
# Simple build, do nothing. | ||
return | ||
|
||
if extracted: | ||
# A list of groups were passed in, use them | ||
for user in extracted: | ||
self.users.add(user) | ||
|
||
@factory.post_generation | ||
def groups(self, create, extracted, **kwargs): | ||
if not create: | ||
# Simple build, do nothing. | ||
return | ||
|
||
if extracted: | ||
# A list of groups were passed in, use them | ||
for group in extracted: | ||
self.groups.add(group) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from .factories import UserFactory, GroupFactory, ACLRuleFactory | ||
from waliki.models import ACLRule | ||
from django.test import TestCase | ||
|
||
|
||
class TestGetUsersRules(TestCase): | ||
|
||
def test_simple_user(self): | ||
user = UserFactory() | ||
ACLRuleFactory(slug='page', permissions=['view_page'], users=[user]) | ||
users = ACLRule.get_users_for('view_page', 'page') | ||
self.assertEqual(set(users), {user}) | ||
|
||
def test_simple_group(self): | ||
group_users = [UserFactory(), UserFactory()] | ||
group = GroupFactory(users=group_users) | ||
ACLRuleFactory(slug='page', permissions=['view_page'], groups=[group]) | ||
users = ACLRule.get_users_for('view_page', 'page') | ||
self.assertEqual(set(users), set(group_users)) | ||
|
||
def test_mixing_group_and_users(self): | ||
user = UserFactory() | ||
group1_users = [UserFactory(), UserFactory()] | ||
group2_users = [UserFactory(), UserFactory()] | ||
group1 = GroupFactory(users=group1_users) | ||
group2 = GroupFactory(users=group2_users) | ||
ACLRuleFactory(slug='page', permissions=['view_page'], | ||
groups=[group1, group2], users=[user]) | ||
users = ACLRule.get_users_for('view_page', 'page') | ||
self.assertEqual(set(users), set(group1_users + group2_users + [user])) | ||
|
||
def test_is_distinct(self): | ||
user = UserFactory() | ||
group1_users = [user] | ||
group1 = GroupFactory(users=group1_users) | ||
ACLRuleFactory(slug='page', permissions=['view_page'], | ||
groups=[group1], users=[user]) | ||
users = ACLRule.get_users_for('view_page', 'page') | ||
self.assertEqual(users.count(), 1) | ||
self.assertEqual(set(users), set(group1_users)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from django.contrib import admin | ||
from .models import Page, ACLRule | ||
|
||
# Register your models here. | ||
admin.site.register(Page) | ||
admin.site.register(ACLRule) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from functools import wraps | ||
from django.conf import settings | ||
from django.shortcuts import render | ||
from django.core.exceptions import PermissionDenied | ||
from django.utils.decorators import available_attrs | ||
from django.utils.encoding import force_str | ||
from django.utils.six.moves.urllib.parse import urlparse | ||
from django.contrib.auth import REDIRECT_FIELD_NAME | ||
from django.shortcuts import resolve_url | ||
from .models import ACLRule | ||
from .settings import WALIKI_ANONYMOUS_USER_PERMISSIONS, WALIKI_LOGGED_USER_PERMISSIONS | ||
|
||
|
||
def page_permission(perm, login_url=None, raise_exception=False, redirect_field_name=REDIRECT_FIELD_NAME): | ||
def decorator(view_func): | ||
@wraps(view_func, assigned=available_attrs(view_func)) | ||
def _wrapped_view(request, *args, **kwargs): | ||
|
||
def check_perms(user): | ||
allowed_users = ACLRule.get_users_for(perm, kwargs['slug']) | ||
if allowed_users: | ||
return user in allowed_users | ||
|
||
if perm in WALIKI_ANONYMOUS_USER_PERMISSIONS: | ||
return True | ||
|
||
if user.is_authenticated() and perm in WALIKI_LOGGED_USER_PERMISSIONS: | ||
return True | ||
|
||
if not isinstance(perm, (list, tuple)): | ||
perms = (perm, ) | ||
else: | ||
perms = perm | ||
# First check if the user has the permission (even anon users) | ||
if user.has_perms(perms): | ||
return True | ||
# In case the 403 handler should be called raise the exception | ||
if raise_exception: | ||
raise PermissionDenied | ||
# As the last resort, show the login form | ||
return False | ||
|
||
if check_perms(request.user): | ||
return view_func(request, *args, **kwargs) | ||
|
||
if request.user.is_authenticated(): | ||
if WALIKI_RENDER_403: | ||
return render(request, 'waliki/403.html', kwargs, status=403) | ||
else: | ||
raise PermissionDenied | ||
|
||
path = request.build_absolute_uri() | ||
# urlparse chokes on lazy objects in Python 3, force to str | ||
resolved_login_url = force_str( | ||
resolve_url(login_url or settings.LOGIN_URL)) | ||
# If the login url is the same scheme and net location then just | ||
# use the path as the "next" url. | ||
login_scheme, login_netloc = urlparse(resolved_login_url)[:2] | ||
current_scheme, current_netloc = urlparse(path)[:2] | ||
if ((not login_scheme or login_scheme == current_scheme) and | ||
(not login_netloc or login_netloc == current_netloc)): | ||
path = request.get_full_path() | ||
from django.contrib.auth.views import redirect_to_login | ||
return redirect_to_login( | ||
path, resolved_login_url, redirect_field_name) | ||
return _wrapped_view | ||
|
||
return decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{% extends "site_base.html" %} | ||
{% load i18n %} | ||
|
||
{% block content %} | ||
<p>{% trans "You aren't authorized to see this page." %}</p> | ||
{% endblock content %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
django-allauth |
Oops, something went wrong.