Permalink
Browse files

Add templatetags for permission check

  • Loading branch information...
1 parent 2d7fa69 commit 2928778eb381731b6eba1c806148abda207babb4 @lambdalisue committed Mar 4, 2012
View
@@ -16,6 +16,8 @@ def setconf(name, default_value):
setattr(settings, name, value)
setconf('PERMISSION_MODULE_NAME', 'permissions')
+setconf('PERMISSION_BUILTIN_TEMPLATETAGS', True)
+setconf('PERMISSION_REPLACE_BUILTIN_IF', True)
# validate settings
if installed:
@@ -28,10 +30,21 @@ def setconf(name, default_value):
)
if 'permission.backends.PermissionBackend' \
not in settings.AUTHENTICATION_BACKENDS:
- raise ImproperlyConfigured(
+ warnings.warn(Warning,
'"permission.backends.PermissionBackend" is not found in '
'`AUTHENTICATION_BACKENDS`.'
)
+ if 'permission.backends.RoleBackend' \
+ not in settings.AUTHENTICATION_BACKENDS:
+ warnings.warn(Warning,
+ '"permission.backends.RoleBackend" is not found in '
+ '`AUTHENTICATION_BACKENDS`.'
+ )
+
+# Register templatetags in builtin
+if settings.PERMISSION_BUILTIN_TEMPLATETAGS:
+ from django.template import add_to_builtins
+ add_to_builtins('permission.templatetags.permission_tags')
# Auto-discover INSTALLED_APPS permissions.py modules
if installed:
@@ -1,4 +1,2 @@
-from authenticate_backend import ModelBackend
-from authenticate_backend import RemoteUserBackend
from permission_backend import PermissionBackend
from role_backend import RoleBackend
@@ -1,64 +0,0 @@
-# vim: set fileencoding=utf-8 :
-"""
-short module explanation
-
-
-AUTHOR:
- lambdalisue[Ali su ae] (lambdalisue@hashnote.net)
-
-License:
- The MIT License (MIT)
-
- Copyright (c) 2012 Alisue allright reserved.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
-
-"""
-from __future__ import with_statement
-from django.contrib.auth.backends import ModelBackend as AuthModelBackend
-from django.contrib.auth.backends import RemoteUserBackend as AuthRemoteUserBackend
-
-class ModelBackend(AuthModelBackend):
- def get_group_permissions(self, user_obj, obj=None):
- """With django-permission, group permission is not available."""
- return set()
- def get_all_permissions(self, user_obj, obj=None):
- """with django-permission, user permission is not available."""
- return set()
- def has_perm(self, user_obj, perm, obj=None):
- """with django-permission, permission check is handled by PermissionBackend"""
- return False
- def has_module_perms(self, user_obj, app_label):
- """with django-permission, permission check is handled by PermissionBackend"""
- return False
-
-class RemoteUserBackend(AuthRemoteUserBackend):
- def get_group_permissions(self, user_obj, obj=None):
- """With django-permission, group permission is not available."""
- return set()
- def get_all_permissions(self, user_obj, obj=None):
- """with django-permission, user permission is not available."""
- return set()
- def has_perm(self, user_obj, perm, obj=None):
- """with django-permission, permission check is handled by PermissionBackend"""
- return False
- def has_module_perms(self, user_obj, app_label):
- """with django-permission, permission check is handled by PermissionBackend"""
- return False
-
@@ -73,8 +73,10 @@ def has_perm(self, user_obj, perm, obj=None):
# get permission handlers fot this perm
handlers = registry.get_handlers(perm)
for handler in handlers:
- if handler.has_perm(user_obj, perm, obj=obj):
- return True
+ # check permissions of handler
+ if perm in handler.get_permissions():
+ if handler.has_perm(user_obj, perm, obj=obj):
+ return True
# do not touch this permission
return False
@@ -109,4 +109,5 @@ def has_perm(self, user_obj, perm, obj=None):
)
def has_module_perm(self, user_obj, app_label):
+ """whether the ``user_obj`` has permissions of ``app_label``"""
return False
No changes.
@@ -0,0 +1,117 @@
+# vim: set fileencoding=utf-8 :
+"""
+short module explanation
+
+
+AUTHOR:
+ lambdalisue[Ali su ae] (lambdalisue@hashnote.net)
+
+License:
+ The MIT License (MIT)
+
+ Copyright (c) 2012 Alisue allright reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+
+"""
+from __future__ import with_statement
+from distutils.version import StrictVersion
+from django import get_version
+
+if StrictVersion(get_version()) < '1.4':
+ from django.template import Node
+ from django.template import NodeList
+ from django.template import VariableDoesNotExist
+ from django.template import TemplateSyntaxError
+ from django.template.base import TextNode
+ # copied from django 1.4b
+ class IfNode(Node):
+ def __init__(self, conditions_nodelists):
+ self.conditions_nodelists = conditions_nodelists
+ def __repr__(self):
+ return "<IfNode>"
+ def __iter__(self):
+ for _, nodelist in self.conditions_nodelists:
+ for node in nodelist:
+ yield node
+ @property
+ def nodelist(self):
+ return NodeList(node for _, nodelist in self.conditions_nodelists for node in nodelist)
+ def render(self, context):
+ for condition, nodelist in self.conditions_nodelists:
+ if condition is not None: # if / elif clause
+ try:
+ match = condition.eval(context)
+ except VariableDoesNotExist:
+ match = None
+ else: # else clause
+ match = True
+ if match:
+ return nodelist.render(context)
+ return ''
+ # copied from django 1.4b
+ def parse(self, parse_until=None):
+ if parse_until is None:
+ parse_until = []
+ nodelist = self.create_nodelist()
+ while self.tokens:
+ token = self.next_token()
+ # Use the raw values here for TOKEN_* for a tiny performance boost.
+ if token.token_type == 0: # TOKEN_TEXT
+ self.extend_nodelist(nodelist, TextNode(token.contents), token)
+ elif token.token_type == 1: # TOKEN_VAR
+ if not token.contents:
+ self.empty_variable(token)
+ filter_expression = self.compile_filter(token.contents)
+ var_node = self.create_variable_node(filter_expression)
+ self.extend_nodelist(nodelist, var_node, token)
+ elif token.token_type == 2: # TOKEN_BLOCK
+ try:
+ command = token.contents.split()[0]
+ except IndexError:
+ self.empty_block_tag(token)
+ if command in parse_until:
+ # put token back on token list so calling
+ # code knows why it terminated
+ self.prepend_token(token)
+ return nodelist
+ # execute callback function for this tag and append
+ # resulting node
+ self.enter_command(command, token)
+ try:
+ compile_func = self.tags[command]
+ except KeyError:
+ self.invalid_block_tag(token, command, parse_until)
+ try:
+ compiled_result = compile_func(self, token)
+ except TemplateSyntaxError, e:
+ if not self.compile_function_error(token, e):
+ raise
+ self.extend_nodelist(nodelist, compiled_result, token)
+ self.exit_command()
+ if parse_until:
+ self.unclosed_block_tag(parse_until)
+ return nodelist
+ def parser_patch(instance):
+ instance.__class__.parse = parse
+ return instance
+else:
+ from django.template.defaulttags import IfNode
+ parser_patch = lambda instance: instance
+
@@ -0,0 +1,131 @@
+# vim: set fileencoding=utf-8 :
+"""
+templatetags
+
+
+AUTHOR:
+ lambdalisue[Ali su ae] (lambdalisue@hashnote.net)
+
+License:
+ The MIT License (MIT)
+
+ Copyright (c) 2012 Alisue allright reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to
+ deal in the Software without restriction, including without limitation the
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ IN THE SOFTWARE.
+
+"""
+from django.conf import settings
+from django import template
+from django.template import TemplateSyntaxError
+from django.template import VariableDoesNotExist
+from django.template.smartif import infix
+from django.template.smartif import IfParser
+from django.template.smartif import OPERATORS
+from django.template.defaulttags import Node
+from django.template.defaulttags import NodeList
+from django.template.defaulttags import TemplateLiteral
+
+from permission.templatetags.patch import IfNode
+from permission.templatetags.patch import parser_patch
+
+register = template.Library()
+
+def of_operator(context, x, y):
+ return x.eval(context), y.eval(context)
+
+def has_operator(context, x, y):
+ user = x.eval(context)
+ perm = y.eval(context)
+ if isinstance(perm, (list, tuple)):
+ perm, obj = perm
+ else:
+ obj = None
+ return user.has_perm(perm, obj)
+
+EXTRA_OPERATORS = {
+ 'of': infix(20, of_operator),
+ 'has': infix(10, has_operator),
+}
+EXTRA_OPERATORS.update(OPERATORS)
+# Assign 'id' to each:
+for key, op in EXTRA_OPERATORS.items():
+ op.id = key
+
+class PermissionIfParser(IfParser):
+ OPERATORS = EXTRA_OPERATORS
+
+ def translate_token(self, token):
+ try:
+ op = self.OPERATORS[token]
+ except (KeyError, TypeError):
+ return self.create_var(token)
+ else:
+ return op()
+
+class TemplatePermissionIfParser(PermissionIfParser):
+ error_class = TemplateSyntaxError
+
+ def __init__(self, parser, *args, **kwargs):
+ self.template_parser = parser
+ super(TemplatePermissionIfParser, self).__init__(*args, **kwargs)
+
+ def create_var(self, value):
+ return TemplateLiteral(self.template_parser.compile_filter(value), value)
+
+
+@register.tag('permission')
+def do_permissionif(parser, token):
+ # patch parser for django 1.3.1
+ parser = parser_patch(parser)
+
+ bits = token.split_contents()
+ ELIF = "el%s" % bits[0]
+ ELSE = "else"
+ ENDIF = "end%s" % bits[0]
+
+ # {% if ... %}
+ bits = bits[1:]
+ condition = do_permissionif.Parser(parser, bits).parse()
+ nodelist = parser.parse((ELIF, ELSE, ENDIF))
+ conditions_nodelists = [(condition, nodelist)]
+ token = parser.next_token()
+
+ # {% elif ... %} (repeatable)
+ while token.contents.startswith(ELIF):
+ bits = token.split_contents()[1:]
+ condition = do_permissionif.Parser(parser, bits).parse()
+ nodelist = parser.parse((ELIF, ELSE, ENDIF))
+ conditions_nodelists.append((condition, nodelist))
+ token = parser.next_token()
+
+ # {% else %} (optional)
+ if token.contents == ELSE:
+ nodelist = parser.parse((ENDIF,))
+ conditions_nodelists.append((None, nodelist))
+ token = parser.next_token()
+
+ # {% endif %}
+ assert token.contents == ENDIF
+
+ return IfNode(conditions_nodelists)
+do_permissionif.Parser = TemplatePermissionIfParser
+
+if settings.PERMISSION_REPLACE_BUILTIN_IF:
+ register.tag('if', do_permissionif)
+
@@ -2,3 +2,4 @@
from test_handlers import *
from test_backends import *
from test_decorators import *
+from test_templatetags import *
@@ -0,0 +1 @@
+from test_permissionif_templatetag import *
Oops, something went wrong.

0 comments on commit 2928778

Please sign in to comment.