diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 98a0715a4..fb8c28396 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -15,6 +15,7 @@ django-extensions==2.1.4 django-image-cropping==1.2 django-webpack-loader==0.6.0 drf-yasg==1.20.0 +django-ratelimit==3.0.1 easy-thumbnails==2.5 python-decouple==3.1 psycopg2-binary==2.8.6 diff --git a/sapl/base/urls.py b/sapl/base/urls.py index b85c55a44..058264049 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -14,7 +14,7 @@ from sapl.settings import MEDIA_URL, LOGOUT_REDIRECT_URL from .apps import AppConfig from .forms import LoginForm -from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, +from .views import (LoginSapl, AlterarSenha, AppConfigCrud, CasaLegislativaCrud, HelpTopicView, LogotipoView, RelatorioAtasView, RelatorioAudienciaView, RelatorioDataFimPrazoTramitacaoView, RelatorioHistoricoTramitacaoView, RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAutorView, @@ -173,8 +173,7 @@ urlpatterns = [ (TemplateView.as_view(template_name='sistema.html')), name='sistema'), - url(r'^login/$', views.LoginView.as_view(template_name='base/login.html', authentication_form=LoginForm), - name='login'), + url(r'^login/$', LoginSapl.as_view(), name='login'), url(r'^logout/$', views.LogoutView.as_view(), {'next_page': LOGOUT_REDIRECT_URL}, name='logout'), diff --git a/sapl/base/views.py b/sapl/base/views.py index 447509882..6af082741 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -6,7 +6,7 @@ import logging import os from django.contrib import messages -from django.contrib.auth import get_user_model +from django.contrib.auth import get_user_model, views from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.models import Group from django.contrib.auth.tokens import default_token_generator @@ -23,6 +23,7 @@ from django.template import TemplateDoesNotExist from django.template.loader import get_template from django.urls import reverse, reverse_lazy from django.utils import timezone +from django.utils.decorators import method_decorator from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode from django.utils.translation import ugettext_lazy as _ @@ -32,11 +33,12 @@ from django_filters.views import FilterView from haystack.query import SearchQuerySet from haystack.views import SearchView +from ratelimit.decorators import ratelimit from sapl import settings from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica from sapl.base.forms import (AutorForm, TipoAutorForm, AutorFilterSet, RecuperarSenhaForm, NovaSenhaForm, UserAdminForm, - OperadorAutorForm) + OperadorAutorForm, LoginForm) from sapl.base.models import Autor, TipoAutor, OperadorAutor from sapl.comissoes.models import Comissao, Reuniao from sapl.crud.base import CrudAux, make_pagination, Crud,\ @@ -62,7 +64,7 @@ from sapl.settings import EMAIL_SEND_USER from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured, parlamentares_ativos, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo, google_recaptcha_configured, sapl_as_sapn, - groups_remove_user, groups_add_user) + groups_remove_user, groups_add_user, get_client_ip) from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet, @@ -86,6 +88,15 @@ class IndexView(TemplateView): return TemplateView.get(self, request, *args, **kwargs) +@method_decorator(ratelimit(key=lambda group, request: get_client_ip(request), + rate='20/m', + method=ratelimit.UNSAFE, + block=True), name='dispatch') +class LoginSapl(views.LoginView): + template_name = 'base/login.html' + authentication_form = LoginForm + + class ConfirmarEmailView(TemplateView): template_name = "email/confirma.html"