diff --git a/sapl/api/views_materia.py b/sapl/api/views_materia.py index d37658afa..0d5356b0b 100644 --- a/sapl/api/views_materia.py +++ b/sapl/api/views_materia.py @@ -8,7 +8,7 @@ customize, wrapper_queryset_response_for_drf_action from sapl.api.permissions import SaplModelPermissions from sapl.materia.models import TipoMateriaLegislativa, Tramitacao,\ - MateriaLegislativa, Proposicao + MateriaLegislativa, Proposicao, DocumentoAcessorio ApiViewSetConstrutor.build_class( @@ -111,6 +111,19 @@ def anexadas(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) + +@customize(DocumentoAcessorio) +class _DocumentoAcessorioViewSet: + + def get_queryset(self): + user = self.request.user + qs = super().get_queryset() + + if user.is_anonymous or 'materia.change_documentoacessorio' not in user.get_all_permissions(): + qs = qs.exclude(restrito=True) + return qs + + @customize(TipoMateriaLegislativa) class _TipoMateriaLegislativaViewSet: diff --git a/sapl/api/views_protocoloadm.py b/sapl/api/views_protocoloadm.py index 5ebe77ec1..30d033ecf 100644 --- a/sapl/api/views_protocoloadm.py +++ b/sapl/api/views_protocoloadm.py @@ -60,9 +60,12 @@ class _DocumentoAcessorioAdministrativoViewSet: def get_queryset(self): qs = super().get_queryset() + user = self.request.user - if self.request.user.is_anonymous: + if user.is_anonymous or 'protocoloadm.change_documentoacessorioadministrativo' not in user.get_all_permissions(): +# if self.request.user.is_anonymous: qs = qs.exclude(documento__restrito=True) + qs = qs.exclude(restrito=True) return qs diff --git a/sapl/materia/forms.py b/sapl/materia/forms.py index b1219d56c..ee6433521 100644 --- a/sapl/materia/forms.py +++ b/sapl/materia/forms.py @@ -330,11 +330,17 @@ def __init__(self, *args, **kwargs): class DocumentoAcessorioForm(FileFieldCheckMixin, ModelForm): data = forms.DateField(required=True) + restrito = forms.ChoiceField( + label=_('Documento Restrito?'), + widget=forms.RadioSelect(), + choices=YES_NO_CHOICES, + initial=False) class Meta: model = DocumentoAcessorio fields = ['tipo', 'nome', 'data', 'autor', - 'ementa', 'indexacao', 'arquivo'] + 'ementa', 'indexacao', 'arquivo', + 'restrito', 'justificativa_restricao'] def clean(self): super(DocumentoAcessorioForm, self).clean() diff --git a/sapl/materia/migrations/0082_auto_20220929_1450.py b/sapl/materia/migrations/0082_auto_20220929_1450.py new file mode 100644 index 000000000..fc613db59 --- /dev/null +++ b/sapl/materia/migrations/0082_auto_20220929_1450.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.28 on 2022-09-29 17:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0081_auto_20220321_0934'), + ] + + operations = [ + migrations.AddField( + model_name='documentoacessorio', + name='justificativa_restricao', + field=models.TextField(blank=True, verbose_name='Justificativa de Restrição'), + ), + migrations.AddField( + model_name='documentoacessorio', + name='restrito', + field=models.BooleanField(blank=True, default=False, verbose_name='Restrito'), + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index 4c4109354..700cd35a5 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -554,6 +554,11 @@ class DocumentoAcessorio(models.Model): proposicao = GenericRelation('Proposicao', related_query_name='proposicao') data_ultima_atualizacao = models.DateTimeField( blank=True, null=True, auto_now=True, verbose_name=_('Data')) + restrito = models.BooleanField(default=False, + verbose_name=_('Restrito'), + blank=True) + justificativa_restricao = models.TextField( + blank=True, verbose_name=_('Justificativa de Restrição')) class Meta: verbose_name = _('Documento Acessório') diff --git a/sapl/materia/views.py b/sapl/materia/views.py index 755fe2f1e..108ad4224 100644 --- a/sapl/materia/views.py +++ b/sapl/materia/views.py @@ -1591,6 +1591,46 @@ def get_context_data(self, **kwargs): context = super(UpdateView, self).get_context_data(**kwargs) return context + class ListView(MasterDetailCrud.ListView): + + def get_queryset(self): + qs = super(MasterDetailCrud.ListView, self).get_queryset() + kwargs = {self.crud.parent_field: self.kwargs['pk']} + exibir_restritos = 'materia.change_documentoacessorio' in self.request.user.get_all_permissions() + if 'o' in self.request.GET: + o = self.request.GET['o'] + indice_field = abs(int(o)) - 1 + if '-' in o: + order_by = '-' + self.list_field_names[indice_field] + else: + order_by = self.list_field_names[indice_field] + if exibir_restritos: + return qs.filter(**kwargs).order_by(order_by, '-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', order_by, '-data', '-id') + + if exibir_restritos: + return qs.filter(**kwargs).order_by('-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', '-data', '-id') + + class DetailView(MasterDetailCrud.DetailView): + layout_key = 'DocumentoAcessorioAdministrativo' + template_name = "materia/documentoacessorio_detail.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['AppConfig'] = sapl.base.models.AppConfig.objects.all().last() + context['user'] = self.request.user + + doc = DocumentoAcessorio.objects.get( + pk=self.kwargs['pk'] + ) + context['object'] = doc + if doc.restrito and not 'materia.change_documentoacessorio' in self.request.user.get_all_permissions(): + context['title'] = 'Documento Restrito' + return context + class AutoriaCrud(MasterDetailCrud): model = Autoria @@ -2872,13 +2912,15 @@ def form_valid(self, form): return fv -def create_zip_docacessorios(materia): +def create_zip_docacessorios(materia, excluir_restritos): """ Creates in memory zip files """ logger = logging.getLogger(__name__) docs = materia.documentoacessorio_set. \ all().values_list('arquivo', flat=True) + if excluir_restritos: + docs = docs.filter(restrito=False) if not docs: return None, None @@ -2908,10 +2950,14 @@ def create_zip_docacessorios(materia): def get_zip_docacessorios(request, pk): logger = logging.getLogger(__name__) username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username + if request.user.is_anonymous or not 'protocoloadm.change_documentoacessorioadministrativo' in request.user.get_all_permissions(): + excluir_restritos = True + else: + excluir_restritos = False materia = get_object_or_404(MateriaLegislativa, pk=pk) data = None try: - external_name, data = create_zip_docacessorios(materia) + external_name, data = create_zip_docacessorios(materia, excluir_restritos) logger.info( "user= {}. Gerou o zip compilado de documento acessorios".format(username)) except FileNotFoundError: @@ -2940,13 +2986,15 @@ def get_zip_docacessorios(request, pk): return response -def create_pdf_docacessorios(materia): +def create_pdf_docacessorios(materia,excluir_restritos): """ Creates a unified in memory PDF file """ logger = logging.getLogger(__name__) docs = materia.documentoacessorio_set. \ all().values_list('arquivo', flat=True) + if excluir_restritos: + docs = docs.filter(restrito=False) if not docs: return None, None @@ -2981,8 +3029,12 @@ def get_pdf_docacessorios(request, pk): materia = get_object_or_404(MateriaLegislativa, pk=pk) logger = logging.getLogger(__name__) username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username + if request.user.is_anonymous or not 'protocoloadm.change_documentoacessorioadministrativo' in request.user.get_all_permissions(): + excluir_restritos = True + else: + excluir_restritos = False try: - external_name, data = create_pdf_docacessorios(materia) + external_name, data = create_pdf_docacessorios(materia, excluir_restritos) logger.info( "user= {}. Gerou o pdf compilado de documento acessorios".format(username)) except FileNotFoundError: diff --git a/sapl/protocoloadm/forms.py b/sapl/protocoloadm/forms.py index 58223f21c..076884efa 100644 --- a/sapl/protocoloadm/forms.py +++ b/sapl/protocoloadm/forms.py @@ -623,14 +623,22 @@ def __init__(self, *args, **kwargs): class DocumentoAcessorioAdministrativoForm(FileFieldCheckMixin, ModelForm): + restrito = forms.ChoiceField( + label=_('Documento Restrito?'), + widget=forms.RadioSelect(), + choices=YES_NO_CHOICES, + initial=False) + class Meta: model = DocumentoAcessorioAdministrativo fields = ['tipo', 'nome', + 'restrito', 'data', 'autor', 'arquivo', - 'assunto'] + 'assunto', + 'justificativa_restricao'] widgets = { 'data': forms.DateInput(format='%d/%m/%Y') diff --git a/sapl/protocoloadm/migrations/0044_auto_20220923_0946.py b/sapl/protocoloadm/migrations/0044_auto_20220923_0946.py new file mode 100644 index 000000000..75ad59f00 --- /dev/null +++ b/sapl/protocoloadm/migrations/0044_auto_20220923_0946.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.28 on 2022-09-23 12:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('protocoloadm', '0043_auto_20220919_1705'), + ] + + operations = [ + migrations.AddField( + model_name='documentoacessorioadministrativo', + name='justificativa_restricao', + field=models.TextField(blank=True, verbose_name='Justificativa de Restrição'), + ), + migrations.AddField( + model_name='documentoacessorioadministrativo', + name='restrito', + field=models.BooleanField(blank=True, default=False, verbose_name='Restrito'), + ), + ] diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 3cdf32735..96735d774 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -362,6 +362,11 @@ class DocumentoAcessorioAdministrativo(models.Model): assunto = models.TextField( blank=True, verbose_name=_('Assunto')) indexacao = models.TextField(blank=True) + restrito = models.BooleanField(default=False, + verbose_name=_('Restrito'), + blank=True) + justificativa_restricao = models.TextField( + blank=True, verbose_name=_('Justificativa de Restrição')) class Meta: verbose_name = _('Documento Acessório') diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py index 38ffcf42a..bfc697c79 100755 --- a/sapl/protocoloadm/views.py +++ b/sapl/protocoloadm/views.py @@ -398,10 +398,15 @@ def get_success_url(self): class DocumentoAdministrativoMixin: def has_permission(self): + + if self.model == DocumentoAcessorioAdministrativo and 'docadm/' + self.kwargs['pk'] in str(self.request): + doc_adm = DocumentoAdministrativo.objects.get(id=self.kwargs['pk']) + if doc_adm.restrito and not 'protocoloadm.change_documentoacessorioadministrativo' in self.request.user.get_all_permissions(): + return False + app_config = AppConfig.objects.last() if app_config and app_config.documentos_administrativos == 'O': return True - return super().has_permission() @@ -1459,15 +1464,51 @@ class UpdateView(MasterDetailCrud.UpdateView): form_class = DocumentoAcessorioAdministrativoForm class ListView(DocumentoAdministrativoMixin, MasterDetailCrud.ListView): + template_name = "protocoloadm/documentoacessorioadministrativo_list.html" def get_queryset(self): qs = super(MasterDetailCrud.ListView, self).get_queryset() kwargs = {self.crud.parent_field: self.kwargs['pk']} - return qs.filter(**kwargs).order_by('-data', '-id') + exibir_restritos = 'protocoloadm.change_documentoacessorioadministrativo' in self.request.user.get_all_permissions() + if 'o' in self.request.GET: + o = self.request.GET['o'] + indice_field = abs(int(o)) - 1 + if '-' in o: + order_by = '-' + self.list_field_names[indice_field] + else: + order_by = self.list_field_names[indice_field] + if exibir_restritos: + return qs.filter(**kwargs).order_by(order_by, '-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', order_by, '-data', '-id') + + if exibir_restritos: + return qs.filter(**kwargs).order_by('-data', '-id') + else: + return qs.filter(**kwargs).order_by('restrito', '-data', '-id') + class DetailView(DocumentoAdministrativoMixin, MasterDetailCrud.DetailView): - pass + layout_key = 'DocumentoAcessorioAdministrativo' + template_name = "protocoloadm/documentoacessorioadministrativo_detail.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['AppConfig'] = sapl.base.models.AppConfig.objects.all().last() + context['user'] = self.request.user + doc_acessorio = DocumentoAcessorioAdministrativo.objects.get( + pk=self.kwargs['pk']) + doc_adm = DocumentoAdministrativo.objects.get( + id=doc_acessorio.documento_id) + if not doc_adm.restrito: + context['doc_adm_restrito'] = False + context['object'] = doc_acessorio + else: + context['doc_adm_restrito'] = True + if (doc_adm.restrito or doc_acessorio.restrito) and not 'protocoloadm.change_documentoacessorioadministrativo' in self.request.user.get_all_permissions(): + context['title'] = 'Documento Restrito' + return context def atualizar_numero_documento(request): diff --git a/sapl/templates/materia/documentoacessorio_detail.html b/sapl/templates/materia/documentoacessorio_detail.html new file mode 100644 index 000000000..1a20cc1cc --- /dev/null +++ b/sapl/templates/materia/documentoacessorio_detail.html @@ -0,0 +1,84 @@ +{% extends "crud/detail_detail.html" %} +{% load i18n common_tags %} +{% load tz %} + +{% block detail_content %} + + {% if not object.restrito or 'materia.change_documentoacessorio' in user.get_all_permissions %} +
{%field_verbose_name object 'tipo'%}
+{%field_verbose_name object 'autor'%}
+{%field_verbose_name object 'nome'%}
+{%field_verbose_name object 'data'%}
+{%field_verbose_name object 'arquivo'%}
+{%field_verbose_name object 'restrito'%}
+{%field_verbose_name object 'justificativa_restricao'%}
+{{ NO_ENTRIES_MSG }}
+ {% else %} ++ {% if view.ordered_list %} + + {{ name }} + {% if 'o' in request.GET or not view.ordering %} + {% if 'o' not in request.GET and forloop.counter == 1 or 'o' in request.GET and forloop.counter|safe == request.GET.o %} + + {% elif 'o' in request.GET and forloop.counter == request.GET.o|str2intabs %} + + {% endif %} + {% endif %} + + {% else %} + {{ name }} + {% endif %} + | + {% endfor %} +|||||||||
---|---|---|---|---|---|---|---|---|---|
+ {{ doc.nome }} + | ++ {{ doc.tipo }} + | ++ {% if doc.data %}{{ doc.data }}{% endif %} + | ++ {% if doc.autor %}{{ doc.autor }}{% endif %} + | ++ {% if doc.arquivo %}Ver arquivo{% endif %} + | + {% else %} ++ Documento Restrito{{ doc.justificativa_restricao|safe }} + | + {% endif %} +
{%field_verbose_name object 'tipo'%}
+{%field_verbose_name object 'autor'%}
+{%field_verbose_name object 'nome'%}
+{%field_verbose_name object 'data'%}
+{%field_verbose_name object 'arquivo'%}
+{%field_verbose_name object 'assunto'%}
+{%field_verbose_name object 'restrito'%}
+{%field_verbose_name object 'justificativa_restricao'%}
+{{ NO_ENTRIES_MSG }}
+ {% else %} ++ {% if view.ordered_list %} + + {{ name }} + {% if 'o' in request.GET or not view.ordering %} + {% if 'o' not in request.GET and forloop.counter == 1 or 'o' in request.GET and forloop.counter|safe == request.GET.o %} + + {% elif 'o' in request.GET and forloop.counter == request.GET.o|str2intabs %} + + {% endif %} + {% endif %} + + {% else %} + {{ name }} + {% endif %} + | + {% endfor %} +|||||||||
---|---|---|---|---|---|---|---|---|---|
+ {{ doc.nome }} + | ++ {{ doc.tipo }} + | ++ {% if doc.data %}{{ doc.data }}{% endif %} + | ++ {% if doc.autor %}{{ doc.autor }}{% endif %} + | ++ {% if doc.assunto %}{{ doc.assunto }}{% endif %} + | + {% else %} ++ Documento Restrito{{ doc.justificativa_restricao|safe }} + | + {% endif %} +