From 62f0bbd389136df77f9fa612ff4e671fb2880dae Mon Sep 17 00:00:00 2001 From: joao Date: Mon, 4 May 2026 17:38:10 -0400 Subject: [PATCH] =?UTF-8?q?Bloqueia=20/voto-individual/=20para=20usu=C3=A1?= =?UTF-8?q?rios=20sem=20Votante/can=5Fvote?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Antes, usuários autenticados sem registro de Votante ou sem a permissão parlamentares.can_vote recebiam HTTP 200 com um template de erro (e, antes do commit anterior, ainda traziam o JS de auto- reload). Agora a view exige as duas condições no início e retorna HTTP 403 caso falhe: - @permission_required('parlamentares.can_vote', raise_exception=True) garante a permissão (com raise_exception para 403 ao invés do redirect padrão pra LOGIN_URL). - Checagem inline de Votante.objects.filter(user=...).exists() pega o caso de superusers (que passam pelo bypass automático de permissões do Django mas não têm cadastro de Votante) e de qualquer custom group que conceda can_vote sem o cadastro. Mantém HTTP 200 com mensagem amigável para falhas de estado que um votante legítimo pode encontrar (nenhuma matéria aberta, parlamentar não presente na sessão). Co-Authored-By: Claude Opus 4.7 (1M context) --- sapl/painel/views.py | 44 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 8d8f2245b..d488294b2 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -3,8 +3,9 @@ import json import logging from django.contrib import messages -from django.contrib.auth.decorators import login_required, user_passes_test -from django.core.exceptions import ObjectDoesNotExist +from django.contrib.auth.decorators import (login_required, permission_required, + user_passes_test) +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.urls import reverse from django.db.models import Q from django.http import HttpResponse, JsonResponse @@ -200,39 +201,22 @@ def can_vote(context, context_vars, request): @login_required +@permission_required('parlamentares.can_vote', raise_exception=True) def votante_view(request): logger = logging.getLogger(__name__) - username = request.user.username if request.user.is_authenticated else 'AnonymousUser' - - # Pega o votante relacionado ao usuário - template_name = 'painel/voto_individual.html' - context = {} - context_vars = {} + username = request.user.username - try: - logger.debug(f'user={username}. Tentando obter objeto Votante com user={request.user}.') - if not request.user.is_anonymous and request.user.is_authenticated: - votante = Votante.objects.get(user=request.user) - else: - raise ObjectDoesNotExist - except ObjectDoesNotExist: - logger.error(f"user={username}. Usuário (user={request.user}) não cadastrado como votante na tela de parlamentares. " - "Contate a administração de sua Casa Legislativa!") - msg = _("Usuário não cadastrado como votante na tela de parlamentares. Contate a administração de sua Casa Legislativa!") - context.update({'error_message': msg}) - - return render(request, template_name, context) - context_vars = {'votante': votante} + if not Votante.objects.filter(user=request.user).exists(): + logger.warning( + f'user={username} sem cadastro de Votante tentou acessar /voto-individual/.' + ) + raise PermissionDenied + + template_name = 'painel/voto_individual.html' context = {'head_title': str(_('Votação Individual'))} + context_vars = {'votante': Votante.objects.get(user=request.user)} - # Verifica se usuário possui permissão para votar - if 'parlamentares.can_vote' in request.user.get_all_permissions(): - context, context_vars = can_vote(context, context_vars, request) - logger.debug("user=" + username + ". Verificando se usuário {} possui permissão para votar.".format(request.user)) - else: - logger.error("user=" + username + ". Usuário {} sem permissão para votar.".format(request.user)) - context.update({'permissao': False, - 'error_message': 'Usuário sem permissão para votar.'}) + context, context_vars = can_vote(context, context_vars, request) # Salva o voto if request.method == 'POST':