# Path: chemtrails/contrib/permissions/models.py
# class AccessRule(models.Model):
# 
#     DIRECTION_CHOICES = (
#         (INCOMING, _('INCOMING')),
#         (EITHER, _('EITHER')),
#         (OUTGOING, _('OUTGOING'))
#     )
# 
#     ctype_source = models.ForeignKey(ContentType, verbose_name=_('source content type'),
#                                      related_name='accessrule_ctype_source_set')
#     ctype_target = models.ForeignKey(ContentType, verbose_name=_('target content type'),
#                                      related_name='accessrule_ctype_target_set')
#     description = models.TextField(_('description'), default='')
#     permissions = models.ManyToManyField(Permission, verbose_name=_('access rule permissions'), blank=True,
#                                          help_text=_('Required permissions for target node.'),
#                                          related_name='accessrule_permissions', related_query_name='accessrule')
#     relation_types = ArrayField(verbose_name=_('relation types'), base_field=JSONField(), default=list,
#                                 help_text=_('List of relation type rule definitions, optionally with a map '
#                                             'of properties for matching the relation type node. '
#                                             'Example: {"USER": {"is_superuser": true}}, {"GROUP": null}'))
#     direction = models.SmallIntegerField(verbose_name=_('direction'), choices=DIRECTION_CHOICES,
#                                          blank=True, null=True, default=None,
#                                          help_text=_('Override calculated direction for relationships.<br/> '
#                                                      'Use with caution, this will affect *all* directional '
#                                                      'relationships for evaluation of this rule!'))
#     is_active = models.BooleanField(default=True, help_text=_('Uncheck to disable evaluation of the rule '
#                                                               'in the rule chain.'))
#     requires_staff = models.BooleanField(default=False, help_text=_('Requires user which should have '
#                                                                     'permissions evaluated to be a staff user.'))
#     created = models.DateTimeField(verbose_name=_('created'), auto_now_add=True)
#     updated = models.DateTimeField(verbose_name=_('updated'), auto_now=True)
# 
#     class Meta:
#         ordering = ('ctype_target', '-created',)
# 
#     def __repr__(self):
#         return '<%(class)s: [%(source)s]-[*]-[%(target)s]>' % {
#             'class': self.__class__.__name__,
#             'source': '%s.%s' % (self.ctype_source.app_label, self.ctype_source.model),
#             'target': '%s.%s' % (self.ctype_target.app_label, self.ctype_target.model),
#         }
# 
#     def __str__(self):
#         return '[%(source)s]-[*]-[%(target)s]' % {
#             'source': self.ctype_source,
#             'target': self.ctype_target
#         }
# 
#     @property
#     def relation_types_obj(self):
#         """
#         Return the relation types JSON string as an OrderedDict.
#         """
#         if self.relation_types:
#             return [json.loads(rule, object_pairs_hook=OrderedDict) for rule in self.relation_types]
#         else:
#             return OrderedDict()
# 
# Path: tests/utils.py
# class flush_nodes(ContextDecorator):
#     """
#     Context decorator which will wipe out the all
#     ``ModelNode`` nodes on enter and exit.
#     """
# 
#     def __enter__(self):
#         clear_neo4j_model_nodes()
# 
#     def __exit__(self, *exc):
#         clear_neo4j_model_nodes()


