Browse Source

Fix recibo proposição e adiciona rate limiter em matéria e norma

pull/3781/head
Edward Ribeiro 1 month ago
parent
commit
f92c461e58
  1. 7
      .dockerignore
  2. 2
      docker/config/nginx/sapl.conf
  3. 10
      docker/docker-compose.yaml
  4. 3
      docker/startup_scripts/gunicorn.conf.py
  5. 5
      docker/startup_scripts/start.sh
  6. 3
      requirements/requirements.txt
  7. 2
      sapl/base/views.py
  8. 9
      sapl/materia/views.py
  9. 7
      sapl/norma/views.py
  10. 5
      sapl/sessao/views.py
  11. 28
      sapl/utils.py
  12. 4
      scripts/gunicorn_start.sh

7
.dockerignore

@ -12,3 +12,10 @@ bower
.travis.yml
.env
.idea
.DS_Store
.coveragerc
*.swp
.coveragerc
.drone.yml
.github
release.sh

2
docker/config/nginx/sapl.conf

@ -7,7 +7,7 @@ upstream sapl_server {
server {
listen 80;
server_name sapl.test;
server_name sapl.prod;
client_max_body_size 4G;

10
docker/docker-compose.yaml

@ -33,11 +33,11 @@ services:
networks:
- sapl-net
sapl:
image: interlegis/sapl:3.1.164-RC3
# build:
# context: ../
# dockerfile: ./docker/Dockerfile
# container_name: sapl
# image: interlegis/sapl:3.1.164-RC3
build:
context: ../
dockerfile: ./docker/Dockerfile
container_name: sapl
labels:
NAME: "sapl"
restart: always

3
docker/startup_scripts/gunicorn.conf.py

@ -52,7 +52,8 @@ graceful_timeout = 30
keepalive = 10
backlog = 2048
max_requests = MAX_REQUESTS
max_requests_jitter = 100
max_requests_jitter = 200
worker_max_memory_per_child = 300 * 1024 * 1024 # 300 MB cap
# Environment (same as exporting before running)
raw_env = [

5
docker/startup_scripts/start.sh

@ -4,19 +4,16 @@ IFS=$'\n\t'
APP_DIR="/var/interlegis/sapl"
DATA_DIR="/var/interlegis/sapl/data"
MEDIA_DIR="/var/interlegis/sapl/media"
RUN_DIR="/var/interlegis/sapl/run"
ENV_FILE="$APP_DIR/.env"
SECRET_FILE="$DATA_DIR/secret.key"
chown -R root:nginx "$RUN_DIR" || true
chown -R root:nginx "$MEDIA_DIR" || true
chmod -R g+rwX "$RUN_DIR" || true
chmod -R g+rwX "$MEDIA_DIR" || true
# setgid bit on our writable trees (not data/)
find "$RUN_DIR" "$MEDIA_DIR" -type d -exec chmod g+s {} + 2>/dev/null || true
find "$RUN_DIR" -type d -exec chmod g+s {} + 2>/dev/null || true
log() { printf '[%s] %s\n' "$(date -Is)" "$*"; }
err() { printf '[%s] ERROR: %s\n' "$(date -Is)" "$*" >&2; }

3
requirements/requirements.txt

@ -22,8 +22,7 @@ pytz==2019.3
python-magic==0.4.15
unipath==1.1
Pillow==10.3.0
rlPyCairo==0.3.0
reportlab==4.2.0
reportlab==3.6.13
WeasyPrint==66
trml2pdf==0.6
gunicorn==23.0.0

2
sapl/base/views.py

@ -68,7 +68,7 @@ class IndexView(TemplateView):
@method_decorator(ratelimit(key=lambda group, request: get_client_ip(request),
rate='20/m',
rate='10/m',
method=ratelimit.UNSAFE,
block=True), name='dispatch')
class LoginSapl(views.LoginView):

9
sapl/materia/views.py

@ -24,7 +24,6 @@ from django.shortcuts import render
from django.template import loader
from django.urls import reverse
from django.utils import formats, timezone
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.views.generic import CreateView, ListView, TemplateView, UpdateView
from django.views.generic.base import RedirectView
@ -32,6 +31,9 @@ from django.views.generic.edit import FormView
from django_filters.views import FilterView
import weasyprint
from ratelimit.decorators import ratelimit
from django.utils.decorators import method_decorator
import sapl
from sapl.base.email_utils import do_envia_email_confirmacao
from sapl.base.models import Autor, CasaLegislativa, AppConfig as BaseAppConfig
@ -1459,6 +1461,7 @@ class TramitacaoCrud(MasterDetailCrud):
return initial
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class ListView(MasterDetailCrud.ListView):
def get_queryset(self):
@ -1531,6 +1534,7 @@ class TramitacaoCrud(MasterDetailCrud):
return HttpResponseRedirect(url)
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class DetailView(MasterDetailCrud.DetailView):
template_name = "materia/tramitacao_detail.html"
@ -1908,6 +1912,7 @@ class MateriaLegislativaCrud(Crud):
def get_success_url(self):
return self.search_url
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class DetailView(Crud.DetailView):
layout_key = 'MateriaLegislativaDetail'
@ -1920,6 +1925,7 @@ class MateriaLegislativaCrud(Crud):
pk=self.kwargs['pk'])
return context
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class ListView(Crud.ListView, RedirectView):
def get_redirect_url(self, *args, **kwargs):
@ -2040,6 +2046,7 @@ class AcompanhamentoExcluirView(TemplateView):
return HttpResponseRedirect(self.get_success_url())
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class MateriaLegislativaPesquisaView(MultiFormatOutputMixin, FilterView):
model = MateriaLegislativa
filterset_class = MateriaLegislativaFilterSet

7
sapl/norma/views.py

@ -19,6 +19,9 @@ from django.views.generic.edit import FormView
from django_filters.views import FilterView
import weasyprint
from ratelimit.decorators import ratelimit
from django.utils.decorators import method_decorator
from sapl import settings
import sapl
from sapl.base.models import AppConfig
@ -147,6 +150,7 @@ class NormaRelacionadaCrud(MasterDetailCrud):
layout_key = 'NormaRelacionadaDetail'
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class NormaPesquisaView(MultiFormatOutputMixin, FilterView):
model = NormaJuridica
filterset_class = NormaFilterSet
@ -232,6 +236,7 @@ class AnexoNormaJuridicaCrud(MasterDetailCrud):
initial['ano'] = self.object.ano
return initial
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class DetailView(MasterDetailCrud.DetailView):
form_class = AnexoNormaJuridicaForm
layout_key = 'AnexoNormaJuridica'
@ -280,6 +285,7 @@ class NormaCrud(Crud):
namespace = self.model._meta.app_config.name
return reverse('%s:%s' % (namespace, 'norma_pesquisa'))
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class DetailView(Crud.DetailView):
def get(self, request, *args, **kwargs):
estatisticas_acesso_normas = AppConfig.objects.first().estatisticas_acesso_normas
@ -337,6 +343,7 @@ class NormaCrud(Crud):
layout_key = 'NormaJuridicaCreate'
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class ListView(Crud.ListView):
def get(self, request, *args, **kwargs):

5
sapl/sessao/views.py

@ -28,6 +28,9 @@ from django.views.generic.edit import FormMixin
from django_filters.views import FilterView
import pytz
from ratelimit.decorators import ratelimit
from django.utils.decorators import method_decorator
from sapl.base.models import AppConfig as AppsAppConfig
from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
MasterDetailCrud,
@ -3794,6 +3797,7 @@ class SessaoListView(ListView):
return context
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class PautaSessaoView(TemplateView):
model = SessaoPlenaria
template_name = "sessao/pauta_inexistente.html"
@ -3809,6 +3813,7 @@ class PautaSessaoView(TemplateView):
reverse('sapl.sessao:pauta_sessao_detail', kwargs={'pk': sessao.pk}))
@method_decorator(ratelimit(key='ip', rate='10/m', block=True), name='dispatch')
class PautaSessaoDetailView(PautaMultiFormatOutputMixin, DetailView):
template_name = "sessao/pauta_sessao_detail.html"
model = SessaoPlenaria

28
sapl/utils.py

@ -419,21 +419,25 @@ def get_base_url(request):
return "{0}://{1}".format(protocol, current_domain)
def create_barcode(value, width=170, height=50):
'''
creates a base64 encoded barcode PNG image
'''
def create_barcode(value, width=170, height=50, dpi=72):
"""
creates a base64 encoded barcode PNG image
"""
from base64 import b64encode
from reportlab.graphics.barcode import createBarcodeDrawing
value_bytes = bytes(value, "ascii")
barcode = createBarcodeDrawing('Code128',
value=value_bytes,
barWidth=width,
height=height,
fontSize=2,
humanReadable=True)
data = b64encode(barcode.asString('png'))
return data.decode('utf-8')
barcode = createBarcodeDrawing(
'Code128',
value=value_bytes,
barWidth=width,
height=height,
fontSize=2,
humanReadable=True
)
# Lower DPI prevents Cairo surface from blowing up
png_bytes = barcode.asString("png", dpi=dpi)
return b64encode(png_bytes).decode("utf-8")
YES_NO_CHOICES = [(True, _('Sim')), (False, _('Não'))]

4
scripts/gunicorn_start.sh

@ -15,8 +15,8 @@ then
fi
NAME="SAPL" # Name of the application (*)
DJANGODIR=$SAPL_DIR/ # Django project directory (*)
SOCKFILE=$SAPL_DIR/run/gunicorn.sock # we will communicate using this unix socket (*)
DJANGODIR="$SAPL_DIR/" # Django project directory (*)
SOCKFILE="$SAPL_DIR/run/gunicorn.sock" # we will communicate using this unix socket (*)
USER=`whoami` # the user to run as (*)
GROUP=`whoami` # the group to run as (*)
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn (*)

Loading…
Cancel
Save