Repository: weni-ai/bothub-engine

Issue:
Examples route permission using user authorization



Discussion:

Resolving patch:
diff --git a/bothub/api/views.py b/bothub/api/views.py
--- a/bothub/api/views.py
+++ b/bothub/api/views.py
@@ -66,15 +66,6 @@ def has_object_permission(self, request, view, obj):
         return authorization.can_contribute
 
 
-class RepositoryExampleEntityPermission(permissions.BasePermission):
-    def has_object_permission(self, request, view, obj):
-        authorization = obj.repository_example.repository_update.repository \
-            .get_user_authorization(request.user)
-        if request.method in READ_METHODS:
-            return authorization.can_read
-        return authorization.can_contribute
-
-
 class RepositoryTranslatedExamplePermission(permissions.BasePermission):
     def has_object_permission(self, request, view, obj):
         repository = obj.original_example.repository_update.repository
@@ -130,8 +121,7 @@ def filter_repository_uuid(self, queryset, name, value):
             authorization = repository.get_user_authorization(request.user)
             if not authorization.can_read:
                 raise PermissionDenied()
-            return queryset.filter(
-                repository_update__repository=repository)
+            return repository.examples(queryset=queryset)
         except Repository.DoesNotExist:
             raise NotFound(
                 _('Repository {} does not exist').format(value))
diff --git a/bothub/common/migrations/0004_auto_20180514_1129.py b/bothub/common/migrations/0004_auto_20180514_1129.py
new file mode 100644
--- /dev/null
+++ b/bothub/common/migrations/0004_auto_20180514_1129.py
@@ -0,0 +1,17 @@
+# Generated by Django 2.0.2 on 2018-05-14 11:29
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('common', '0003_auto_20180503_1223'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='repositoryexample',
+            options={'ordering': ['-created_at'], 'verbose_name': 'repository example', 'verbose_name_plural': 'repository examples'},
+        ),
+    ]
diff --git a/bothub/common/models.py b/bothub/common/models.py
--- a/bothub/common/models.py
+++ b/bothub/common/models.py
@@ -102,8 +102,10 @@ def languages_status(self):
                 languages.SUPPORTED_LANGUAGES,
             ))
 
