Browse Source

Verifica permissão de acesso em documentos administrativos

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pull/3865/head
Edward Ribeiro 3 weeks ago
parent
commit
4c2be22322
  1. 9
      sapl/protocoloadm/models.py
  2. 103
      sapl/protocoloadm/tests/test_docadm_acesso.py
  3. 16
      sapl/protocoloadm/views.py

9
sapl/protocoloadm/models.py

@ -6,7 +6,8 @@ from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
from sapl.base.models import Autor, AppConfig as SaplAppConfig
from sapl.base.models import Autor, AppConfig as SaplAppConfig, \
DOC_ADM_OSTENSIVO
from sapl.materia.models import TipoMateriaLegislativa, UnidadeTramitacao,\
MateriaLegislativa
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, texto_upload_path,
@ -341,6 +342,12 @@ class DocumentoAdministrativo(models.Model):
update_fields=update_fields)
def pode_ver_documento_adm(user, documento):
if SaplAppConfig.attr('documentos_administrativos') == DOC_ADM_OSTENSIVO:
return not (documento.restrito and user.is_anonymous)
return user.has_perm('protocoloadm.detail_documentoadministrativo')
class DocumentoAcessorioAdministrativo(models.Model):
documento = models.ForeignKey(DocumentoAdministrativo,
on_delete=models.PROTECT)

103
sapl/protocoloadm/tests/test_docadm_acesso.py

@ -0,0 +1,103 @@
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from model_bakery import baker
import pytest
from sapl.base.models import AppConfig
from sapl.protocoloadm.models import DocumentoAdministrativo
@pytest.fixture
def media_tmp(settings, tmp_path):
settings.MEDIA_ROOT = str(tmp_path)
return tmp_path
def _config(comportamento):
cache.clear()
AppConfig.objects.all().delete()
baker.make(AppConfig, documentos_administrativos=comportamento)
def _documento(restrito):
documento = baker.make(DocumentoAdministrativo, restrito=restrito)
documento.texto_integral = SimpleUploadedFile(
'texto.pdf', b'%PDF-1.4 conteudo', content_type='application/pdf')
documento.save()
return documento
def _client(client, perfil):
if perfil == 'anonimo':
return client
user = baker.make(get_user_model(), username=perfil)
if perfil == 'com_permissao':
ct = ContentType.objects.get_for_model(DocumentoAdministrativo)
perm, _ = Permission.objects.get_or_create(
codename='detail_documentoadministrativo', content_type=ct,
defaults={'name': 'detail'})
user.user_permissions.add(perm)
client.force_login(user)
return client
ACESSO = [
# (comportamento, restrito, perfil, pode_ver)
('O', False, 'anonimo', True),
('O', False, 'sem_permissao', True),
('O', False, 'com_permissao', True),
('O', True, 'anonimo', False),
('O', True, 'sem_permissao', True),
('O', True, 'com_permissao', True),
('R', False, 'anonimo', False),
('R', False, 'sem_permissao', False),
('R', False, 'com_permissao', True),
('R', True, 'anonimo', False),
('R', True, 'sem_permissao', False),
('R', True, 'com_permissao', True),
]
@pytest.mark.django_db(transaction=False)
@pytest.mark.parametrize('comportamento,restrito,perfil,pode_ver', ACESSO)
def test_doc_texto_integral_acesso(client, media_tmp, comportamento,
restrito, perfil, pode_ver):
_config(comportamento)
documento = _documento(restrito)
client = _client(client, perfil)
response = client.get(reverse('sapl.protocoloadm:doc_texto_integral',
kwargs={'pk': documento.pk}))
assert response.status_code == (200 if pode_ver else 404)
@pytest.mark.django_db(transaction=False)
@pytest.mark.parametrize('comportamento,restrito,perfil,pode_ver', ACESSO)
def test_pdf_docacessorios_acesso(client, media_tmp, comportamento,
restrito, perfil, pode_ver):
_config(comportamento)
documento = baker.make(DocumentoAdministrativo, restrito=restrito)
client = _client(client, perfil)
response = client.get(reverse('sapl.protocoloadm:merge_docacessorios',
kwargs={'pk': documento.pk}))
if pode_ver:
assert response.status_code != 404
else:
assert response.status_code == 404
@pytest.mark.django_db(transaction=False)
@pytest.mark.parametrize('url_name', ['doc_texto_integral',
'merge_docacessorios'])
def test_docadm_pk_inexistente(client, url_name):
_config('O')
response = client.get(reverse('sapl.protocoloadm:' + url_name,
kwargs={'pk': 999999}))
assert response.status_code == 404

16
sapl/protocoloadm/views.py

@ -42,7 +42,7 @@ from sapl.parlamentares.models import Legislatura, Parlamentar
from sapl.protocoloadm.forms import VinculoDocAdminMateriaForm,\
VinculoDocAdminMateriaEmLoteFilterSet
from sapl.protocoloadm.models import Protocolo, DocumentoAdministrativo,\
VinculoDocAdminMateria
VinculoDocAdminMateria, pode_ver_documento_adm
from sapl.relatorios.views import relatorio_doc_administrativos
from sapl.utils import (create_barcode, get_base_url, get_client_ip,
get_mime_type_from_file_extension, lista_anexados,
@ -101,15 +101,9 @@ def recuperar_materia_protocolo(request):
def doc_texto_integral(request, pk):
can_see = True
documento = get_object_or_404(DocumentoAdministrativo, pk=pk)
if not request.user.is_authenticated:
app_config = AppConfig.objects.last()
if app_config and app_config.documentos_administrativos == 'R':
can_see = False
if can_see:
documento = DocumentoAdministrativo.objects.get(pk=pk)
if pode_ver_documento_adm(request.user, documento):
if documento.texto_integral:
arquivo = documento.texto_integral
@ -127,6 +121,8 @@ def doc_texto_integral(request, pk):
def get_pdf_docacessorios(request, pk):
documento_administrativo = get_object_or_404(DocumentoAdministrativo, pk=pk)
if not pode_ver_documento_adm(request.user, documento_administrativo):
raise Http404
logger = logging.getLogger(__name__)
username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username
try:
@ -498,7 +494,7 @@ class DocumentoAdministrativoCrud(Crud):
def get(self, *args, **kwargs):
pk = self.kwargs['pk']
documento = DocumentoAdministrativo.objects.get(id=pk)
documento = get_object_or_404(DocumentoAdministrativo, pk=pk)
if documento.restrito and self.request.user.is_anonymous:
return redirect('/')
return super(Crud.DetailView, self).get(args, kwargs)

Loading…
Cancel
Save