<commit_before># -*- coding: utf-8 -*-
"""
    tipfy.ext.user.acl
    ~~~~~~~~~~~~~~~~~~

    Simple Access Control List.

    This module provides utilities to manage permissions for anything that
    requires some level of restriction, like datastore models or handlers.
    Access permissions can be grouped in roles for convenience, so that a new
    user can be assigned to a role directly instead of having all his
    permissions defined manually. Individual access permissions can then
    override or extend the role permissions.

    .. note::
       Roles are optional, so this module doesn't define a roles model, to keep
       things simple and fast. Role definitions are set directly in the Acl
       class. The strategy to load roles is open to the implementation: for
       best performance, define them statically in a module.

    Usage example:

    .. code-block:: python

       # Set a dict of roles with an 'admin' role that has full access and
       # assign users to it. Each role maps to a list of rules. Each rule is a
       # tuple (topic, name, flag), where flag is as bool to allow or disallow
       # access. Wildcard '*' can be used to match all topics and/or names.
       Acl.roles_map = {
           'admin': [
               ('*', '*', True),
           ],
       }

       # Assign users 'user_1' and 'user_2' to the 'admin' role.
       AclRules.insert_or_update(area='my_area', user='user_1', roles=['admin'])
       AclRules.insert_or_update(area='my_area', user='user_2', roles=['admin'])

       # Restrict 'user_2' from accessing a specific resource, adding a new
       # rule with flag set to False. Now this user has access to everything
       # except this resource.
       user_acl = AclRules.get_by_area_and_user('my_area', 'user_2')
       user_acl.rules.append(('UserAdmin', '*', False))
       user_acl.put()

       # Check that 'user_2' permissions are correct.
       acl = Acl(area='my_area', user='user_2')
       assert acl.has_access(topic='UserAdmin', name='save') is False
       assert acl.has_access(topic='AnythingElse', name='put') is True

    The Acl object should be created once after a user is loaded, so that
    it becomes available for the app to do all necessary permissions checkings.

    Based on concept from Solar's Access and Role classes: http://solarphp.com.

    :copyright: <NAME> <<EMAIL>>
    :copyright: 2010 by tipfy.org.
    :license: BSD, see LICENSE.txt for more details.
"""
from google.appengine.ext import db
from google.appengine.api import memcache

from tipfy import get_config
from tipfy.ext.db import PickleProperty

#: Cache for loaded rules.
_rules_map = {}


class AclMixin(object):
    """A mixin that adds an ``acl`` property to a :class:`tipfy.RequestHandler`.

    The handler must have the properties ``area`` and ``current_user`` set for
    it to work.
    """
    roles_map = None
    roles_lock = None

    @cached_property
    def acl(self):
        """Loads and returns the access permission for the currently logged in
        user. This requires the handler to have an ``area`` and ``current_user``
        attributes. Casted to a string they must return the object identifiers.
        """
        return Acl(str(self.area.key()), str(self.current_user.key()),
            self.roles_map, self.roles_lock)


def validate_rules(rules):
    """Ensures that the list of rule tuples is set correctly."""<commit_msg>Added missing import for AclMixin.<commit_after># -*- coding: utf-8 -*-
"""
    tipfy.ext.user.acl
    ~~~~~~~~~~~~~~~~~~

    Simple Access Control List.

    This module provides utilities to manage permissions for anything that
    requires some level of restriction, like datastore models or handlers.
    Access permissions can be grouped in roles for convenience, so that a new
    user can be assigned to a role directly instead of having all his
    permissions defined manually. Individual access permissions can then
    override or extend the role permissions.

    .. note::
       Roles are optional, so this module doesn't define a roles model, to keep
       things simple and fast. Role definitions are set directly in the Acl
       class. The strategy to load roles is open to the implementation: for
       best performance, define them statically in a module.

    Usage example:

    .. code-block:: python

       # Set a dict of roles with an 'admin' role that has full access and
       # assign users to it. Each role maps to a list of rules. Each rule is a
       # tuple (topic, name, flag), where flag is as bool to allow or disallow
       # access. Wildcard '*' can be used to match all topics and/or names.
       Acl.roles_map = {
           'admin': [
               ('*', '*', True),
           ],
       }

       # Assign users 'user_1' and 'user_2' to the 'admin' role.
       AclRules.insert_or_update(area='my_area', user='user_1', roles=['admin'])
       AclRules.insert_or_update(area='my_area', user='user_2', roles=['admin'])

       # Restrict 'user_2' from accessing a specific resource, adding a new
       # rule with flag set to False. Now this user has access to everything
       # except this resource.
       user_acl = AclRules.get_by_area_and_user('my_area', 'user_2')
       user_acl.rules.append(('UserAdmin', '*', False))
       user_acl.put()

       # Check that 'user_2' permissions are correct.
       acl = Acl(area='my_area', user='user_2')
       assert acl.has_access(topic='UserAdmin', name='save') is False
       assert acl.has_access(topic='AnythingElse', name='put') is True

    The Acl object should be created once after a user is loaded, so that
    it becomes available for the app to do all necessary permissions checkings.

    Based on concept from Solar's Access and Role classes: http://solarphp.com.

    :copyright: <NAME> <<EMAIL>>
    :copyright: 2010 by tipfy.org.
    :license: BSD, see LICENSE.txt for more details.
"""
from google.appengine.ext import db
from google.appengine.api import memcache

from tipfy import get_config, cached_property
from tipfy.ext.db import PickleProperty

#: Cache for loaded rules.
_rules_map = {}


class AclMixin(object):
    """A mixin that adds an ``acl`` property to a :class:`tipfy.RequestHandler`.

    The handler must have the properties ``area`` and ``current_user`` set for
    it to work.
    """
    roles_map = None
    roles_lock = None

    @cached_property
    def acl(self):
        """Loads and returns the access permission for the currently logged in
        user. This requires the handler to have an ``area`` and ``current_user``
        attributes. Casted to a string they must return the object identifiers.
        """
        return Acl(str(self.area.key()), str(self.current_user.key()),
            self.roles_map, self.roles_lock)


def validate_rules(rules):
    """Ensures that the list of rule tuples is set correctly."""
{'fraction_non_alphanumeric': 0.09527946713003185, 'fraction_numerical': 0.003764842166232262, 'mean_word_length': 2.9401026811180833, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2985761', 'n_tokens_mistral': 1948, 'n_tokens_neox': 1881, 'n_words': 794}