-    def examples(self, language=None, deleted=True):
-        query = RepositoryExample.objects.filter(
+    def examples(self, language=None, deleted=True, queryset=None):
+        if queryset is None:
+            queryset = RepositoryExample.objects
+        query = queryset.filter(
             repository_update__repository=self)
         if language:
             query = query.filter(
@@ -267,6 +269,7 @@ class RepositoryExample(models.Model):
     class Meta:
         verbose_name = _('repository example')
         verbose_name_plural = _('repository examples')
+        ordering = ['-created_at']
 
     repository_update = models.ForeignKey(
         RepositoryUpdate,


Test patch:
diff --git a/bothub/api/tests/example.py b/bothub/api/tests/example.py
--- a/bothub/api/tests/example.py
+++ b/bothub/api/tests/example.py
@@ -8,6 +8,7 @@
 from bothub.common import languages
 from bothub.common.models import Repository
 from bothub.common.models import RepositoryExample
+from bothub.common.models import RepositoryExampleEntity
 
 from ..views import NewRepositoryExampleViewSet
 from ..views import RepositoryExampleViewSet
@@ -34,7 +35,8 @@ def request(self, token, data):
         }
         request = self.factory.post(
             '/api/example/new/',
-            data,
+            json.dumps(data),
+            content_type='application/json',
             **authorization_header)
         response = NewRepositoryExampleViewSet.as_view(
             {'post': 'create'})(request)
@@ -48,9 +50,10 @@ def test_okay(self):
         response, content_data = self.request(
             self.owner_token,
             {
-                'repository': self.repository.uuid,
+                'repository': str(self.repository.uuid),
                 'text': text,
                 'intent': intent,
+                'entities': [],
             })
         self.assertEqual(
             response.status_code,
@@ -66,9 +69,10 @@ def test_forbidden(self):
         response, content_data = self.request(
             self.user_token,
             {
-                'repository': self.repository.uuid,
+                'repository': str(self.repository.uuid),
                 'text': 'hi',
                 'intent': 'greet',
+                'entities': [],
             })
         self.assertEqual(
             response.status_code,
@@ -80,6 +84,7 @@ def test_repository_uuid_required(self):
             {
                 'text': 'hi',
                 'intent': 'greet',
+                'entities': [],
             })
         self.assertEqual(
             response.status_code,
@@ -89,9 +94,10 @@ def test_repository_does_not_exists(self):
         response, content_data = self.request(
             self.owner_token,
             {
-                'repository': uuid.uuid4(),
+                'repository': str(uuid.uuid4()),
                 'text': 'hi',
                 'intent': 'greet',
+                'entities': [],
             })
         self.assertEqual(
             response.status_code,
@@ -107,11 +113,34 @@ def test_invalid_repository_uuid(self):
                 'repository': 'invalid',
                 'text': 'hi',
                 'intent': 'greet',
+                'entities': [],
             })
         self.assertEqual(
             response.status_code,
             status.HTTP_400_BAD_REQUEST)
 
+    def test_with_entities(self):
+        response, content_data = self.request(
+            self.owner_token,
+            {
+                'repository': str(self.repository.uuid),
+                'text': 'my name is douglas',
+                'intent': 'greet',
+                'entities': [
+                    {
+                        'start': 11,
+                        'end': 18,
+                        'entity': 'name',
+                    },
+                ],
+            })
+        self.assertEqual(
+            response.status_code,
+            status.HTTP_201_CREATED)
+        self.assertEqual(
+            len(content_data.get('entities')),
+            1)
+
 
 class RepositoryExampleRetrieveTestCase(TestCase):
     def setUp(self):
@@ -127,7 +156,12 @@ def setUp(self):
             language=languages.LANGUAGE_EN)
         self.example = RepositoryExample.objects.create(
             repository_update=self.repository.current_update(),
-            text='hi')
+            text='my name is douglas')
+        RepositoryExampleEntity.objects.create(
+            repository_example=self.example,
+            start=11,
+            end=18,
+            entity='name')
 
         self.private_repository = Repository.objects.create(
             owner=self.owner,
@@ -182,6 +216,17 @@ def test_public(self):
             content_data.get('id'),
             self.example.id)
 
+    def test_list_entities(self):
+        response, content_data = self.request(
+            self.example,
+            self.owner_token)
+        self.assertEqual(
+            response.status_code,
+            status.HTTP_200_OK)
+        self.assertEqual(
+            len(content_data.get('entities')),
+            1)
+
 
 class RepositoryExampleDestroyTestCase(TestCase):
     def setUp(self):
diff --git a/bothub/api/tests/examples.py b/bothub/api/tests/examples.py
--- a/bothub/api/tests/examples.py
+++ b/bothub/api/tests/examples.py
@@ -33,6 +33,10 @@ def setUp(self):
             original_example=self.example,
             text='oi',
             language=languages.LANGUAGE_PT)
+        self.deleted = RepositoryExample.objects.create(
+            repository_update=self.repository.current_update(),
+            text='hey')
+        self.deleted.delete()
 
         self.private_repository = Repository.objects.create(
             owner=self.owner,
@@ -161,3 +165,15 @@ def test_forbidden(self):
         self.assertEqual(
             response.status_code,
             status.HTTP_403_FORBIDDEN)
+
+    def test_dont_list_deleted(self):
+        response, content_data = self.request(
+            {
+                'repository_uuid': self.repository.uuid,
+            },
+            self.owner_token)
+        self.assertEqual(
+            response.status_code,
+            status.HTTP_200_OK)
+        for repository in content_data.get('results'):
+            self.failIf(self.deleted.id == repository.get('id'))