diff --git a/mayan/apps/common/classes.py b/mayan/apps/common/classes.py index ffd4b9e626..f8958a304e 100644 --- a/mayan/apps/common/classes.py +++ b/mayan/apps/common/classes.py @@ -301,7 +301,9 @@ class Template(object): self.__class__._registry[name] = self def get_absolute_url(self): - return reverse('rest_api:template-detail', args=(self.name,)) + return reverse( + viewname='rest_api:template-detail', kwargs={'template_pk': self.name} + ) def render(self, request): context = { diff --git a/mayan/apps/common/forms.py b/mayan/apps/common/forms.py index d7cba8309e..fc8146ebac 100644 --- a/mayan/apps/common/forms.py +++ b/mayan/apps/common/forms.py @@ -9,6 +9,8 @@ from django.db import models from django.utils.module_loading import import_string from django.utils.translation import ugettext_lazy as _ +from mayan.apps.acls.models import AccessControlList + from .classes import Package from .models import UserLocaleProfile from .utils import resolve_attribute @@ -134,12 +136,20 @@ class FilteredSelectionForm(forms.Form): Form to select the from a list of choice filtered by access. Can be configure to allow single or multiple selection. """ + _field_name = None + _label = None + _help_text = None + _permission = None + _queryset = None + _widget_class = None + _widget_attributes = None + def __init__(self, *args, **kwargs): - field_name = kwargs.pop('field_name', None) - label = kwargs.pop('label', None) - help_text = kwargs.pop('help_text', None) - permission = kwargs.pop('permission', None) - queryset = kwargs.pop('queryset', None) + field_name = self._field_name or kwargs.pop('field_name', None) + label = self._label or kwargs.pop('label', None) + help_text = self._help_text or kwargs.pop('help_text', None) + permission = self._permission or kwargs.pop('permission', None) + queryset = self.get_queryset() or kwargs.pop('queryset', None) if queryset is None: model = kwargs.pop('model', None) @@ -150,12 +160,19 @@ class FilteredSelectionForm(forms.Form): queryset = model.objects.all() - user = kwargs.pop('user', None) - widget_class = kwargs.pop('widget_class', None) - widget_attributes = kwargs.pop('widget_attributes', {'size': '10'}) + user = self.get_user() or kwargs.pop('user', None) + widget_class = self._widget_class or kwargs.pop('widget_class', None) + widget_attributes = self._widget_attributes or kwargs.pop( + 'widget_attributes', {'size': '10'} + ) if not widget_class: - if kwargs.pop('allow_multiple', False): + if self._allow_multiple is not None: + allow_multiple = self._allow_multiple + else: + allow_multiple = self.kwargs.pop('allow_multiple', False) + + if allow_multiple: extra_kwargs = {} field_class = forms.ModelMultipleChoiceField widget_class = forms.widgets.SelectMultiple @@ -177,6 +194,12 @@ class FilteredSelectionForm(forms.Form): widget=widget_class(attrs=widget_attributes), **extra_kwargs ) + def get_queryset(self): + return self._queryset + + def get_user(self): + return None + class LicenseForm(FileDisplayForm): DIRECTORY = () diff --git a/mayan/apps/common/mixins.py b/mayan/apps/common/mixins.py index b0f258840b..103dc36dbe 100644 --- a/mayan/apps/common/mixins.py +++ b/mayan/apps/common/mixins.py @@ -46,7 +46,7 @@ class DeleteExtraDataMixin(object): else: self.object.delete() - return HttpResponseRedirect(success_url) + return HttpResponseRedirect(redirect_to=success_url) class DynamicFormViewMixin(object): @@ -179,9 +179,9 @@ class MultipleInstanceActionMixin(object): def get_success_message(self, count): return ungettext( - self.success_message, - self.success_message_plural, - count + singular=self.success_message, + plural=self.success_message_plural, + number=count ) % { 'count': count, } @@ -197,11 +197,11 @@ class MultipleInstanceActionMixin(object): count += 1 messages.success( - self.request, - self.get_success_message(count=count) + request=self.request, + message=self.get_success_message(count=count) ) - return HttpResponseRedirect(self.get_success_url()) + return HttpResponseRedirect(redirect_to=self.get_success_url()) class MultipleObjectMixin(object): @@ -278,9 +278,9 @@ class ObjectActionMixin(object): def get_success_message(self, count): return ungettext( - self.success_message, - self.success_message_plural, - count + singular=self.success_message, + plural=self.success_message_plural, + number=count ) % { 'count': count, } @@ -299,14 +299,15 @@ class ObjectActionMixin(object): pass except ActionError: messages.error( - self.request, self.error_message % {'instance': instance} + request=self.request, + message=self.error_message % {'instance': instance} ) else: self.action_count += 1 messages.success( - self.request, - self.get_success_message(count=self.action_count) + request=self.request, + message=self.get_success_message(count=self.action_count) ) @@ -321,17 +322,20 @@ class ObjectListPermissionFilterMixin(object): def dispatch(self, request, *args, **kwargs): if self.access_object_retrieve_method and self.object_permission: AccessControlList.objects.check_access( - permissions=(self.object_permission,), user=request.user, - obj=getattr(self, self.access_object_retrieve_method)() + obj=getattr(self, self.access_object_retrieve_method)(), + permissions=(self.object_permission,), user=request.user ) - return super(ObjectListPermissionFilterMixin, self).dispatch(request, *args, **kwargs) + return super(ObjectListPermissionFilterMixin, self).dispatch( + request, *args, **kwargs + ) def get_queryset(self): queryset = super(ObjectListPermissionFilterMixin, self).get_queryset() if not self.access_object_retrieve_method and self.object_permission: return AccessControlList.objects.filter_by_access( - self.object_permission, self.request.user, queryset=queryset + obj=self.object_permission, queryset=queryset, + user=self.request.user ) else: return queryset @@ -368,9 +372,10 @@ class ObjectPermissionCheckMixin(object): if self.object_permission: try: AccessControlList.objects.check_access( - permissions=self.object_permission, user=request.user, obj=self.get_permission_object(), - related=getattr(self, 'object_permission_related', None) + permissions=self.object_permission, + related=getattr(self, 'object_permission_related', None), + user=request.user ) except PermissionDenied: if self.object_permission_raise_404: @@ -437,8 +442,8 @@ class ViewPermissionCheckMixin(object): def dispatch(self, request, *args, **kwargs): if self.view_permission: Permission.check_permissions( - requester=self.request.user, - permissions=(self.view_permission,) + permissions=(self.view_permission,), + requester=self.request.user ) return super( diff --git a/mayan/apps/common/models.py b/mayan/apps/common/models.py index 7d8fc62a18..148c3b1c98 100644 --- a/mayan/apps/common/models.py +++ b/mayan/apps/common/models.py @@ -18,6 +18,7 @@ from .storages import storage_sharedupload logger = logging.getLogger(__name__) +#TODO: move outside of models.py def upload_to(instance, filename): return 'shared-file-{}'.format(uuid.uuid4().hex) diff --git a/mayan/apps/common/paginator.py b/mayan/apps/common/paginator.py index e5545fcf91..7a7adcd931 100644 --- a/mayan/apps/common/paginator.py +++ b/mayan/apps/common/paginator.py @@ -48,8 +48,8 @@ class PurePaginator(Paginator): self.allow_empty_first_page = allow_empty_first_page self.object_list = object_list self.orphans = orphans - self.per_page = per_page self.page_kwarg = page_kwarg + self.per_page = per_page self.request = request def page(self, number): diff --git a/mayan/apps/common/permissions_runtime.py b/mayan/apps/common/permissions_runtime.py index 9dc4e4797e..20df80407a 100644 --- a/mayan/apps/common/permissions_runtime.py +++ b/mayan/apps/common/permissions_runtime.py @@ -7,5 +7,5 @@ from mayan.apps.permissions import PermissionNamespace namespace = PermissionNamespace(label=_('Common'), name='common') permission_error_log_view = namespace.add_permission( - name='error_log_view', label=_('View error log') + label=_('View error log'), name='error_log_view' ) diff --git a/mayan/apps/common/queues.py b/mayan/apps/common/queues.py index bf649abb48..01569efe9e 100644 --- a/mayan/apps/common/queues.py +++ b/mayan/apps/common/queues.py @@ -5,13 +5,13 @@ from django.utils.translation import ugettext_lazy as _ from mayan.apps.task_manager.classes import CeleryQueue queue_default = CeleryQueue( - name='default', label=_('Default'), is_default_queue=True + is_default_queue=True, label=_('Default'), name='default' ) -queue_tools = CeleryQueue(name='tools', label=_('Tools')) +queue_tools = CeleryQueue(label=_('Tools'), name='tools') queue_common_periodic = CeleryQueue( - name='common_periodic', label=_('Common periodic'), transient=True + label=_('Common periodic'), name='common_periodic', transient=True ) queue_common_periodic.add_task_type( - name='mayan.apps.common.tasks.task_delete_stale_uploads', - label=_('Delete stale uploads') + label=_('Delete stale uploads'), + name='mayan.apps.common.tasks.task_delete_stale_uploads' ) diff --git a/mayan/apps/common/settings.py b/mayan/apps/common/settings.py index 2206192210..c97dbd07fa 100644 --- a/mayan/apps/common/settings.py +++ b/mayan/apps/common/settings.py @@ -11,7 +11,7 @@ from mayan.apps.smart_settings import Namespace from .literals import DEFAULT_COMMON_HOME_VIEW -namespace = Namespace(name='common', label=_('Common')) +namespace = Namespace(label=_('Common'), name='common') setting_auto_logging = namespace.add_setting( global_name='COMMON_AUTO_LOGGING', @@ -86,7 +86,7 @@ setting_temporary_directory = namespace.add_setting( is_path=True ) -namespace = Namespace(name='django', label=_('Django')) +namespace = Namespace(label=_('Django'), name='django') setting_django_allowed_hosts = namespace.add_setting( global_name='ALLOWED_HOSTS', default=settings.ALLOWED_HOSTS, @@ -402,7 +402,7 @@ setting_django_wsgi_application = namespace.add_setting( ), ) -namespace = Namespace(name='celery', label=_('Celery')) +namespace = Namespace(label=_('Celery'), name='celery') setting_celery_always_eager = namespace.add_setting( global_name='CELERY_TASK_ALWAYS_EAGER', diff --git a/mayan/apps/common/tests/base.py b/mayan/apps/common/tests/base.py index f87649500b..81c97bed83 100644 --- a/mayan/apps/common/tests/base.py +++ b/mayan/apps/common/tests/base.py @@ -37,9 +37,7 @@ class BaseTestCase(DatabaseConversionMixin, ACLBaseTestMixin, ContentTypeCheckMi class GenericViewTestCase(BaseTestCase): - def setUp(self): - super(GenericViewTestCase, self).setUp() - self.has_test_view = False + has_test_view = False def tearDown(self): from mayan.urls import urlpatterns @@ -87,13 +85,10 @@ class GenericViewTestCase(BaseTestCase): path=path, data=data, follow=follow ) - def login(self, username, password): - logged_in = self.client.login(username=username, password=password) + def login(self, *args, **kwargs): + logged_in = self.client.login(*args, **kwargs) - user = get_user_model().objects.get(username=username) - - self.assertTrue(logged_in) - self.assertTrue(user.is_authenticated) + return logged_in def login_user(self): self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) diff --git a/mayan/apps/common/tests/test_api.py b/mayan/apps/common/tests/test_api.py index 2302c62a64..a0111db300 100644 --- a/mayan/apps/common/tests/test_api.py +++ b/mayan/apps/common/tests/test_api.py @@ -12,7 +12,7 @@ TEST_TEMPLATE_RESULT = '[-\w]+)/(?P[-\w]+)/(?P\d+)/errors/$', - ObjectErrorLogEntryListView.as_view(), name='object_error_list' + regex=r'^objects/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/errors/$', + name='object_error_list', view=ObjectErrorLogEntryListView.as_view() ), url( - r'^object/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/errors/clear/$', - ObjectErrorLogEntryListClearView.as_view(), - name='object_error_list_clear' + regex=r'^objects/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/errors/clear/$', + name='object_error_list_clear', + view=ObjectErrorLogEntryListClearView.as_view() ), ] urlpatterns += [ url( - r'^favicon\.ico$', FaviconRedirectView.as_view() + regex=r'^favicon\.ico$', view=FaviconRedirectView.as_view() ), url( - r'^jsi18n/(?P\S+?)/$', javascript_catalog, - name='javascript_catalog' + regex=r'^jsi18n/(?P\S+?)/$', name='javascript_catalog', + view=javascript_catalog ), url( - r'^set_language/$', set_language, name='set_language' + regex=r'^set_language/$', name='set_language', view=set_language ), ] api_urls = [ url( - r'^content_types/$', APIContentTypeList.as_view(), - name='content-type-list' + regex=r'^content_types/$', name='content-type-list', + view=APIContentTypeList.as_view() ), url( - r'^templates/$', APITemplateListView.as_view(), - name='template-list' + regex=r'^templates/$', name='template-list', + view=APITemplateListView.as_view() ), url( - r'^templates/(?P[-\w]+)/$', APITemplateView.as_view(), - name='template-detail' + regex=r'^templates/(?P[-\w]+)/$', name='template-detail', + view=APITemplateView.as_view() ), ] diff --git a/mayan/apps/common/views.py b/mayan/apps/common/views.py index db0319c234..8bdc694e66 100644 --- a/mayan/apps/common/views.py +++ b/mayan/apps/common/views.py @@ -15,6 +15,9 @@ from django.utils.translation import ugettext_lazy as _ from django.views.generic import RedirectView, TemplateView from mayan.apps.acls.models import AccessControlList +from mayan.apps.common.mixins import ( + ContentTypeViewMixin, ExternalObjectViewMixin +) from .exceptions import NotLatestVersion, UnknownLatestVersion from .forms import ( @@ -171,7 +174,9 @@ class ObjectErrorLogEntryListClearView(ConfirmView): ) -class ObjectErrorLogEntryListView(SingleObjectListView): +class ObjectErrorLogEntryListView(ContentTypeViewMixin, ExternalObjectViewMixin, SingleObjectListView): + #TODO: Update for MERC 6. Return 404. + """ def dispatch(self, request, *args, **kwargs): AccessControlList.objects.check_access( obj=self.get_object(), permissions=permission_error_log_view, @@ -181,6 +186,7 @@ class ObjectErrorLogEntryListView(SingleObjectListView): return super(ObjectErrorLogEntryListView, self).dispatch( request, *args, **kwargs ) + """ def get_extra_context(self): return { @@ -202,6 +208,7 @@ class ObjectErrorLogEntryListView(SingleObjectListView): 'title': _('Error log entries for: %s' % self.get_object()), } + """ def get_object(self): content_type = get_object_or_404( klass=ContentType, app_label=self.kwargs['app_label'], @@ -211,9 +218,9 @@ class ObjectErrorLogEntryListView(SingleObjectListView): return get_object_or_404( klass=content_type.model_class(), pk=self.kwargs['object_id'] ) - + """ def get_object_list(self): - return self.get_object().error_logs.all() + return self.get_external_object().error_logs.all() class PackagesLicensesView(SimpleView):