diff --git a/sapl/base/media.py b/sapl/base/media.py index 3cbe758ae..639334a33 100644 --- a/sapl/base/media.py +++ b/sapl/base/media.py @@ -10,6 +10,9 @@ from sapl.materia.models import Proposicao, pode_ver_proposicao from sapl.protocoloadm.models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, pode_ver_documento_adm) +from sapl.sessao.models import (JustificativaAusencia, Orador, + OradorExpediente, OradorOrdemDia, + SessaoPlenaria, restringe_sessoes_visiveis) from sapl.utils import EXTENSOES_ATIVAS, tipo_ativo X_ACCEL_PREFIX = '/media-interna/' @@ -31,6 +34,28 @@ RESOLVEDORES = { } +# Arquivos gravados em sapl/public///..., que seguem a +# visibilidade da sessão plenária a que pertencem. +MODELOS_DE_SESSAO = {m._meta.model_name: m for m in ( + SessaoPlenaria, Orador, OradorExpediente, OradorOrdemDia, + JustificativaAusencia)} + + +def _de_sessao_oculta(request, partes): + model = MODELOS_DE_SESSAO.get(partes[2]) + if request.user.is_authenticated or not model or len(partes) < 5 or \ + partes[1] != 'public' or not partes[3].isdigit(): + return False + if model is SessaoPlenaria: + sessoes = SessaoPlenaria.objects.filter(pk=partes[3]) + else: + sessoes = SessaoPlenaria.objects.filter( + pk__in=model.objects.filter(pk=partes[3]).values( + 'sessao_plenaria_id')) + return sessoes.exists() and not restringe_sessoes_visiveis( + sessoes, request.user).exists() + + def _nome_protegido(request, path): """Devolve o nome do arquivo gravado no objeto dono, se o usuário puder vê-lo. O caminho servido vem do banco, nunca da URL.""" @@ -56,6 +81,9 @@ def media(request, path): protegido = path.startswith('sapl/private/') or bool( PROTEGIDO_RE.match(path)) nome = _nome_protegido(request, path) if protegido else path + + if len(partes) > 2 and _de_sessao_oculta(request, partes): + raise Http404 nome_arquivo = os.path.basename(nome) content_type = (mimetypes.guess_type(nome_arquivo)[0] or diff --git a/sapl/base/tests/test_media.py b/sapl/base/tests/test_media.py index fcdceeca9..4daaf8643 100644 --- a/sapl/base/tests/test_media.py +++ b/sapl/base/tests/test_media.py @@ -71,9 +71,10 @@ def _assert_servido(response, path): ('O', True, None, False), ('O', True, 'logado', True), ('R', False, None, False), - ('R', False, 'logado', True), + ('R', False, 'logado', False), ('R', True, None, False), - ('R', True, 'logado', True), + ('R', True, 'logado', False), + ('R', True, 'com_permissao', True), ]) def test_documento_administrativo(client, comportamento, restrito, perfil, pode_ver): @@ -82,6 +83,9 @@ def test_documento_administrativo(client, comportamento, restrito, perfil, texto_integral=DOC_PATH) if perfil == 'logado': _login(client, 'logado') + elif perfil == 'com_permissao': + _login(client, 'perm', + 'protocoloadm.detail_documentoadministrativo') response = _get(client, DOC_PATH) diff --git a/sapl/protocoloadm/models.py b/sapl/protocoloadm/models.py index 70341cb15..3cd034d1b 100644 --- a/sapl/protocoloadm/models.py +++ b/sapl/protocoloadm/models.py @@ -343,10 +343,10 @@ class DocumentoAdministrativo(models.Model): def pode_ver_documento_adm(user, documento): - if user.is_authenticated: - return True - return not documento.restrito and SaplAppConfig.attr( - 'documentos_administrativos') == DOC_ADM_OSTENSIVO + """Mesmas regras da página de detalhe do documento (CRUD).""" + 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): diff --git a/sapl/protocoloadm/tests/test_docadm_acesso.py b/sapl/protocoloadm/tests/test_docadm_acesso.py index df2ca07b0..602da119c 100644 --- a/sapl/protocoloadm/tests/test_docadm_acesso.py +++ b/sapl/protocoloadm/tests/test_docadm_acesso.py @@ -62,10 +62,10 @@ ACESSO = [ ('O', True, 'sem_permissao', True), ('O', True, 'com_permissao', True), ('R', False, 'anonimo', False), - ('R', False, 'sem_permissao', True), + ('R', False, 'sem_permissao', False), ('R', False, 'com_permissao', True), ('R', True, 'anonimo', False), - ('R', True, 'sem_permissao', True), + ('R', True, 'sem_permissao', False), ('R', True, 'com_permissao', True), ] diff --git a/sapl/sessao/tests/test_sessao_oculta_api.py b/sapl/sessao/tests/test_sessao_oculta_api.py index b915ce1d0..0ee143aef 100644 --- a/sapl/sessao/tests/test_sessao_oculta_api.py +++ b/sapl/sessao/tests/test_sessao_oculta_api.py @@ -70,9 +70,20 @@ def test_api_mostra_sessao_previa_ao_usuario_autenticado(client, sessoes): @pytest.mark.django_db(transaction=False) -def test_media_de_sessao_e_publica(client, settings, sessoes): +def test_media_de_sessao_oculta_do_anonimo(client, settings, sessoes): settings.DEBUG = False - for sessao in sessoes: - response = client.get( - '/media/sapl/public/sessaoplenaria/%s/pauta/p.pdf' % sessao.pk) - assert response.status_code == 200 + previa, iniciada = sessoes + orador_previa = Orador.objects.get(sessao_plenaria=previa) + orador_iniciada = Orador.objects.get(sessao_plenaria=iniciada) + + def get(path): + return client.get('/media/sapl/public/' + path).status_code + + assert get('sessaoplenaria/%s/pauta/p.pdf' % previa.pk) == 404 + assert get('sessaoplenaria/%s/pauta/p.pdf' % iniciada.pk) == 200 + assert get('orador/%s/anexo/a.pdf' % orador_previa.pk) == 404 + assert get('orador/%s/anexo/a.pdf' % orador_iniciada.pk) == 200 + + client.force_login(baker.make(get_user_model())) + assert get('sessaoplenaria/%s/pauta/p.pdf' % previa.pk) == 200 + assert get('orador/%s/anexo/a.pdf' % orador_previa.pk) == 200