From f64aa0010cced208568e3945b6dd3b196a5edc68 Mon Sep 17 00:00:00 2001 From: LeandroRoberto Date: Wed, 30 Nov 2016 16:20:28 -0200 Subject: [PATCH] =?UTF-8?q?Ref=20list=20de=20prop=20nao=20recebidas/n?= =?UTF-8?q?=C3=A3o=20incorp/incorp.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/crud/base.py | 14 ++++-- .../migrations/0071_auto_20161130_1001.py | 19 ++++++++ .../migrations/0072_auto_20161130_1618.py | 19 ++++++++ sapl/materia/models.py | 8 ++++ sapl/materia/views.py | 43 +++++++++++++++++-- sapl/rules/__init__.py | 15 +++++++ sapl/rules/map_rules.py | 20 +++------ .../materia/prop_devolvidas_list.html | 9 +--- sapl/templates/materia/proposicao_detail.html | 16 ++++--- 9 files changed, 128 insertions(+), 35 deletions(-) create mode 100644 sapl/materia/migrations/0071_auto_20161130_1001.py create mode 100644 sapl/materia/migrations/0072_auto_20161130_1618.py diff --git a/sapl/crud/base.py b/sapl/crud/base.py index cc84c7b4e..7c39850bf 100644 --- a/sapl/crud/base.py +++ b/sapl/crud/base.py @@ -180,7 +180,15 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin): perms = self.get_permission_required() # Torna a view pública se não possuir conteudo # no atributo permission_required - return self.request.user.has_perms(perms) if len(perms) else True + if not len(perms): + return True + + for perm in perms: + if self.request.user.has_perm(perm): + return True + return False + + # return self.request.user.has_perms(perms) if len(perms) else True def dispatch(self, request, *args, **kwargs): if not self.has_permission(): @@ -257,9 +265,7 @@ class CrudBaseMixin(CrispyLayoutFormMixin): self.permission_required = list( set(self.permission_required) - set(obj.public)) else: - obj.public = list( - set(self.permission_required) - - set((RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE))) + obj.public = [] self.permission_required = tuple(( self.permission(pr) for pr in self.permission_required)) diff --git a/sapl/materia/migrations/0071_auto_20161130_1001.py b/sapl/materia/migrations/0071_auto_20161130_1001.py new file mode 100644 index 000000000..c1b688121 --- /dev/null +++ b/sapl/materia/migrations/0071_auto_20161130_1001.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.11 on 2016-11-30 10:01 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0070_auto_20161111_1301'), + ] + + operations = [ + migrations.AlterModelOptions( + name='proposicao', + options={'permissions': (('detail_proposicao_enviada', 'Pode acessar detalhes de uma proposição enviada.'), ('detail_proposicao_devolvida', 'Pode acessar detalhes de uma proposição devolvida.')), 'verbose_name': 'Proposição', 'verbose_name_plural': 'Proposições'}, + ), + ] diff --git a/sapl/materia/migrations/0072_auto_20161130_1618.py b/sapl/materia/migrations/0072_auto_20161130_1618.py new file mode 100644 index 000000000..da265d3ff --- /dev/null +++ b/sapl/materia/migrations/0072_auto_20161130_1618.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.11 on 2016-11-30 16:18 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0071_auto_20161130_1001'), + ] + + operations = [ + migrations.AlterModelOptions( + name='proposicao', + options={'permissions': (('detail_proposicao_enviada', 'Pode acessar detalhes de uma proposição enviada.'), ('detail_proposicao_devolvida', 'Pode acessar detalhes de uma proposição devolvida.'), ('detail_proposicao_incorporada', 'Pode acessar detalhes de uma proposição incorporada.')), 'verbose_name': 'Proposição', 'verbose_name_plural': 'Proposições'}, + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 26937e6a4..8bdd6eecb 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -598,6 +598,14 @@ class Proposicao(models.Model): verbose_name = _('Proposição') verbose_name_plural = _('Proposições') unique_together = (('content_type', 'object_id'), ) + permissions = ( + ('detail_proposicao_enviada', + _('Pode acessar detalhes de uma proposição enviada.')), + ('detail_proposicao_devolvida', + _('Pode acessar detalhes de uma proposição devolvida.')), + ('detail_proposicao_incorporada', + _('Pode acessar detalhes de uma proposição incorporada.')), + ) def __str__(self): return '%s %s/%s' % (Proposicao._meta.verbose_name, diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 16770ac91..28d97884b 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -251,7 +251,7 @@ class ProposicaoDevolvida(PermissionRequiredMixin, ListView): model = Proposicao ordering = ['data_envio'] paginate_by = 10 - permission_required = ('materia.list_proposicao', ) + permission_required = ('materia.detail_proposicao_devolvida', ) def get_queryset(self): return Proposicao.objects.filter( @@ -275,7 +275,7 @@ class ProposicaoPendente(PermissionRequiredMixin, ListView): model = Proposicao ordering = ['data_envio', 'autor', 'tipo', 'descricao'] paginate_by = 10 - permission_required = ('materia.list_proposicao', ) + permission_required = ('materia.detail_proposicao_enviada', ) def get_queryset(self): return Proposicao.objects.filter( @@ -300,7 +300,7 @@ class ProposicaoRecebida(PermissionRequiredMixin, ListView): model = Proposicao ordering = ['data_envio'] paginate_by = 10 - permission_required = ('materia.list_proposicao', ) + permission_required = 'materia.detail_proposicao_incorporada' def get_queryset(self): return Proposicao.objects.filter( @@ -472,10 +472,16 @@ class ProposicaoCrud(Crud): class DetailView(Crud.DetailView): layout_key = 'Proposicao' + permission_required = (RP_DETAIL, 'materia.detail_proposicao_enviada', + 'materia.detail_proposicao_devolvida', + 'materia.detail_proposicao_incorporada') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['subnav_template_name'] = '' + + context['title'] = '%s (%s)' % ( + self.object, self.object.autor) return context def get(self, request, *args, **kwargs): @@ -535,6 +541,37 @@ class ProposicaoCrud(Crud): return redirect(reverse('sapl.materia:proposicao_detail', kwargs={'pk': kwargs['pk']})) + def dispatch(self, request, *args, **kwargs): + + try: + p = Proposicao.objects.get(id=kwargs['pk']) + except: + raise Http404() + + if not self.has_permission(): + return self.handle_no_permission() + + if p.autor.user != request.user: + if not p.data_envio and not p.data_devolucao: + raise Http404() + + if p.data_devolucao and not request.user.has_perm( + 'materia.detail_proposicao_devolvida'): + raise Http404() + + if p.data_envio and not p.data_recebimento\ + and not request.user.has_perm( + 'materia.detail_proposicao_enviada'): + raise Http404() + + if p.data_envio and p.data_recebimento\ + and not request.user.has_perm( + 'materia.detail_proposicao_incorporada'): + raise Http404() + + return super(PermissionRequiredMixin, self).dispatch( + request, *args, **kwargs) + class DeleteView(BaseLocalMixin, Crud.DeleteView): def _action_is_valid(self, request, *args, **kwargs): diff --git a/sapl/rules/__init__.py b/sapl/rules/__init__.py index 407b77ba1..6c5987c64 100644 --- a/sapl/rules/__init__.py +++ b/sapl/rules/__init__.py @@ -2,6 +2,21 @@ from django.utils.translation import ugettext_lazy as _ default_app_config = 'sapl.rules.apps.AppConfig' +""" +Os cinco radicais de permissão completa são: + + RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ + '.list_', '.detail_', '.add_', '.change_', '.delete_', + +Tanto a app crud quanto a app rules estão sempre ligadas a um model. Ao lidar +com permissões, sempre é analisado se é apenas um radical ou permissão +completa, sendo apenas um radical, a permissão completa é montada com base +no model associado. +""" + +RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ + '.list_', '.detail_', '.add_', '.change_', '.delete_', + SAPL_GROUP_ADMINISTRATIVO = _("Operador Administrativo") SAPL_GROUP_PROTOCOLO = _("Operador de Protocolo Administrativo") diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 6f9a4165f..f5565b372 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -12,7 +12,9 @@ from sapl.rules import (SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_ANONYMOUS, SAPL_GROUP_GERAL, SAPL_GROUP_LOGIN_SOCIAL, SAPL_GROUP_MATERIA, SAPL_GROUP_NORMA, SAPL_GROUP_PAINEL, SAPL_GROUP_PARLAMENTAR, - SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO) + SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO, + RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE) + from sapl.sessao import models as sessao """ @@ -42,20 +44,8 @@ arquivo (sapl.rules.map_rules.py) e criar os grupos definidos na regra de negócio trabalham com os cinco radiais de permissão e com qualquer outro tipo de permissão customizada, nesta ordem de precedência. -Os cinco radicais de permissão completa são: - - RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ - '.list_', '.detail_', '.add_', '.change_', '.delete_', - -Tanto a app crud quanto a app rules estão sempre ligadas a um model. Ao lidar -com permissões, sempre é analisado se é apenas um radical ou permissão -completa, sendo apenas um radical, a permissão completa é montada com base -no model associado. """ -RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ - '.list_', '.detail_', '.add_', '.change_', '.delete_', - __base__ = [RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE] __listdetailchange__ = [RP_LIST, RP_DETAIL, RP_CHANGE] @@ -83,7 +73,9 @@ rules_group_protocolo = { (materia.Anexada, __base__), (materia.Autoria, __base__), - (materia.Proposicao, __listdetailchange__), + (materia.Proposicao, ['detail_proposicao_enviada', + 'detail_proposicao_devolvida', + 'detail_proposicao_incorporada']), (compilacao.TextoArticulado, ['view_restricted_textoarticulado']) ] } diff --git a/sapl/templates/materia/prop_devolvidas_list.html b/sapl/templates/materia/prop_devolvidas_list.html index 153c7d778..79c9bd531 100644 --- a/sapl/templates/materia/prop_devolvidas_list.html +++ b/sapl/templates/materia/prop_devolvidas_list.html @@ -14,7 +14,7 @@ Tipo Descrição Autor - Vínculo + Motivo da Devolução @@ -24,12 +24,7 @@ {{ prop.tipo.descricao }} {{ prop.descricao }} {{ prop.autor }} - - {% if prop.materia_gerada %} - {{ prop.materia_gerada.tipo.sigla }} {{ prop.materia_gerada.numero }}/{{ prop.materia_gerada.ano }} - {% elif prop.documento_gerado %} - {{ prop.documento_gerado.materia.tipo.sigla }} {{ prop.documento_gerado.materia.numero }}/{{ prop.documento_gerado.materia.ano }} - {% endif %} + {{ prop.justificativa_devolucao}} {% endfor %} diff --git a/sapl/templates/materia/proposicao_detail.html b/sapl/templates/materia/proposicao_detail.html index 2a0f6e6de..61669d168 100644 --- a/sapl/templates/materia/proposicao_detail.html +++ b/sapl/templates/materia/proposicao_detail.html @@ -15,14 +15,16 @@ {% block editions %} {% if object.data_envio %} - {% block editions_actions_return %} -
- {% trans "Recibo de Envio" %} - {% if not object.data_recebimento %} - {% trans 'Retornar Proposição Enviada' %} - {% endif %} -
+ {% if user == object.autor.user %} + {% block editions_actions_return %} +
+ {% trans "Recibo de Envio" %} + {% if not object.data_recebimento %} + {% trans 'Retornar Proposição Enviada' %} + {% endif %} +
{% endblock %} + {% endif %} {% else %}