From d6616bccde07ad47ceae77f88a46a45506674ed2 Mon Sep 17 00:00:00 2001 From: eduardocalil Date: Wed, 11 May 2016 12:43:49 -0300 Subject: [PATCH] Fix #316 316 login simples (#328) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Inicia implementação do login simples * Cria o Login * Melhora a mensagem de erro no Login * Ajusta migração para novas mudanças das models Signed-off-by: Luciano Almeida * Concerta problema de duplicidade Signed-off-by: Luciano Almeida * Arruma conflito com master e traduz textos de info Signed-off-by: Luciano Almeida * Remove global e corrige alguns textos Signed-off-by: Luciano Almeida * Arruma exclusão de stubs desnecessários Signed-off-by: Luciano Almeida * Arruma problema de merge no makemigrations Signed-off-by: Luciano Almeida * Cria função para pegar fields_dict Signed-off-by: Luciano Almeida * Retira código desnecessário * Arruma exclusão de stubs desnecessários Signed-off-by: Luciano Almeida * Arruma problema de merge no makemigrations Signed-off-by: Luciano Almeida * Cria função para pegar fields_dict Signed-off-by: Luciano Almeida * Adiciona datas invalidas à model ProblemaMigracao Signed-off-by: Luciano Almeida * Arruma imports Signed-off-by: Luciano Almeida * Adiciona a ativação/desativação do virtualenv * Ajusta sugestões de correção do PR Signed-off-by: Luciano Almeida * Exclui arquivo de migrate pra resolver conflito Signed-off-by: Luciano Almeida * Concerta alguns problemas de model e admin Signed-off-by: Luciano Almeida * FIX: substitui null por '' ao limpar autor * Init crud legislação citada * Tests * Init crud legislacao * Init crud legislação citada * Valida legislação repetida * Valida legislação igual * Ajeita testes * Init Crud Tramitação * Valida ultima tramitação * Ordena tramitações * Teste delete * Termina validações para deletar uma tramitação * Fix testes * Fix #381 * Adiciona placeholder * Estruturar View e template de pendências. * Refat dos tipos de pendências e rend. dos vides * Alteração na reenderização da mensagem dos Vides. * Ajuste na integração com Compilação * Criar Filtro em Nível de Notificação de Pendências * Fix #398 * Faz o merge de migrations de materia * Fix #397 - Apresentar Filiação Partidária Atual * HOT FIX: filiação vem em ordem decrescente: first() ao invés de last() * Fix #407 * Adiciona o campo Natureza de Processo * Resolve alguns erros apontados pelo check_qa * Adiciona mais um 'guarda' pra preservar ordem decrescente de filiação * Init crud legislação citada * Comeca a implementacao do travis * Modifica o travis * Insere a verificacao com o Travis apos testes em um fork do sapl * Faz a integracao continua com o travis funcionar corretamente * Fix #355 crud relatoria * Init crud legislação citada * Init Crud Tramitação * Init crud relatoria * Disabilita localização atual * Valida localização atual * Fix qa e testes * Init crud documento acessório * Monta layout para autor * Adicona busca de autor na criação de documento acessório * Esconde campo não usado de autor * Define layout documento acessório * Ajusta botão de salvar e cancelar * Fix qa * Adiciona edição de documento acessório * Fix qa e testes * Init crud legislação citada * Init Crud Tramitação * Init crud relatoria * Fix qa e testes * Fix url * Adiciona campo de arquivo em Documento Acessório * Fix #391 refatora pesquisa doc adm django filter (#417) * Refatora a Pesquisa de Documento Adm * Finaliza a refatoracao da pesquisa por documento administrativo * Cria o botao de pesquisa por Documento Administrativo * Faz ir para o menu principal quando clica na logoda aplicacao * Arruma PEP8 * Arruma alguns detalhes * Faz modificacoes propostas pela issue 418 fix #418 * Fix #429 - ordem descrescente de mandato parlamentar (#437) * Ordena Mandato por data_inicio de Legislatura em ordem decrescente * Fix #402 - checagem de filiação partidária (#423) * Fix #402 - checagem de filiação partidária * WIP * WIP * WIP * WIP * Init crud legislação citada * Disabilita localização atual * Valida localização atual * Fix qa e testes * Init crud documento acessório * Monta layout para autor * Adicona busca de autor na criação de documento acessório * Esconde campo não usado de autor * Define layout documento acessório * Fix qa * Remove duplicidade do helper * Modifica row dos botões * Init crud relatoria * Disabilita localização atual * Valida localização atual * Init crud legislação citada * Init Crud Tramitação * Init crud relatoria * Fix qa e testes * Init crud documento acessório * Monta layout para autor * Adicona busca de autor na criação de documento acessório * Define layout documento acessório * Fix url * Adiciona campo de arquivo em Documento Acessório * Init crud proposicao * Muda url de proposição e valida tipo de proposicao para adição de matéria * Muda data inválida para elaboração * Ordena listagem pela data de envio * Valida se uma proposição está sendo enviada ou criada * Valida remoção ou retorno de proposição * Remove código desnecessário * Fix qa * Fix testes * Inicia implementação do login simples * Cria o Login * Melhora a mensagem de erro no Login * Faz algumas das mudancas apontadas na revisao * Tenta arrumar a quebra nos testes * Faz com que todos os testes passem * Muda detalhes na url do template --- base/forms.py | 12 +++++++ base/tests/test_login.py | 69 +++++++++++++++++++++++++++++++++++++ base/tests/teststub_urls.py | 10 ++++++ base/urls.py | 8 +++++ base/views.py | 2 +- protocoloadm/views.py | 2 +- sapl/settings.py | 2 ++ templates/base.html | 20 +++++++++++ templates/base/login.html | 68 ++++++++++++++++++++++++++++++++++++ 9 files changed, 191 insertions(+), 2 deletions(-) create mode 100755 base/tests/test_login.py create mode 100644 base/tests/teststub_urls.py create mode 100644 templates/base/login.html diff --git a/base/forms.py b/base/forms.py index 6b05ee59b..4d13f6adb 100644 --- a/base/forms.py +++ b/base/forms.py @@ -1,6 +1,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Fieldset, Layout from django import forms +from django.contrib.auth.forms import AuthenticationForm from django.core.exceptions import ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ @@ -109,3 +110,14 @@ class CasaLegislativaTabelaAuxForm(ModelForm): ) ) super(CasaLegislativaTabelaAuxForm, self).__init__(*args, **kwargs) + + +class LoginForm(AuthenticationForm): + username = forms.CharField(label="Username", max_length=30, + widget=forms.TextInput( + attrs={ + 'class': 'form-control', 'name': 'username'})) + password = forms.CharField(label="Password", max_length=30, + widget=forms.PasswordInput( + attrs={ + 'class': 'form-control', 'name': 'password'})) diff --git a/base/tests/test_login.py b/base/tests/test_login.py new file mode 100755 index 000000000..3fe9301dd --- /dev/null +++ b/base/tests/test_login.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +import pytest +from django.contrib.auth.models import User + +pytestmark = pytest.mark.django_db + + +@pytest.fixture +def user(): + return User.objects.create_user('jfirmino', password='123') + + +def test_login_aparece_na_barra_para_usuario_nao_logado(client): + response = client.get('/') + assert 'Login' in str(response.content) + + +def test_username_do_usuario_logado_aparece_na_barra(client, user): + assert client.login(username='jfirmino', password='123') + response = client.get('/') + assert 'Login' not in str(response.content) + assert 'jfirmino' in str(response.content) + assert 'Sair' in str(response.content) + + +def test_nome_completo_do_usuario_logado_aparece_na_barra(client, user): + # nome completo para o usuario + user.first_name = 'Joao' + user.last_name = 'Firmino' + user.save() + assert client.login(username='jfirmino', password='123') + response = client.get('/') + assert 'Login' not in str(response.content) + assert 'Joao Firmino' in str(response.content) + assert 'Sair' in str(response.content) + + +@pytest.mark.urls('base.tests.teststub_urls') +@pytest.mark.parametrize("link_login,destino", [ + # login redireciona para home + ('/login/', '/'), +]) +def test_login(app, user, link_login, destino): + pagina_login = app.get(link_login) + form = pagina_login.forms['login-form'] + form['username'] = 'jfirmino' + form['password'] = '123' + res = form.submit() # login + + assert str(user.pk) == app.session['_auth_user_id'] + assert res.url == destino + + +@pytest.mark.parametrize("link_logout,destino", [ + # logout redireciona para a pagina de login + ('/logout/', '/login/'), +]) +def test_logout(client, user, link_logout, destino): + # com um usuário logado ... + assert client.login(username='jfirmino', password='123') + assert str(user.pk) == client.session['_auth_user_id'] + + # ... acionamos o link de logout + res = client.get(link_logout, follow=True) + + destino_real = res.redirect_chain[-1][0] + + assert '_auth_user_id' not in client.session + assert destino_real == destino diff --git a/base/tests/teststub_urls.py b/base/tests/teststub_urls.py new file mode 100644 index 000000000..3a3410f98 --- /dev/null +++ b/base/tests/teststub_urls.py @@ -0,0 +1,10 @@ +from django.conf.urls import patterns, url +from django.views.generic.base import TemplateView + +from sapl.urls import urlpatterns as original_patterns + +urlpatterns = original_patterns + patterns('', url(r'^zzzz$', + TemplateView.as_view( + template_name='index.html'), + name='zzzz') + ) diff --git a/base/urls.py b/base/urls.py index 4ddb4532a..0a4caad73 100644 --- a/base/urls.py +++ b/base/urls.py @@ -1,12 +1,15 @@ from django.conf.urls import url +from django.contrib.auth import views from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.views.generic.base import TemplateView from .apps import AppConfig +from .forms import LoginForm from .views import CasaLegislativaTableAuxView, HelpView app_name = AppConfig.name + urlpatterns = [ url(r'^sistema/', TemplateView.as_view(template_name='sistema.html')), url(r'^ajuda/(?P\w+)$', HelpView.as_view(), name='help_topic'), @@ -14,6 +17,11 @@ urlpatterns = [ name='help_base'), url(r'^casa-legislativa$', CasaLegislativaTableAuxView.as_view(), name='casa_legislativa'), + + url(r'^login/$', views.login, { + 'template_name': 'base/login.html', 'authentication_form': LoginForm}, + name='login'), + url(r'^logout/$', views.logout, {'next_page': '/login'}, name='logout') ] # Fix a static asset finding error on Django 1.9 + gunicorn: diff --git a/base/views.py b/base/views.py index 1950ce99a..2e801a3c5 100644 --- a/base/views.py +++ b/base/views.py @@ -42,7 +42,7 @@ class CasaLegislativaTableAuxView(FormView): casa = CasaLegislativa.objects.first() if casa: if ("remover" in request.POST or - (form.cleaned_data['logotipo'] and casa.logotipo)): + (form.cleaned_data['logotipo'] and casa.logotipo)): try: os.unlink(casa.logotipo.path) except OSError: diff --git a/protocoloadm/views.py b/protocoloadm/views.py index 19e67e9ba..5f874ef78 100644 --- a/protocoloadm/views.py +++ b/protocoloadm/views.py @@ -4,7 +4,7 @@ from datetime import date, datetime from braces.views import FormValidMessageMixin from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse -from django.db.models import Q, Max +from django.db.models import Max, Q from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ diff --git a/sapl/settings.py b/sapl/settings.py index 975b809e4..f0b6dc0e7 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -30,6 +30,8 @@ DEBUG = config('DEBUG', default=False, cast=bool) ALLOWED_HOSTS = ['*'] +LOGIN_REDIRECT_URL = '/' +LOGIN_URL = '/login/?next=' # SAPL business apps in dependency order SAPL_APPS = ( diff --git a/templates/base.html b/templates/base.html index 4822ebc2d..4fe933103 100644 --- a/templates/base.html +++ b/templates/base.html @@ -103,6 +103,26 @@ + + diff --git a/templates/base/login.html b/templates/base/login.html new file mode 100644 index 000000000..fb47ff084 --- /dev/null +++ b/templates/base/login.html @@ -0,0 +1,68 @@ +{% extends "crud/detail.html" %} +{% load i18n %} +{% block base_content %} + + + + +
+
+
+ +
+
+
+ +{% endblock base_content %} + + {% block javascript %} + + + + + {% endblock %}