# Path: tutelary/engine.py
# class Action(SimpleSeparated):
#     """Actions are represented by period-separated sequences of elements
#     (e.g. ``parcel.edit``, ``admin.assign-role``) with wildcard
#     elements indicated by ``*`` (e.g. ``party.*``).  A list of
#     *registered* actions is maintained to support permissions set
#     queries to find the set of actions that are permitted on a
#     specified object pattern.
# 
#     """
#     separator = '.'
# 
#     registered = set()
# 
#     def register(action):
#         """Action registration is used to support generating lists of
#         permitted actions from a permission set and an object pattern.
#         Only registered actions will be returned by such queries.
# 
#         """
#         if isinstance(action, str):
#             Action.register(Action(action))
#         elif isinstance(action, Action):
#             Action.registered.add(action)
#         else:
#             for a in action:
#                 Action.register(a)
# 
# Path: tutelary/models.py
# class Policy(models.Model):
#     """An individual policy has a name and a JSON policy body.  Changes to
#     policies are audited.
# 
#     """
# 
#     name = models.CharField(max_length=200)
#     """Policy name field."""
# 
#     body = models.TextField()
#     """Policy JSON body."""
# 
#     audit_log = AuditLog()
# 
#     def __str__(self):
#         return self.name
# 
#     def variable_names(self):
#         pat = re.compile(r'\$(?:([_a-z][_a-z0-9]*)|{([_a-z][_a-z0-9]*)})')
#         return set([m[0] for m in re.findall(pat, self.body)])
# 
#     def save(self, *args, **kwargs):
#         super().save(*args, **kwargs)
#         self.refresh()
# 
#     def refresh(self):
#         for pset in _policy_psets([self]):
#             pset.refresh()
# 
# Path: tutelary/decorators.py
# def permissioned_model(cls, perm_type=None, path_fields=None, actions=None):
#     """Function to set up a model for permissioning.  Can either be called
#     directly, passing a class and suitable values for ``perm_type``,
#     ``path_fields`` and ``actions``, or can be used as a class
#     decorator, taking values for ``perm_type``, ``path_fields`` and
#     ``actions`` from the ``TutelaryMeta`` subclass of the decorated
#     class.
# 
#     """
#     if not issubclass(cls, models.Model):
#         raise DecoratorException(
#             'permissioned_model',
#             "class '" + cls.__name__ + "' is not a Django model"
#         )
#     added = False
#     try:
#         if not hasattr(cls, 'TutelaryMeta'):
#             if perm_type is None or path_fields is None or actions is None:
#                 raise DecoratorException(
#                     'permissioned_model',
#                     ("missing argument: all of perm_type, path_fields and " +
#                      "actions must be supplied")
#                 )
#             added = True
#             cls.TutelaryMeta = type('TutelaryMeta', (object,),
#                                     dict(perm_type=perm_type,
#                                          path_fields=path_fields,
#                                          actions=actions))
#         cls.TutelaryMeta.pfs = ([cls.TutelaryMeta.perm_type] +
#                                 get_path_fields(cls))
#         perms_objs = {}
#         for a in cls.TutelaryMeta.actions:
#             an = a
#             ap = {}
#             if isinstance(a, tuple):
#                 an = a[0]
#                 ap = a[1]
#             Action.register(an)
#             if isinstance(ap, dict) and 'permissions_object' in ap:
#                 po = ap['permissions_object']
#                 if po is not None:
#                     try:
#                         t = cls._meta.get_field(po).__class__
#                         if t not in [models.ForeignKey,
#                                      models.OneToOneField]:
#                             raise PermissionObjectException(po)
#                     except:
#                         raise PermissionObjectException(po)
#                 perms_objs[an] = po
#         if len(perms_objs) == 0:
#             cls.get_permissions_object = get_perms_object
#         else:
#             cls.get_permissions_object = make_get_perms_object(perms_objs)
#         return cls
#     except:
#         if added:
#             del cls.TutelaryMeta
#         raise


from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
from tutelary.engine import Action
from tutelary.models import Policy
from tutelary.decorators import permissioned_model


permissioned_model(
    Policy, perm_type='policy', path_fields=['name'],
    actions=[
        ('policy.list', {'description': "Can list existing policies",
                         'permissions_object': None}),
        ('policy.create', {'description': "Can create policies",
                           'permissions_object': None}),
        ('policy.detail', {'description': "Can view details of a policy"}),
        ('policy.edit',   {'description': "Can update existing policies"}),
        ('policy.delete', {'description': "Can delete policies"})
    ]
)
permissioned_model(
    User, perm_type='user', path_fields=['username'],
    actions=[
        ('user.list',   {'permissions_object': None}),
        ('user.create', {'permissions_object': None}),
        'user.detail',
        'user.edit',
        'user.delete'
    ]
)

Action.register('statistics')


class UserPolicyAssignment(models.Model):
    user = models.ForeignKey(User)

