From a9fdd3e654b713c17fb3f88281ca2a402908ed74 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 15 Nov 2019 22:36:35 -0400 Subject: [PATCH 1/5] Make the statistics slug field unique Signed-off-by: Roberto Rosario --- HISTORY.rst | 1 + .../migrations/0002_auto_20191116_0236.py | 20 +++++++++++++++++++ mayan/apps/mayan_statistics/models.py | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py diff --git a/HISTORY.rst b/HISTORY.rst index 144f1a5c31..6d13f506ae 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -8,6 +8,7 @@ - Move the file patching code from the Dependency class to a generalized utility of the storages app. - Add book link to the documentation. +- Make the statistics slug field unique. 3.2.10 (2019-11-19) =================== diff --git a/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py b/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py new file mode 100644 index 0000000000..132fb0f448 --- /dev/null +++ b/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.25 on 2019-11-16 02:36 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mayan_statistics', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='statisticresult', + name='slug', + field=models.SlugField(unique=True, verbose_name='Slug'), + ), + ] diff --git a/mayan/apps/mayan_statistics/models.py b/mayan/apps/mayan_statistics/models.py index 92b913efad..c84dc2790e 100644 --- a/mayan/apps/mayan_statistics/models.py +++ b/mayan/apps/mayan_statistics/models.py @@ -11,7 +11,7 @@ from django.utils.translation import ugettext_lazy as _ class StatisticResult(models.Model): # Translators: 'Slug' refers to the URL valid ID of the statistic # More info: https://docs.djangoproject.com/en/1.7/glossary/#term-slug - slug = models.SlugField(verbose_name=_('Slug')) + slug = models.SlugField(unique=True, verbose_name=_('Slug')) datetime = models.DateTimeField( auto_now=True, verbose_name=_('Date time') ) From 88ab66749e427a4a9e0af37151b5c3f1995be652 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 15 Nov 2019 22:42:11 -0400 Subject: [PATCH 2/5] Self-heal statistics results model Happens when multiple results are created using the same slug value. Forum topic 1404. Signed-off-by: Roberto Rosario --- HISTORY.rst | 3 +++ mayan/apps/mayan_statistics/classes.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 6d13f506ae..18f024ff03 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -9,6 +9,9 @@ generalized utility of the storages app. - Add book link to the documentation. - Make the statistics slug field unique. +- Self-heal statistics results model when multiple + results are created using the same slug value. + Forum topic 1404. 3.2.10 (2019-11-19) =================== diff --git a/mayan/apps/mayan_statistics/classes.py b/mayan/apps/mayan_statistics/classes.py index e4296d095f..ff0c93c896 100644 --- a/mayan/apps/mayan_statistics/classes.py +++ b/mayan/apps/mayan_statistics/classes.py @@ -158,6 +158,11 @@ class Statistic(object): return StatisticResult.objects.get(slug=self.slug) except StatisticResult.DoesNotExist: return StatisticResult.objects.none() + except StatisticResult.MultipleObjectsReturned: + # This should not happen. Self-heal by deleting the duplicate + # results. + StatisticResult.objects.filter(slug=self.slug).delete() + return StatisticResult.objects.none() def get_results_data(self): results = self.get_results() From 6d942272247d60146a472e923228d7234e157d2f Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 22 Nov 2019 21:23:35 -0400 Subject: [PATCH 3/5] Update statistics migration to rename duplicates Signed-off-by: Roberto Rosario --- HISTORY.rst | 2 ++ .../migrations/0002_auto_20191116_0236.py | 28 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 18f024ff03..73b9b0f627 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -12,6 +12,8 @@ - Self-heal statistics results model when multiple results are created using the same slug value. Forum topic 1404. +- Update mayan_statistics migration 0002 to rename + duplicate slugs. 3.2.10 (2019-11-19) =================== diff --git a/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py b/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py index 132fb0f448..7970a2f630 100644 --- a/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py +++ b/mayan/apps/mayan_statistics/migrations/0002_auto_20191116_0236.py @@ -1,10 +1,30 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.25 on 2019-11-16 02:36 from __future__ import unicode_literals from django.db import migrations, models +def operation_rename_duplicates(apps, schema_editor): + StatisticResult = apps.get_model( + app_label='mayan_statistics', model_name='StatisticResult' + ) + slugs = [] + + for entry in StatisticResult.objects.using(schema_editor.connection.alias).all(): + if entry.slug in slugs: + counter = 1 + while(True): + attempt = '{}_{}'.format(entry.slug, counter) + if attempt not in slugs: + break + else: + counter = counter + 1 + + entry.slug = attempt + entry.save() + + slugs.append(entry.slug) + + class Migration(migrations.Migration): dependencies = [ @@ -12,6 +32,10 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RunPython( + code=operation_rename_duplicates, + reverse_code=migrations.RunPython.noop + ), migrations.AlterField( model_name='statisticresult', name='slug', From 6687b1e61eca5830a2aab025edfe562109703db7 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 27 Nov 2019 03:51:12 -0400 Subject: [PATCH 4/5] Fix reverse inheritance permissions Signed-off-by: Roberto Rosario --- HISTORY.rst | 1 + mayan/apps/acls/classes.py | 18 ++++++++- mayan/apps/acls/tests/test_views.py | 22 ++++++----- mayan/apps/documents/apps.py | 10 +---- .../apps/documents/tests/test_permissions.py | 38 +++++++++++++++++++ 5 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 mayan/apps/documents/tests/test_permissions.py diff --git a/HISTORY.rst b/HISTORY.rst index 73b9b0f627..64d9dcbda5 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,6 +14,7 @@ Forum topic 1404. - Update mayan_statistics migration 0002 to rename duplicate slugs. +- Fix reverse inheritance permissions. 3.2.10 (2019-11-19) =================== diff --git a/mayan/apps/acls/classes.py b/mayan/apps/acls/classes.py index 1c06e0d05e..e3c6f40748 100644 --- a/mayan/apps/acls/classes.py +++ b/mayan/apps/acls/classes.py @@ -6,12 +6,15 @@ import logging from django.apps import apps from django.utils.encoding import force_text +from mayan.apps.common.utils import get_related_field + logger = logging.getLogger(__name__) class ModelPermission(object): _functions = {} _inheritances = {} + _inheritances_reverse = {} _registry = {} @classmethod @@ -69,7 +72,14 @@ class ModelPermission(object): return results else: - return cls._registry.get(klass, ()) + # Return the permissions for the klass and the models that + # inherit from it. + result = [] + result.extend(cls._registry.get(klass, ())) + for model in cls._inheritances_reverse.get(klass, ()): + result.extend(cls._registry.get(model, ())) + + return result @classmethod def get_for_instance(cls, instance): @@ -103,4 +113,10 @@ class ModelPermission(object): @classmethod def register_inheritance(cls, model, related): + model_reverse = get_related_field( + model=model, related_field_name=related + ).related_model + cls._inheritances_reverse.setdefault(model_reverse, []) + cls._inheritances_reverse[model_reverse].append(model) + cls._inheritances[model] = related diff --git a/mayan/apps/acls/tests/test_views.py b/mayan/apps/acls/tests/test_views.py index e338a99109..66bdbdc03e 100644 --- a/mayan/apps/acls/tests/test_views.py +++ b/mayan/apps/acls/tests/test_views.py @@ -8,7 +8,7 @@ from ..permissions import permission_acl_edit, permission_acl_view from .mixins import ACLTestMixin -class AccessControlListViewTestCase(ACLTestMixin, GenericViewTestCase): +class AccessControlListViewTestMixin(object): def _request_test_acl_create_get_view(self): return self.get( viewname='acls:acl_create', @@ -17,6 +17,18 @@ class AccessControlListViewTestCase(ACLTestMixin, GenericViewTestCase): } ) + def _request_test_acl_create_post_view(self): + return self.post( + viewname='acls:acl_create', + kwargs=self.test_content_object_view_kwargs, data={ + 'role': self.test_role.pk + } + ) + + +class AccessControlListViewTestCase( + AccessControlListViewTestMixin, ACLTestMixin, GenericViewTestCase +): def test_acl_create_get_view_no_permission(self): self._setup_test_object() @@ -40,14 +52,6 @@ class AccessControlListViewTestCase(ACLTestMixin, GenericViewTestCase): self.assertEqual(AccessControlList.objects.count(), acl_count) - def _request_test_acl_create_post_view(self): - return self.post( - viewname='acls:acl_create', - kwargs=self.test_content_object_view_kwargs, data={ - 'role': self.test_role.pk - } - ) - def test_acl_create_view_post_no_permission(self): self._setup_test_object() diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py index d0443f1578..238eda888e 100644 --- a/mayan/apps/documents/apps.py +++ b/mayan/apps/documents/apps.py @@ -199,15 +199,7 @@ class DocumentsApp(MayanAppConfig): permission_document_create, permission_document_type_delete, permission_document_type_edit, permission_document_type_view, permission_acl_edit, permission_acl_view, - permission_document_delete, permission_document_download, - permission_document_edit, permission_document_new_version, - permission_document_print, permission_document_properties_edit, - permission_document_restore, permission_document_trash, - permission_document_version_revert, - permission_document_version_view, permission_document_view, - permission_events_view, permission_transformation_create, - permission_transformation_delete, - permission_transformation_edit, permission_transformation_view, + permission_events_view, ) ) diff --git a/mayan/apps/documents/tests/test_permissions.py b/mayan/apps/documents/tests/test_permissions.py new file mode 100644 index 0000000000..be38906523 --- /dev/null +++ b/mayan/apps/documents/tests/test_permissions.py @@ -0,0 +1,38 @@ +from __future__ import unicode_literals + +from mayan.apps.acls.classes import ModelPermission +from mayan.apps.acls.permissions import permission_acl_edit +from mayan.apps.acls.tests.mixins import ACLTestMixin +from mayan.apps.common.tests import BaseTestCase + +from ..models import DocumentType +from ..permissions import permission_document_view + +from .base import GenericDocumentViewTestCase + + +class DocumentTypeACLPermissionsTestCase(BaseTestCase): + def test_document_type_permission_test(self): + result = ModelPermission.get_for_class(klass=DocumentType) + self.assertTrue(permission_document_view in result) + + +class DocumentTypeACLPermissionsViewTestCase( + ACLTestMixin, GenericDocumentViewTestCase +): + auto_upload_document = False + + def test_document_type_acl_permission_view_test(self): + self.test_object = self.test_document_type + self._create_test_acl() + self.grant_access( + obj=self.test_object, permission=permission_acl_edit + ) + + response = self.get( + viewname='acls:acl_permissions', kwargs={'pk': self.test_acl.pk} + ) + self.assertContains( + response=response, text=permission_document_view.label, + status_code=200 + ) From 620c23a92ed45e0818be3ecf2775950b898c8a11 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 27 Nov 2019 03:54:43 -0400 Subject: [PATCH 5/5] Remove circular index create ACL permission Signed-off-by: Roberto Rosario --- HISTORY.rst | 2 ++ mayan/apps/document_indexing/apps.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 64d9dcbda5..b6fed37bee 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -15,6 +15,8 @@ - Update mayan_statistics migration 0002 to rename duplicate slugs. - Fix reverse inheritance permissions. +- Remove index create permission as an ACL permission + for indexes. 3.2.10 (2019-11-19) =================== diff --git a/mayan/apps/document_indexing/apps.py b/mayan/apps/document_indexing/apps.py index c28f567daf..4e37aa99a2 100644 --- a/mayan/apps/document_indexing/apps.py +++ b/mayan/apps/document_indexing/apps.py @@ -85,7 +85,6 @@ class DocumentIndexingApp(MayanAppConfig): ModelPermission.register( model=Index, permissions=( permission_acl_edit, permission_acl_view, - permission_document_indexing_create, permission_document_indexing_delete, permission_document_indexing_edit, permission_document_indexing_instance_view,