def test_everyone(self):
        def test_user_deny(user):
            request.user = user
            response = viewset.as_view({'get': 'list'})(request)
            self.assertEqual(
                response.status_code,
                403
            )
            self.assertEqual(
                response.data['detail'],
                "DRFS: Permission denied by acl"
            )

        def test_user_allow(user):
            request.user = user
            response = viewset.as_view({'get': 'list'})(request)
            self.assertEqual(
                response.status_code,
                200
            )
            self.assertEqual(
                response.data,
                []
            )


        modelClass = models.TestModel
        viewset = drfs.generate_viewset(modelClass, acl = [{
            "principalId": "$everyone",
            "property": ".+",
            "permission": "DENY"
        }])

        request = self.factory.get('/')
        test_user_deny(self.anonymous)
        test_user_deny(self.user)
        test_user_deny(self.admin)

        #

        viewset = drfs.generate_viewset(modelClass, acl = [{
            "principalId": "$everyone",
            "property": ".+",
            "permission": "ALLOW"
        }])

        request = self.factory.get('/')
        test_user_allow(self.anonymous)
        test_user_allow(self.user)
        test_user_allow(self.admin)
    def test_unauthenticated(self):
        modelClass = models.TestModel
        viewset = drfs.generate_viewset(modelClass, acl = [{
            "principalId": "$unauthenticated",
            "property": ".+",
            "permission": "DENY"
        }])
        request = self.factory.get('/')

        request.user = self.anonymous
        response = viewset.as_view({'get': 'list'})(request)
        self.assertEqual(
            response.status_code,
            403
        )
        self.assertEqual(
            response.data['detail'],
            "DRFS: Permission denied by acl"
        )

        request.user = self.user
        response = viewset.as_view({'get': 'list'})(request)
        self.assertEqual(
            response.status_code,
            200
        )
        self.assertEqual(
            response.data,
            []
        )
    def test_owner(self):
        modelClass = models.TestModelWithOwner
        obj = modelClass.objects.create(
            owner = self.user
        )
        viewset = drfs.generate_viewset(modelClass, acl = [{
            "principalId": "$owner",
            "property": ".+",
            "permission": "DENY"
        }])
        request = self.factory.get('/')

        request.user = self.anonymous
        response = viewset.as_view({'get': 'retrieve'})(request, pk=obj.pk)
        self.assertEqual(
            response.status_code,
            200
        )
        self.assertEqual(
            response.data['owner'],
            obj.pk
        )

        request.user = self.user
        response = viewset.as_view({'get': 'retrieve'})(request, pk=obj.pk)
        self.assertEqual(
            response.status_code,
            403
        )
        self.assertEqual(
            response.data['detail'],
            "DRFS: Permission denied by acl"
        )
        obj.delete()
    def test_selializergen(self):
        modelClass = models.TestModel
        serializerClass = drfs.generate_serializer(modelClass)
        viewset = drfs.generate_viewset(modelClass)

        self.assertEqual(
            viewset.queryset.model,
            modelClass
        )
        self.assertEqual(
            viewset.serializer_class.Meta.fields,
            serializerClass.Meta.fields
        )
        self.assertEqual(
            viewset.serializer_class.Meta.model,
            modelClass
        )
        self.assertEqual(
            viewset.filter_backends,
            ()
        )
        self.assertEqual(
            viewset.permission_classes,
            [AllowAny]
        )
    def test_selializergen_with_expand(self):
        modelClass = models.TestModelWithRelations_Flat
        modelClass.DRFS_MODEL_DEFINITION['serializer'] = {
            'expandableFields': {
                'belongs_to_field': {
                    'visible_fields': ['id', 'username']
                }
            }
        }
        serializerClass = drfs.generate_serializer(modelClass)
        viewset = drfs.generate_viewset(modelClass)

        self.assertEqual(
            viewset.queryset.model,
            modelClass
        )
        self.assertEqual(
            viewset.serializer_class.Meta.fields,
            serializerClass.Meta.fields
        )
        self.assertEqual(
            viewset.serializer_class.Meta.model,
            modelClass
        )
        self.assertEqual(
            viewset.filter_backends,
            ()
        )
        self.assertEqual(
            viewset.permission_classes,
            [AllowAny]
        )

        modelClass.objects.create(belongs_to_field=self.user)

        request = self.factory.get('/?expand=' + json.dumps({'belongs_to_field': True}))
        request.query_params = {
            'expand': json.dumps({'belongs_to_field': True})
        }
        response = viewset.as_view({'get': 'list'})(request)
        self.assertListEqual(response.data, [{
            "id": 1,
            "belongs_to_field": 1,
            "$belongs_to_field": {
                "id": 1,
                "username": "******"
            },
            "has_one": None,
            "has_many": []
        }])
    def test_complex_acl(self):
        def test_user(user, apiPoint, expectCode):
            request.user = user
            func = viewset.as_view(apiPoint)
            p = list(apiPoint.items())[0][1]
            if p in ['list', 'create']:
                response = func(request)
            else:
                response = func(request, pk=obj.pk)
            self.assertEqual(
                response.status_code,
                expectCode
            )
            return response.data


        modelClass = models.TestModelWithOwner
        obj = modelClass.objects.create(
            owner = self.user
        )

        class SpecialMixin(object):
            @action(detail=False)
            def my_custom_action(self, *args, **kwargs):
                return Response('success')

            @action(methods=['get', 'post'], detail=False)
            def my_custom_action2(self, *args, **kwargs):
                return Response('success')


        viewset = drfs.generate_viewset(modelClass, mixins=[SpecialMixin], acl=[
            {
                "principalId": "$everyone",
                "property": ".+",
                "permission": "DENY"
            }, {
                "principalId": "$authenticated",
                "property": "create",
                "permission": "ALLOW"
            }, {
                "principalId": "$authenticated",
                "property": ["list", "my_custom_action"],
                "permission": "ALLOW"
            }, {
                "principalId": "$unauthenticated",
                "property": "my_custom_action2",
                "permission": "ALLOW"
            } ,{
                "principalId": "$owner",
                "property": "update",
                "permission": "ALLOW"
            }, {
                "principalId": "$owner",
                "property": "destroy",
                "permission": "ALLOW"
            }, {
                "principalId": "$admin",
                "property": ".+",
                "permission": "ALLOW"
            }
        ])

        request = self.factory.get('/')
        test_user(self.anonymous, {'get': 'list'}, 403)
        test_user(self.anonymous, {'get': 'retrieve'}, 403)
        test_user(self.anonymous, {'get': 'my_custom_action'}, 403)
        test_user(self.anonymous, {'get': 'my_custom_action2'}, 200)
        test_user(self.user, {'get': 'my_custom_action2'}, 403)

        request = self.factory.post('/')
        test_user(self.anonymous, {'post': 'my_custom_action2'}, 200)
    def test_django_permissions(self):
        modelClass = models.TestModel
        viewset = drfs.generate_viewset(modelClass, acl = [{
            "principalId": "$everyone",
            "property": ".+",
            "permission": "DENY"
        },{
            "principalId": "$djangoPermissions",
            "requiredCodename": "tests.view_testmodel",
            "property": ".+",
            "permission": "ALLOW"
        }])
        request = self.factory.get('/')

        # anon
        request.user = self.anonymous
        response = viewset.as_view({'get': 'list'})(request)
        self.assertEqual(
            response.status_code,
            403
        )
        self.assertEqual(
            response.data['detail'],
            "DRFS: Permission denied by acl"
        )
        # user without permission
        request.user = self.user
        response = viewset.as_view({'get': 'list'})(request)
        self.assertEqual(
            response.status_code,
            403
        )
        self.assertEqual(
            response.data['detail'],
            "DRFS: Permission denied by acl"
        )
        # user with permission
        from django.contrib.auth.models import Permission
        from django.contrib.contenttypes.models import ContentType
        from .models import TestModel
        user = self.user
        permission, created = Permission.objects.get_or_create(
            codename='view_testmodel',
            content_type=ContentType.objects.get(model=TestModel.__name__.lower())
        )
        user.user_permissions.add(permission)

        request.user = User.objects.get(username='******')
        response = viewset.as_view({'get': 'list'})(request)
        self.assertEqual(
            response.status_code,
            200
        )
        self.assertEqual(
            response.data,
            []
        )

        # admin (allow all)
        request.user = self.admin
        response = viewset.as_view({'get': 'list'})(request)
        self.assertEqual(
            response.status_code,
            200
        )
        self.assertEqual(
            response.data,
            []
        )