# Path: tutelary/engine.py
# class Action(SimpleSeparated):
#     """Actions are represented by period-separated sequences of elements
#     (e.g. ``parcel.edit``, ``admin.assign-role``) with wildcard
#     elements indicated by ``*`` (e.g. ``party.*``).  A list of
#     *registered* actions is maintained to support permissions set
#     queries to find the set of actions that are permitted on a
#     specified object pattern.
# 
#     """
#     separator = '.'
# 
#     registered = set()
# 
#     def register(action):
#         """Action registration is used to support generating lists of
#         permitted actions from a permission set and an object pattern.
#         Only registered actions will be returned by such queries.
# 
#         """
#         if isinstance(action, str):
#             Action.register(Action(action))
#         elif isinstance(action, Action):
#             Action.registered.add(action)
#         else:
#             for a in action:
#                 Action.register(a)
# 
# Path: tutelary/models.py
# class Policy(models.Model):
#     """An individual policy has a name and a JSON policy body.  Changes to
#     policies are audited.
# 
#     """
# 
#     name = models.CharField(max_length=200)
#     """Policy name field."""
# 
#     body = models.TextField()
#     """Policy JSON body."""
# 
#     audit_log = AuditLog()
# 
#     def __str__(self):
#         return self.name
# 
#     def variable_names(self):
#         pat = re.compile(r'\$(?:([_a-z][_a-z0-9]*)|{([_a-z][_a-z0-9]*)})')
#         return set([m[0] for m in re.findall(pat, self.body)])
# 
#     def save(self, *args, **kwargs):
#         super().save(*args, **kwargs)
#         self.refresh()
# 
#     def refresh(self):
#         for pset in _policy_psets([self]):
#             pset.refresh()
# 
# Path: tutelary/decorators.py
# def permissioned_model(cls, perm_type=None, path_fields=None, actions=None):
#     """Function to set up a model for permissioning.  Can either be called
#     directly, passing a class and suitable values for ``perm_type``,
#     ``path_fields`` and ``actions``, or can be used as a class
#     decorator, taking values for ``perm_type``, ``path_fields`` and
#     ``actions`` from the ``TutelaryMeta`` subclass of the decorated
#     class.
# 
#     """
#     if not issubclass(cls, models.Model):
#         raise DecoratorException(
#             'permissioned_model',
#             "class '" + cls.__name__ + "' is not a Django model"
#         )
#     added = False
#     try:
#         if not hasattr(cls, 'TutelaryMeta'):
#             if perm_type is None or path_fields is None or actions is None:
#                 raise DecoratorException(
#                     'permissioned_model',
#                     ("missing argument: all of perm_type, path_fields and " +
#                      "actions must be supplied")
#                 )
#             added = True
#             cls.TutelaryMeta = type('TutelaryMeta', (object,),
#                                     dict(perm_type=perm_type,
#                                          path_fields=path_fields,
#                                          actions=actions))
#         cls.TutelaryMeta.pfs = ([cls.TutelaryMeta.perm_type] +
#                                 get_path_fields(cls))
#         perms_objs = {}
#         for a in cls.TutelaryMeta.actions:
#             an = a
#             ap = {}
#             if isinstance(a, tuple):
#                 an = a[0]
#                 ap = a[1]
#             Action.register(an)
#             if isinstance(ap, dict) and 'permissions_object' in ap:
#                 po = ap['permissions_object']
#                 if po is not None:
#                     try:
#                         t = cls._meta.get_field(po).__class__
#                         if t not in [models.ForeignKey,
#                                      models.OneToOneField]:
#                             raise PermissionObjectException(po)
#                     except:
#                         raise PermissionObjectException(po)
#                 perms_objs[an] = po
#         if len(perms_objs) == 0:
#             cls.get_permissions_object = get_perms_object
#         else:
#             cls.get_permissions_object = make_get_perms_object(perms_objs)
#         return cls
#     except:
#         if added:
#             del cls.TutelaryMeta
#         raise


# Path: example/exampleapp/models.py
from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
from tutelary.engine import Action
from tutelary.models import Policy
from tutelary.decorators import permissioned_model



permissioned_model(
    Policy, perm_type='policy', path_fields=['name'],
    actions=[
        ('policy.list', {'description': "Can list existing policies",
                         'permissions_object': None}),
        ('policy.create', {'description': "Can create policies",
                           'permissions_object': None}),
        ('policy.detail', {'description': "Can view details of a policy"}),
        ('policy.edit',   {'description': "Can update existing policies"}),
        ('policy.delete', {'description': "Can delete policies"})
    ]
)
permissioned_model(
    User, perm_type='user', path_fields=['username'],
    actions=[
        ('user.list',   {'permissions_object': None}),
        ('user.create', {'permissions_object': None}),
        'user.detail',
        'user.edit',
        'user.delete'
    ]
)

Action.register('statistics')


class UserPolicyAssignment(models.Model):
    user = models.ForeignKey(User)

    policy = models.ForeignKey(Policy)