import json
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from rest_framework import status
from rest_framework.reverse import reverse
from rest_framework.test import APITestCase, APIClient
from chemtrails.contrib.permissions.models import AccessRule
from tests.utils import flush_nodes
    def test_get_access_rule_list(self):
        response = self.client.get(reverse('admin:accessrule-list'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    @flush_nodes()
    def test_get_access_rule_detail(self):
        access_rule = AccessRule.objects.create(
            ctype_source=ContentType.objects.get_by_natural_key('auth', 'user'),
            ctype_target=ContentType.objects.get_by_natural_key('testapp', 'book'),
            is_active=True,
            relation_types=[{'BOOK': None}]
        )
        access_rule.permissions.add(*list(Permission.objects.filter(codename__in=['add_book', 'change_book'])))
        response = self.client.get(reverse('admin:accessrule-detail', kwargs={'pk': access_rule.pk}))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    @flush_nodes()
    def test_post_access_rule(self):
        response = self.client.post(reverse('admin:accessrule-list'), data={
            'ctype_source': 'auth.user',
            'ctype_target': 'testapp.book',
            'permissions': [
                'testapp.add_book',
                'testapp.change_book',
                'testapp.delete_book'
            ],
            'relation_types': [{'BOOK': None}]
        }, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)


# Path: chemtrails/contrib/permissions/models.py
# class AccessRule(models.Model):
# 
#     DIRECTION_CHOICES = (
#         (INCOMING, _('INCOMING')),
#         (EITHER, _('EITHER')),
#         (OUTGOING, _('OUTGOING'))
#     )
# 
#     ctype_source = models.ForeignKey(ContentType, verbose_name=_('source content type'),
#                                      related_name='accessrule_ctype_source_set')
#     ctype_target = models.ForeignKey(ContentType, verbose_name=_('target content type'),
#                                      related_name='accessrule_ctype_target_set')
#     description = models.TextField(_('description'), default='')
#     permissions = models.ManyToManyField(Permission, verbose_name=_('access rule permissions'), blank=True,
#                                          help_text=_('Required permissions for target node.'),
#                                          related_name='accessrule_permissions', related_query_name='accessrule')
#     relation_types = ArrayField(verbose_name=_('relation types'), base_field=JSONField(), default=list,
#                                 help_text=_('List of relation type rule definitions, optionally with a map '
#                                             'of properties for matching the relation type node. '
#                                             'Example: {"USER": {"is_superuser": true}}, {"GROUP": null}'))
#     direction = models.SmallIntegerField(verbose_name=_('direction'), choices=DIRECTION_CHOICES,
#                                          blank=True, null=True, default=None,
#                                          help_text=_('Override calculated direction for relationships.<br/> '
#                                                      'Use with caution, this will affect *all* directional '
#                                                      'relationships for evaluation of this rule!'))
#     is_active = models.BooleanField(default=True, help_text=_('Uncheck to disable evaluation of the rule '
#                                                               'in the rule chain.'))
#     requires_staff = models.BooleanField(default=False, help_text=_('Requires user which should have '
#                                                                     'permissions evaluated to be a staff user.'))
#     created = models.DateTimeField(verbose_name=_('created'), auto_now_add=True)
#     updated = models.DateTimeField(verbose_name=_('updated'), auto_now=True)
# 
#     class Meta:
#         ordering = ('ctype_target', '-created',)
# 
#     def __repr__(self):
#         return '<%(class)s: [%(source)s]-[*]-[%(target)s]>' % {
#             'class': self.__class__.__name__,
#             'source': '%s.%s' % (self.ctype_source.app_label, self.ctype_source.model),
#             'target': '%s.%s' % (self.ctype_target.app_label, self.ctype_target.model),
#         }
# 
#     def __str__(self):
#         return '[%(source)s]-[*]-[%(target)s]' % {
#             'source': self.ctype_source,
#             'target': self.ctype_target
#         }
# 
#     @property
#     def relation_types_obj(self):
#         """
#         Return the relation types JSON string as an OrderedDict.
#         """
#         if self.relation_types:
#             return [json.loads(rule, object_pairs_hook=OrderedDict) for rule in self.relation_types]
#         else:
#             return OrderedDict()
# 
# Path: tests/utils.py
# class flush_nodes(ContextDecorator):
#     """
#     Context decorator which will wipe out the all
#     ``ModelNode`` nodes on enter and exit.
#     """
# 
#     def __enter__(self):
#         clear_neo4j_model_nodes()
# 
#     def __exit__(self, *exc):
#         clear_neo4j_model_nodes()


# Path: tests/contrib/permissions/test_views.py
import json
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from rest_framework import status
from rest_framework.reverse import reverse
from rest_framework.test import APITestCase, APIClient
from chemtrails.contrib.permissions.models import AccessRule
from tests.utils import flush_nodes

    def test_get_access_rule_list(self):
        response = self.client.get(reverse('admin:accessrule-list'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    @flush_nodes()
    def test_get_access_rule_detail(self):
        access_rule = AccessRule.objects.create(
            ctype_source=ContentType.objects.get_by_natural_key('auth', 'user'),
            ctype_target=ContentType.objects.get_by_natural_key('testapp', 'book'),
            is_active=True,
            relation_types=[{'BOOK': None}]
        )
        access_rule.permissions.add(*list(Permission.objects.filter(codename__in=['add_book', 'change_book'])))
        response = self.client.get(reverse('admin:accessrule-detail', kwargs={'pk': access_rule.pk}))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    @flush_nodes()
    def test_post_access_rule(self):
        response = self.client.post(reverse('admin:accessrule-list'), data={
            'ctype_source': 'auth.user',
            'ctype_target': 'testapp.book',
            'permissions': [
                'testapp.add_book',
                'testapp.change_book',
                'testapp.delete_book'
            ],
            'relation_types': [{'BOOK': None}]
        }, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)


    @flush_nodes()