Commits

Andriy Kornatskyy  committed 90946b1

Added authorized decorator

  • Participants
  • Parent commits d8a891d

Comments (0)

Files changed (3)

 
 setup(
     name='wheezy.security',
-    version='0.1',
+    version='0.1.1',
     description='A lightweight security/cryptography library',
     long_description=README,
     url='https://bitbucket.org/akorn/wheezy.security',

File src/wheezy/security/authorization.py

+
+""" ``authorization`` module.
+"""
+
+from wheezy.security.errors import SecurityError
+
+
+def authorized(wrapped=None, roles=None):
+    """ Demand the user accessing protected resource is
+        authenticated and optionally in one of allowed ``roles``.
+
+        Requires wrapped object to provide attribute principal.
+
+        ``roles`` - a list of authorized roles.
+
+        >>> from wheezy.security.principal import Principal
+        >>> class Context(object):
+        ...     principal = None
+        ...
+        ...     @authorized
+        ...     def op_a(self):
+        ...         return True
+        ...
+        ...     @authorized(roles=('operator',))
+        ...     def op_b(self):
+        ...         return True
+        >>> c = Context()
+        >>> c.op_a() # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
+        Traceback (most recent call last):
+            ...
+        SecurityError: ...
+        >>> c.principal = Principal()
+        >>> c.op_a()
+        True
+        >>> c.principal = None
+        >>> c.op_b() # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
+        Traceback (most recent call last):
+            ...
+        SecurityError: ...
+        >>> c.op_b() # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
+        Traceback (most recent call last):
+            ...
+        SecurityError: ...
+        >>> c.principal = Principal(roles=('user',))
+        >>> c.op_b() # doctest: +ELLIPSIS +IGNORE_EXCEPTION_DETAIL
+        Traceback (most recent call last):
+            ...
+        SecurityError: ...
+        >>> c.principal = Principal(roles=('user', 'operator'))
+        >>> c.op_b()
+        True
+    """
+    def decorate(func):
+        if roles:
+            def check_roles(context, *args, **kwargs):
+                principal = context.principal
+                if principal:
+                    principal_roles = principal.roles
+                    for role in roles:
+                        if role in principal_roles:
+                            break
+                    else:
+                        raise SecurityError('Not authorized.')
+                    return func(context, *args, **kwargs)
+                else:
+                    raise SecurityError('Not authorized.')
+            return check_roles
+        else:
+            def check_authenticated(context, *args, **kwargs):
+                if context.principal:
+                    return func(context, *args, **kwargs)
+                else:
+                    raise SecurityError('Not authorized.')
+            return check_authenticated
+    if wrapped is None:
+        return decorate
+    else:
+        return decorate(wrapped)

File src/wheezy/security/errors.py

+
+""" ``errors`` module.
+"""
+
+
+class SecurityError(RuntimeError):
+    """ Raised when a security error occurs. It is subclass of
+        ``RuntimeError``.
+    """
+
+    def __init__(self, message):
+        self.message = message
+
+    def __str__(self):
+        return self.message