diff --git a/.travis.yml b/.travis.yml index 9d469a9b4..d3ba4e10e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,45 +1,23 @@ language: python -sudo: required python: - - "3.4.3" + - 3.4.3 + services: - postgresql -addons: - postgresql: "9.3" - install: - - sudo apt-get install git nginx python3-dev libpq-dev graphviz-dev graphviz pkg-config python-psycopg2 nodejs npm - - sudo ln -s /usr/bin/node - pip install -r requirements/test-requirements.txt - - pip install --upgrade setuptools - -# Line 24 to 35 is a hack found in this link below -# It was used to fix an error in database building -# https://dockyard.com/blog/ruby/2013/03/29/running-postgresql-9-2-on-travis-ci before_script: - - sudo /etc/init.d/postgresql stop - - sudo cp /etc/postgresql/9.2/main/pg_hba.conf ./ - - sudo apt-get remove postgresql postgresql-9.2 -qq --purge - - source /etc/lsb-release - - echo "deb http://apt.postgresql.org/pub/repos/apt/ $DISTRIB_CODENAME-pgdg main" > pgdg.list - - sudo mv pgdg.list /etc/apt/sources.list.d/ - - wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add - - - sudo apt-get update - - sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install postgresql-9.3 postgresql-contrib-9.3 -qq - - sudo /etc/init.d/postgresql stop - - sudo cp ./pg_hba.conf /etc/postgresql/9.3/main - - sudo /etc/init.d/postgresql start - npm install -g bower - - cp .env_dev .env - - sed -i -e 's/getpass.getuser()/"postgres"/g' sapl/settings.py - - psql -c 'create database sapl;' -U postgres + - cp sapl/.env_test sapl/.env + - psql -c "CREATE USER sapl WITH PASSWORD 'sapl'" -U postgres; + - psql -c "CREATE DATABASE sapl OWNER sapl;" -U postgres script: - ./manage.py migrate - ./manage.py bower install - - pip freeze - - ./test_and_check_qa.sh \ No newline at end of file + - py.test + # - ./test_and_check_qa.sh \ No newline at end of file diff --git a/README.rst b/README.rst index 9770c0015..67d1e84db 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,5 @@ -.. image:: https://badge.waffle.io/interlegis/sapl.png?label=ready&title=Ready - :target: https://waffle.io/interlegis/sapl - :alt: 'Stories in Ready' +.. image:: https://travis-ci.org/interlegis/sapl.svg?branch=master + :target: https://travis-ci.org/interlegis/sapl *********************************************** SAPL - Sistema de Apoio ao Processo Legislativo @@ -246,18 +245,18 @@ Boas Práticas * Em caso de Implementação de modelo que envolva a classe ``django.contrib.auth.models.User``, não a use diretamente, use para isso a função ``get_settings_auth_user_model()`` de ``sapl.utils``. Exemplo: - - no lugar de ``owner = models.ForeignKey(User, ... )`` - - use ``owner = models.ForeignKey(get_settings_auth_user_model(), ... )`` + - no lugar de ``owner = models.ForeignKey(User, ... )`` + - use ``owner = models.ForeignKey(get_settings_auth_user_model(), ... )`` - Não use em qualquer modelagem futura, ``ForeignKey`` com ``User`` ou mesmo ``settings.AUTH_USER_MODEL`` sem o import correto que não é o do projeto e sim o que está em ``sapl.utils``, ou seja (``from django.conf import settings``) - - em https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#referencing-the-user-model é explicado por que ser dessa forma! + - em https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#referencing-the-user-model é explicado por que ser dessa forma! - Já em qualquer uso em implementação de execução, ao fazer uma query, por exemplo: - não use ``django.contrib.auth.models.User`` para utilizar as caracteristicas do model, para isso, use esta função: django.contrib.auth.get_user_model() - - Seguir esses passos simplificará qualquer customização futura que venha a ser feita na autenticação do usuários ao evitar correções de inúmeros import's e ainda, desta forma, torna a funcionalidade de autenticação reimplementável por qualquer outro projeto que venha usar partes ou o todo do SAPL. + - Seguir esses passos simplificará qualquer customização futura que venha a ser feita na autenticação do usuários ao evitar correções de inúmeros import's e ainda, desta forma, torna a funcionalidade de autenticação reimplementável por qualquer outro projeto que venha usar partes ou o todo do SAPL. Atenção: diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 44ef147c0..9c8faaa2d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,4 +1,5 @@ dj-database-url==0.4.1 +django==1.9.7 django-admin-bootstrapped==2.5.7 django-bootstrap3==7.0.1 django-bower==5.1.0 @@ -10,8 +11,7 @@ django-extra-views==0.8.0 django-filter==0.13.0 django-floppyforms==1.6.2 django-model-utils==2.5 -django-sass-processor==0.4.0 -django==1.9.7 +django-sass-processor==0.4.6 djangorestframework easy-thumbnails==2.3 git+git://github.com/interlegis/trml2pdf.git diff --git a/.env_dev b/sapl/.env_test similarity index 100% rename from .env_dev rename to sapl/.env_test diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 4f8370eac..ed1da8633 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -38,11 +38,6 @@ def isinst(value, class_str): return classe == class_str -@register.filter -def to_class_name(value): - return value.__class__.__name__.lower() - - @register.filter def get_add_perm(value, arg): perm = value diff --git a/sapl/comissoes/tests/test_comissoes.py b/sapl/comissoes/tests/test_comissoes.py index af5e71da7..fee303192 100644 --- a/sapl/comissoes/tests/test_comissoes.py +++ b/sapl/comissoes/tests/test_comissoes.py @@ -44,14 +44,14 @@ def make_filiacao(): @pytest.mark.django_db(transaction=False) -def test_incluir_parlamentar_errors(client): +def test_incluir_parlamentar_errors(admin_client): comissao = make_comissao() composicao = make_composicao(comissao) - response = client.post(reverse('sapl.comissoes:participacao_create', - kwargs={'pk': composicao.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.comissoes:participacao_create', + kwargs={'pk': composicao.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['parlamentar'] == ['Este campo é obrigatório.']) @@ -62,18 +62,18 @@ def test_incluir_parlamentar_errors(client): @pytest.mark.django_db(transaction=False) -def test_incluir_comissao_submit(client): +def test_incluir_comissao_submit(admin_client): tipo = mommy.make(TipoComissao, sigla='T', nome='Teste') - response = client.post(reverse('sapl.comissoes:comissao_create'), - {'tipo': tipo.pk, - 'nome': 'Comissão Teste', - 'sigla': 'CT', - 'data_criacao': '2016-03-22', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.comissoes:comissao_create'), + {'tipo': tipo.pk, + 'nome': 'Comissão Teste', + 'sigla': 'CT', + 'data_criacao': '2016-03-22', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 comissao = Comissao.objects.first() @@ -82,11 +82,11 @@ def test_incluir_comissao_submit(client): @pytest.mark.django_db(transaction=False) -def test_incluir_comissao_errors(client): +def test_incluir_comissao_errors(admin_client): - response = client.post(reverse('sapl.comissoes:comissao_create'), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.comissoes:comissao_create'), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) diff --git a/sapl/crispy_layout_mixin.py b/sapl/crispy_layout_mixin.py index c6c4437a6..40f6b01e4 100644 --- a/sapl/crispy_layout_mixin.py +++ b/sapl/crispy_layout_mixin.py @@ -1,12 +1,12 @@ from math import ceil -import rtyaml from crispy_forms.bootstrap import FormActions from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit from django import template from django.utils import formats from django.utils.translation import ugettext as _ +import rtyaml def heads_and_tails(list_of_lists): @@ -50,8 +50,9 @@ class SaplFormLayout(Layout): def get_field_display(obj, fieldname): field = obj._meta.get_field(fieldname) - verbose_name = str(field.verbose_name) - if field.choices: + verbose_name = str(field.verbose_name)\ + if hasattr(field, 'verbose_name') else '' + if hasattr(field, 'choices') and field.choices: value = getattr(obj, 'get_%s_display' % fieldname)() else: value = getattr(obj, fieldname) @@ -74,6 +75,14 @@ def get_field_display(obj, fieldname): value.name.split('/')[-1:][0]) else: display = '' + elif 'ManyRelatedManager' in str(type(value))\ + or 'RelatedManager' in str(type(value)): + display = '' + if not verbose_name: + verbose_name = str(field.related_model._meta.verbose_name_plural) else: display = str(value) return verbose_name, display @@ -147,7 +156,9 @@ class CrispyLayoutFormMixin: def read_yaml_from_file(yaml_layout): # TODO cache this at application level t = template.loader.get_template(yaml_layout) - rendered = t.render() + # aqui é importante converter para str pois, dependendo do ambiente, + # o rtyaml pode usar yaml.CSafeLoader, que exige str ou stream + rendered = str(t.render()) return rtyaml.load(rendered) diff --git a/sapl/materia/tests/test_materia.py b/sapl/materia/tests/test_materia.py index 1386e294a..ce530185b 100644 --- a/sapl/materia/tests/test_materia.py +++ b/sapl/materia/tests/test_materia.py @@ -80,7 +80,7 @@ def make_materia_principal(): @pytest.mark.django_db(transaction=False) -def test_materia_anexada_submit(client): +def test_materia_anexada_submit(admin_client): materia_principal = make_materia_principal() # Cria a matéria que será anexada @@ -99,14 +99,14 @@ def test_materia_anexada_submit(client): materia_anexada = MateriaLegislativa.objects.get(numero=32, ano=2004) # Testa POST - response = client.post(reverse('sapl.materia:anexada_create', - kwargs={'pk': materia_principal.pk}), - {'tipo': materia_anexada.tipo.pk, - 'numero': materia_anexada.numero, - 'ano': materia_anexada.ano, - 'data_anexacao': '2016-03-18', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:anexada_create', + kwargs={'pk': materia_principal.pk}), + {'tipo': materia_anexada.tipo.pk, + 'numero': materia_anexada.numero, + 'ano': materia_anexada.ano, + 'data_anexacao': '2016-03-18', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 # Verifica se a matéria foi anexada corretamente @@ -116,7 +116,7 @@ def test_materia_anexada_submit(client): @pytest.mark.django_db(transaction=False) -def test_autoria_submit(client): +def test_autoria_submit(admin_client): materia_principal = make_materia_principal() # Cria um tipo de Autor @@ -126,14 +126,14 @@ def test_autoria_submit(client): autor = mommy.make(Autor, tipo=tipo_autor, nome='Autor Teste') # Testa POST - response = client.post(reverse('sapl.materia:autoria_create', - kwargs={'pk': materia_principal.pk}), - {'autor': autor.pk, - 'primeiro_autor': True, - 'materia_id': materia_principal.pk, - 'partido': '', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:autoria_create', + kwargs={'pk': materia_principal.pk}), + {'autor': autor.pk, + 'primeiro_autor': True, + 'materia_id': materia_principal.pk, + 'partido': '', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 # Verifica se o autor foi realmente criado @@ -144,7 +144,7 @@ def test_autoria_submit(client): @pytest.mark.django_db(transaction=False) -def test_despacho_inicial_submit(client): +def test_despacho_inicial_submit(admin_client): materia_principal = make_materia_principal() # Cria uma comissão @@ -156,11 +156,11 @@ def test_despacho_inicial_submit(client): data_criacao='2016-03-18') # Testa POST - response = client.post(reverse('sapl.materia:despachoinicial_create', - kwargs={'pk': materia_principal.pk}), - {'comissao': comissao.pk, - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:despachoinicial_create', + kwargs={'pk': materia_principal.pk}), + {'comissao': comissao.pk, + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 # Verifica se o despacho foi criado @@ -170,19 +170,19 @@ def test_despacho_inicial_submit(client): @pytest.mark.django_db(transaction=False) -def test_numeracao_submit(client): +def test_numeracao_submit(admin_client): materia_principal = make_materia_principal() materia = make_materia_principal() # Testa POST - response = client.post(reverse('sapl.materia:numeracao_create', - kwargs={'pk': materia_principal.pk}), - {'tipo_materia': materia.tipo.pk, - 'numero_materia': materia.numero, - 'ano_materia': materia.ano, - 'data_materia': '2016-03-21', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:numeracao_create', + kwargs={'pk': materia_principal.pk}), + {'tipo_materia': materia.tipo.pk, + 'numero_materia': materia.numero, + 'ano_materia': materia.ano, + 'data_materia': '2016-03-21', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 @@ -193,7 +193,7 @@ def test_numeracao_submit(client): @pytest.mark.django_db(transaction=False) -def test_documento_acessorio_submit(client): +def test_documento_acessorio_submit(admin_client): materia_principal = make_materia_principal() # Cria um tipo de Autor @@ -207,15 +207,16 @@ def test_documento_acessorio_submit(client): descricao='Teste') # Testa POST - response = client.post(reverse('sapl.materia:documentoacessorio_create', - kwargs={'pk': materia_principal.pk}), - {'tipo': tipo.pk, - 'nome': 'teste_nome', - 'data_materia': '2016-03-21', - 'autor': autor, - 'ementa': 'teste_ementa', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse( + 'sapl.materia:documentoacessorio_create', + kwargs={'pk': materia_principal.pk}), + {'tipo': tipo.pk, + 'nome': 'teste_nome', + 'data_materia': '2016-03-21', + 'autor': autor, + 'ementa': 'teste_ementa', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 @@ -227,19 +228,20 @@ def test_documento_acessorio_submit(client): @pytest.mark.django_db(transaction=False) -def test_legislacao_citada_submit(client): +def test_legislacao_citada_submit(admin_client): materia_principal = make_materia_principal() norma = make_norma() # Testa POST - response = client.post(reverse('sapl.materia:legislacaocitada_create', - kwargs={'pk': materia_principal.pk}), - {'tipo': norma.tipo.pk, - 'numero': norma.numero, - 'ano': norma.ano, - 'disposicao': 'disposicao', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post( + reverse('sapl.materia:legislacaocitada_create', + kwargs={'pk': materia_principal.pk}), + {'tipo': norma.tipo.pk, + 'numero': norma.numero, + 'ano': norma.ano, + 'disposicao': 'disposicao', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 @@ -249,7 +251,7 @@ def test_legislacao_citada_submit(client): @pytest.mark.django_db(transaction=False) -def test_tramitacao_submit(client): +def test_tramitacao_submit(admin_client): materia_principal = make_materia_principal() # Cria status para tramitação status_tramitacao = mommy.make(StatusTramitacao, @@ -257,7 +259,7 @@ def test_tramitacao_submit(client): sigla='ST', descricao='Status_Teste') # Testa POST - response = client.post( + response = admin_client.post( reverse('sapl.materia:tramitacao_create', kwargs={'pk': materia_principal.pk}), {'unidade_tramitacao_local': make_unidade_tramitacao( @@ -283,12 +285,12 @@ def test_tramitacao_submit(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_anexada(client): +def test_form_errors_anexada(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:anexada_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:anexada_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) @@ -301,42 +303,43 @@ def test_form_errors_anexada(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_autoria(client): +def test_form_errors_autoria(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:autoria_create', - kwargs={'pk': materia_principal.pk}), - {'materia_id': materia_principal.pk, - 'partido': '', - 'autor': '', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:autoria_create', + kwargs={'pk': materia_principal.pk}), + {'materia_id': materia_principal.pk, + 'partido': '', + 'autor': '', + 'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['autor'] == ['Este campo é obrigatório.']) @pytest.mark.django_db(transaction=False) -def test_form_errors_despacho_inicial(client): +def test_form_errors_despacho_inicial(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:despachoinicial_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:despachoinicial_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['comissao'] == ['Este campo é obrigatório.']) @pytest.mark.django_db(transaction=False) -def test_form_errors_documento_acessorio(client): +def test_form_errors_documento_acessorio(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:documentoacessorio_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post( + reverse('sapl.materia:documentoacessorio_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) @@ -345,13 +348,14 @@ def test_form_errors_documento_acessorio(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_legislacao_citada(client): +def test_form_errors_legislacao_citada(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:legislacaocitada_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post( + reverse('sapl.materia:legislacaocitada_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) @@ -362,13 +366,13 @@ def test_form_errors_legislacao_citada(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_numeracao(client): +def test_form_errors_numeracao(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:numeracao_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:numeracao_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo_materia'] == ['Este campo é obrigatório.']) @@ -381,13 +385,14 @@ def test_form_errors_numeracao(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_tramitacao(client): +def test_form_errors_tramitacao(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:tramitacao_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post( + reverse('sapl.materia:tramitacao_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['data_tramitacao'] == ['Este campo é obrigatório.']) @@ -402,13 +407,14 @@ def test_form_errors_tramitacao(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_relatoria(client): +def test_form_errors_relatoria(admin_client): materia_principal = make_materia_principal() - response = client.post(reverse('sapl.materia:relatoria_create', - kwargs={'pk': materia_principal.pk}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post( + reverse('sapl.materia:relatoria_create', + kwargs={'pk': materia_principal.pk}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['data_designacao_relator'] == ['Este campo é obrigatório.']) @@ -417,12 +423,12 @@ def test_form_errors_relatoria(client): @pytest.mark.django_db(transaction=False) -def test_proposicao_submit(client): - response = client.post(reverse('sapl.materia:proposicao_create'), - {'tipo': mommy.make(TipoProposicao, pk=3).pk, - 'descricao': 'Teste proposição', - 'salvar': 'salvar'}, - follow=True) +def test_proposicao_submit(admin_client): + response = admin_client.post(reverse('sapl.materia:proposicao_create'), + {'tipo': mommy.make(TipoProposicao, pk=3).pk, + 'descricao': 'Teste proposição', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 @@ -432,11 +438,11 @@ def test_proposicao_submit(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_proposicao(client): +def test_form_errors_proposicao(admin_client): - response = client.post(reverse('sapl.materia:proposicao_create'), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.materia:proposicao_create'), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) assert (response.context_data['form'].errors['descricao'] == diff --git a/sapl/norma/tests/test_norma.py b/sapl/norma/tests/test_norma.py index 16c980d15..65c0f28b1 100644 --- a/sapl/norma/tests/test_norma.py +++ b/sapl/norma/tests/test_norma.py @@ -6,22 +6,22 @@ from sapl.norma.models import NormaJuridica, TipoNormaJuridica @pytest.mark.django_db(transaction=False) -def test_incluir_norma_submit(client): +def test_incluir_norma_submit(admin_client): # Cria um tipo de norma tipo = mommy.make(TipoNormaJuridica, sigla='T', descricao='Teste') # Testa POST - response = client.post(reverse('sapl.norma:normajuridica_create'), - {'tipo': tipo.pk, - 'numero': '1', - 'ano': '2016', - 'data': '2016-03-22', - 'esfera_federacao': 'E', - 'ementa': 'Teste_Ementa', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.norma:normajuridica_create'), + {'tipo': tipo.pk, + 'numero': '1', + 'ano': '2016', + 'data': '2016-03-22', + 'esfera_federacao': 'E', + 'ementa': 'Teste_Ementa', + 'salvar': 'salvar'}, + follow=True) assert response.status_code == 200 norma = NormaJuridica.objects.first() @@ -31,11 +31,11 @@ def test_incluir_norma_submit(client): @pytest.mark.django_db(transaction=False) -def test_incluir_norma_errors(client): +def test_incluir_norma_errors(admin_client): - response = client.post(reverse('sapl.norma:normajuridica_create'), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.norma:normajuridica_create'), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['tipo'] == ['Este campo é obrigatório.']) diff --git a/sapl/parlamentares/tests/test_parlamentares.py b/sapl/parlamentares/tests/test_parlamentares.py index 2739dcd62..16b0fb158 100644 --- a/sapl/parlamentares/tests/test_parlamentares.py +++ b/sapl/parlamentares/tests/test_parlamentares.py @@ -8,20 +8,20 @@ from sapl.parlamentares.models import (Dependente, Filiacao, Legislatura, @pytest.mark.django_db(transaction=False) -def test_cadastro_parlamentar(client): +def test_cadastro_parlamentar(admin_client): legislatura = mommy.make(Legislatura) url = reverse('sapl.parlamentares:parlamentar_create') - response = client.get(url) + response = admin_client.get(url) assert response.status_code == 200 - response = client.post(url, {'nome_completo': 'Teresa Barbosa', - 'nome_parlamentar': 'Terezinha', - 'sexo': 'F', - 'ativo': 'True', - 'legislatura': legislatura.id, - 'data_expedicao_diploma': '2001-01-01'}, - follow=True) + response = admin_client.post(url, {'nome_completo': 'Teresa Barbosa', + 'nome_parlamentar': 'Terezinha', + 'sexo': 'F', + 'ativo': 'True', + 'legislatura': legislatura.id, + 'data_expedicao_diploma': '2001-01-01'}, + follow=True) [parlamentar] = Parlamentar.objects.all() assert parlamentar.nome_parlamentar == 'Terezinha' @@ -36,9 +36,9 @@ def test_cadastro_parlamentar(client): @pytest.mark.django_db(transaction=False) -def test_incluir_parlamentar_errors(client): +def test_incluir_parlamentar_errors(admin_client): url = reverse('sapl.parlamentares:parlamentar_create') - response = client.post(url) + response = admin_client.post(url) erros_esperados = {campo: ['Este campo é obrigatório.'] for campo in ['legislatura', 'data_expedicao_diploma', @@ -50,34 +50,34 @@ def test_incluir_parlamentar_errors(client): @pytest.mark.django_db(transaction=False) -def test_filiacao_submit(client): +def test_filiacao_submit(admin_client): mommy.make(Parlamentar, pk=14) mommy.make(Partido, pk=32) - client.post(reverse('sapl.parlamentares:filiacao_create', - kwargs={'pk': 14}), - {'partido': 32, - 'data': '2016-03-22', - 'salvar': 'salvar'}, - follow=True) + admin_client.post(reverse('sapl.parlamentares:filiacao_create', + kwargs={'pk': 14}), + {'partido': 32, + 'data': '2016-03-22', + 'salvar': 'salvar'}, + follow=True) filiacao = Filiacao.objects.first() assert 32 == filiacao.partido.pk @pytest.mark.django_db(transaction=False) -def test_dependente_submit(client): +def test_dependente_submit(admin_client): mommy.make(Parlamentar, pk=14) mommy.make(Partido, pk=32) mommy.make(TipoDependente, pk=3) - client.post(reverse('sapl.parlamentares:dependente_create', - kwargs={'pk': 14}), - {'nome': 'Eduardo', - 'tipo': 3, - 'sexo': 'M', - 'salvar': 'salvar'}, - follow=True) + admin_client.post(reverse('sapl.parlamentares:dependente_create', + kwargs={'pk': 14}), + {'nome': 'Eduardo', + 'tipo': 3, + 'sexo': 'M', + 'salvar': 'salvar'}, + follow=True) dependente = Dependente.objects.first() assert 3 == dependente.tipo.pk @@ -85,12 +85,13 @@ def test_dependente_submit(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_dependente(client): +def test_form_errors_dependente(admin_client): mommy.make(Parlamentar, pk=14) - response = client.post(reverse('sapl.parlamentares:dependente_create', - kwargs={'pk': 14}), - {'salvar': 'salvar'}, - follow=True) + response = admin_client.post( + reverse('sapl.parlamentares:dependente_create', + kwargs={'pk': 14}), + {'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['nome'] == ['Este campo é obrigatório.']) @@ -101,14 +102,14 @@ def test_form_errors_dependente(client): @pytest.mark.django_db(transaction=False) -def test_form_errors_filiacao(client): +def test_form_errors_filiacao(admin_client): mommy.make(Parlamentar, pk=14) - response = client.post(reverse('sapl.parlamentares:filiacao_create', - kwargs={'pk': 14}), - {'partido': '', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.parlamentares:filiacao_create', + kwargs={'pk': 14}), + {'partido': '', + 'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['partido'] == ['Este campo é obrigatório.']) @@ -117,31 +118,31 @@ def test_form_errors_filiacao(client): @pytest.mark.django_db(transaction=False) -def test_mandato_submit(client): +def test_mandato_submit(admin_client): mommy.make(Parlamentar, pk=14) mommy.make(Legislatura, pk=5) - client.post(reverse('sapl.parlamentares:mandato_create', - kwargs={'pk': 14}), - {'legislatura': 5, - 'data_fim_mandato': '2016-01-01', - 'data_expedicao_diploma': '2016-03-22', - 'observacao': 'Observação do mandato', - 'salvar': 'salvar'}, - follow=True) + admin_client.post(reverse('sapl.parlamentares:mandato_create', + kwargs={'pk': 14}), + {'legislatura': 5, + 'data_fim_mandato': '2016-01-01', + 'data_expedicao_diploma': '2016-03-22', + 'observacao': 'Observação do mandato', + 'salvar': 'salvar'}, + follow=True) mandato = Mandato.objects.first() assert 'Observação do mandato' == mandato.observacao @pytest.mark.django_db(transaction=False) -def test_form_errors_mandato(client): +def test_form_errors_mandato(admin_client): mommy.make(Parlamentar, pk=14) - response = client.post(reverse('sapl.parlamentares:mandato_create', - kwargs={'pk': 14}), - {'legislatura': '', - 'salvar': 'salvar'}, - follow=True) + response = admin_client.post(reverse('sapl.parlamentares:mandato_create', + kwargs={'pk': 14}), + {'legislatura': '', + 'salvar': 'salvar'}, + follow=True) assert (response.context_data['form'].errors['legislatura'] == ['Este campo é obrigatório.']) diff --git a/sapl/protocoloadm/tests/test_protocoloadm.py b/sapl/protocoloadm/tests/test_protocoloadm.py index 40dccb2dc..b4d39942e 100644 --- a/sapl/protocoloadm/tests/test_protocoloadm.py +++ b/sapl/protocoloadm/tests/test_protocoloadm.py @@ -8,22 +8,22 @@ from sapl.protocoloadm.models import Protocolo @pytest.mark.django_db(transaction=False) -def test_anular_protocolo_acessivel(client): - response = client.get(reverse('sapl.protocoloadm:anular_protocolo')) +def test_anular_protocolo_acessivel(admin_client): + response = admin_client.get(reverse('sapl.protocoloadm:anular_protocolo')) assert response.status_code == 200 @pytest.mark.django_db(transaction=False) -def test_anular_protocolo_submit(client): +def test_anular_protocolo_submit(admin_client): mommy.make(Protocolo, numero='76', ano='2016', anulado=False) # TODO: setar usuario e IP - response = client.post(reverse('sapl.protocoloadm:anular_protocolo'), - {'numero': '76', - 'ano': '2016', - 'justificativa_anulacao': 'TESTE', - 'salvar': 'Anular'}, - follow=True) + response = admin_client.post(reverse('sapl.protocoloadm:anular_protocolo'), + {'numero': '76', + 'ano': '2016', + 'justificativa_anulacao': 'TESTE', + 'salvar': 'Anular'}, + follow=True) assert response.status_code == 200 diff --git a/sapl/settings.py b/sapl/settings.py index 96dee01eb..fb7fc4bb9 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -38,6 +38,7 @@ LOGIN_URL = '/login/?next=' # SAPL business apps in dependency order SAPL_APPS = ( 'sapl.base', + 'sapl.crud', 'sapl.parlamentares', 'sapl.comissoes', 'sapl.materia', diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index e4163a499..901f7286c 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -131,13 +131,11 @@ body { } } - fieldset { - fieldset { font-size: 95%; legend { font-size: 18px; } } -} \ No newline at end of file +} diff --git a/sapl/utils.py b/sapl/utils.py index 088319563..5b1bee282 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -261,7 +261,7 @@ def permissoes_parlamentares(): def permissoes_protocoloadm(): lista_permissoes = [] perms_protocolo = Permission.objects.filter( - group__name='Operador de Protocolo') + group__name='Operador de Protocolo Administrativo') for p in perms_protocolo: lista_permissoes.append('protocoloadm.' + p.codename) return set(lista_permissoes) @@ -270,7 +270,7 @@ def permissoes_protocoloadm(): def permissoes_adm(): lista_permissoes = [] perms_adm = Permission.objects.filter( - group__name='Operador de Administração') + group__name='Operador Administrativo') for p in perms_adm: lista_permissoes.append('protocoloadm.' + p.codename) return set(lista_permissoes) @@ -279,7 +279,7 @@ def permissoes_adm(): def permissoes_sessao(): lista_permissoes = [] perms_sessao = list(Permission.objects.filter( - group__name='Operador de Sessão')) + group__name='Operador de Sessão Plenária')) for p in perms_sessao: lista_permissoes.append('sessao.' + p.codename) return set(lista_permissoes) @@ -288,7 +288,7 @@ def permissoes_sessao(): def permissoes_painel(): lista_permissoes = [] perms_painel = list(Permission.objects.filter( - group__name='Operador de Painel')) + group__name='Operador de Painel Eletrônico')) for p in perms_painel: lista_permissoes.append('painel.' + p.codename) return set(lista_permissoes) diff --git a/scripts/inicializa_grupos_autorizacoes.py b/scripts/inicializa_grupos_autorizacoes.py index 21d43808f..65f27f880 100644 --- a/scripts/inicializa_grupos_autorizacoes.py +++ b/scripts/inicializa_grupos_autorizacoes.py @@ -1,188 +1,114 @@ +from django.apps import apps from django.contrib.auth.models import Group, Permission, User from django.contrib.contenttypes.models import ContentType -def cria_grupos_permissoes(): - - if not Group.objects.filter("Teste"): - pass - - # Cria todos os grupos necessários para a aplicação - - op_geral = Group.objects.get_or_create(name="Operador Geral") - op_prot = Group.objects.get_or_create(name="Operador de Protocolo") - op_sessao = Group.objects.get_or_create(name="Operador de Sessão") - op_comissao = Group.objects.get_or_create(name="Operador de Comissão") - op_adm = Group.objects.get_or_create(name="Operador de Administração") - op_norma = Group.objects.get_or_create(name="Operador de Norma Jurídica") - op_materia = Group.objects.get_or_create( - name="Operador de Matéria Legislativa") - op_painel = Group.objects.get_or_create(name="Operador de Painel") - op_autor = Group.objects.get_or_create(name="Autor") - - op_geral = op_geral[0] - op_prot = op_prot[0] - op_sessao = op_sessao[0] - op_comissao = op_comissao[0] - op_adm = op_adm[0] - op_norma = op_norma[0] - op_materia = op_materia[0] - op_painel = op_painel[0] - op_autor = op_autor[0] - - # Base - - permissao_add_cl = Permission.objects.get( - name="Can add Casa Legislativa") - permissao_edit_cl = Permission.objects.get( - name="Can change Casa Legislativa") - permissao_remove_cl = Permission.objects.get( - name="Can delete Casa Legislativa") - - permissoes_base = [permissao_add_cl, - permissao_edit_cl, - permissao_remove_cl] +def cria_ou_reseta_grupo(nome): + grupo = Group.objects.get_or_create(name=nome)[0] + for p in list(grupo.permissions.all()): + grupo.permissions.remove(p) + return grupo - # Comissao - cts = ContentType.objects.filter(app_label='comissoes') - perms_comissoes = list(Permission.objects.filter(content_type__in=cts)) +def cria_usuario(nome, grupo): + nome_usuario = nome + usuario = User.objects.get_or_create(username=nome_usuario)[0] + usuario.set_password('interlegis') + usuario.save() + grupo.user_set.add(usuario) - # Materia - cts = ContentType.objects.filter(app_label='materia') - perms_materia = list(Permission.objects.filter(content_type__in=cts)) - - # Norma - - cts = ContentType.objects.filter(app_label='norma') - perms_norma = list(Permission.objects.filter(content_type__in=cts)) - - # Painel - - cts = ContentType.objects.filter(app_label='painel') - perms_painel = list(Permission.objects.filter(content_type__in=cts)) - - # Parlamentares +def cria_grupos_permissoes(): - cts = ContentType.objects.filter(app_label='parlamentares') - perms_parlamentares = list(Permission.objects.filter(content_type__in=cts)) + nomes_apps = ['base', 'parlamentares', 'comissoes', + 'materia', 'norma', 'sessao', 'painel'] - # ProtocoloADM e DOCADM + permissoes = {app: list(Permission.objects.filter( + content_type__in=ContentType.objects.filter(app_label=app))) + for app in nomes_apps} + # permissoes específicas para protocolo e documento administrativo cts = ContentType.objects.filter(app_label='protocoloadm') - perms_docadm = list(Permission.objects.filter(content_type__in=cts)) - - cts_exc1 = cts.filter(model__icontains='tramitacao') - cts_exc2 = cts.filter(model__icontains='documentoadministrativo') - - cts = cts.exclude(id__in=[o.id for o in cts_exc1]) - cts = cts.exclude(id__in=[o.id for o in cts_exc2]) - - perms_protocoloadm = list(Permission.objects.filter(content_type__in=cts)) - - # Sessao - - cts = ContentType.objects.filter(app_label='sessao') - perms_sessao = list(Permission.objects.filter(content_type__in=cts)) - - # Painel - - cts = ContentType.objects.filter(app_label='painel') - perms_painel = list(Permission.objects.filter(content_type__in=cts)) + # documento administrativo + permissoes['documento_administrativo'] = list( + Permission.objects.filter(content_type__in=cts)) + nome_grupo = 'Operador Administrativo' + grupo = cria_ou_reseta_grupo(nome_grupo) + for p in permissoes['documento_administrativo']: + grupo.permissions.add(p) + + nome_usuario = 'operador_administrativo' + cria_usuario(nome_usuario, grupo) + + # prolocolo administrativo + cts = cts.exclude(model__icontains='tramitacao').exclude( + model__icontains='documentoadministrativo') + permissoes['protocoloadm'] = list( + Permission.objects.filter(content_type__in=cts)) + nome_grupo = 'Operador de Protocolo Administrativo' + grupo = cria_ou_reseta_grupo(nome_grupo) + for p in permissoes['protocoloadm']: + grupo.permissions.add(p) + + nome_usuario = 'operador_protocoloadm' + cria_usuario(nome_usuario, grupo) + + # permissoes do base + cts = ContentType.objects.filter(app_label='base') + permissoes['base'] = list( + Permission.objects.filter(content_type__in=cts)) + + for nome_app in nomes_apps: + + if nome_app not in {'base', 'parlamentares'}: + # Elimina casos especificos + + # Cria Grupo + nome_grupo = 'Operador de %s' % apps.get_app_config( + nome_app).verbose_name + grupo = cria_ou_reseta_grupo(nome_grupo) + + # Elimina o acesso a proposicoes pelo Operador de Matérias + if nome_app == 'materia': + cts = ContentType.objects.filter( + app_label='materia').exclude(model='proposicao') + permissoes['materia'] = list( + Permission.objects.filter(content_type__in=cts)) + + # Configura as permissoes + for p in permissoes[nome_app]: + grupo.permissions.add(p) + + # Cria o Usuario + nome_usuario = 'operador_%s' % nome_app + usuario = User.objects.get_or_create(username=nome_usuario)[0] + usuario.set_password('interlegis') + usuario.save() + grupo.user_set.add(usuario) + + # Operador Geral + grupo_geral = cria_ou_reseta_grupo('Operador Geral') + for lista in permissoes.values(): + for p in lista: + grupo_geral.permissions.add(p) + + nome_usuario = 'operador_geral' + cria_usuario(nome_usuario, grupo_geral) # Autor - - perms_autor = Permission.objects.get(name="Can add Proposição") - - # Configura Permissoes Operador de Protocolo - for p in perms_protocoloadm: - op_prot.permissions.add(p) - - # Configura Permissoes Operador de Sessao - for p in perms_sessao: - op_sessao.permissions.add(p) - - # Configura Permissoes Operador de Comissao - for p in perms_comissoes: - op_comissao.permissions.add(p) - - # Configura Permissoes Operador de Administracao - for p in perms_docadm: - op_adm.permissions.add(p) - - # Configura Permissoes Operador de Norma - for p in perms_norma: - op_norma.permissions.add(p) - - # Configura Permissoes Operador de Materia - for p in perms_materia: - op_materia.permissions.add(p) - - # Configura Permissoes Operador de Painel - for p in perms_painel: - op_painel.permissions.add(p) + perms_autor = [] + perms_autor.append(Permission.objects.get(name='Can add Proposição')) + perms_autor.append(Permission.objects.get(name='Can change Proposição')) + perms_autor.append(Permission.objects.get(name='Can delete Proposição')) # Configura Permissoes Autor - op_autor.permissions.add(perms_autor) - - # Configura Permissoes Operador Geral - perms_op_geral = perms_protocoloadm + perms_sessao + perms_comissoes - perms_op_geral = perms_op_geral + perms_docadm + perms_norma - perms_op_geral = perms_op_geral + perms_materia - perms_op_geral = perms_op_geral + perms_parlamentares + perms_painel - perms_op_geral = perms_op_geral + permissoes_base - - for p in perms_op_geral: - op_geral.permissions.add(p) - op_geral.permissions.add(perms_autor) - - # Cria usuarios - op_geral_user = User.objects.get_or_create(username='op_geral')[0] - op_geral_user.set_password('interlegis') - op_geral_user.save() - op_geral.user_set.add(op_geral_user) - - op_materia_user = User.objects.get_or_create(username='op_materia')[0] - op_materia_user.set_password('interlegis') - op_materia_user.save() - op_materia.user_set.add(op_materia_user) - - op_prot_user = User.objects.get_or_create(username='op_protocolo')[0] - op_prot_user.set_password('interlegis') - op_prot_user.save() - op_prot.user_set.add(op_prot_user) - - op_sessao_user = User.objects.get_or_create(username='op_sessao')[0] - op_sessao_user.set_password('interlegis') - op_sessao_user.save() - op_sessao.user_set.add(op_sessao_user) - - op_comissao_user = User.objects.get_or_create(username='op_comissao')[0] - op_comissao_user.set_password('interlegis') - op_comissao_user.save() - op_comissao.user_set.add(op_comissao_user) - - op_adm_user = User.objects.get_or_create(username='op_adm')[0] - op_adm_user.set_password('interlegis') - op_adm_user.save() - op_adm.user_set.add(op_adm_user) - - op_norma_user = User.objects.get_or_create(username='op_norma')[0] - op_norma_user.set_password('interlegis') - op_norma_user.save() - op_norma.user_set.add(op_norma_user) - - op_painel_user = User.objects.get_or_create(username='op_painel')[0] - op_painel_user.set_password('interlegis') - op_painel_user.save() - op_painel.user_set.add(op_norma_user) - - op_autor_user = User.objects.get_or_create(username='op_autor')[0] - op_autor_user.set_password('interlegis') - op_autor_user.save() - op_autor.user_set.add(op_autor_user) + grupo = cria_ou_reseta_grupo('Autor') + for p in perms_autor: + grupo.permissions.add(p) + + nome_usuario = 'operador_autor' + cria_usuario(nome_usuario, grupo_geral) if __name__ == '__main__': cria_grupos_permissoes() diff --git a/scripts/test_inicializa_grupos_autorizacoes.py b/scripts/test_inicializa_grupos_autorizacoes.py new file mode 100644 index 000000000..a8e9064a0 --- /dev/null +++ b/scripts/test_inicializa_grupos_autorizacoes.py @@ -0,0 +1,47 @@ +import pytest +from django.apps import apps +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType + +from inicializa_grupos_autorizacoes import cria_grupos_permissoes + +pytestmark = pytest.mark.django_db + +apps_com_permissao_padrao = [ + 'comissoes', 'norma', 'sessao', 'painel'] + + +@pytest.mark.parametrize('app_label', apps_com_permissao_padrao) +def test_grupo_padrao_tem_permissoes_sobre_todo_o_app(app_label): + + app = apps.get_app_config(app_label) + + # código testado + cria_grupos_permissoes() + + def gerar_permissoes(app): + for model in app.get_models(): + for op in ['add', 'change', 'delete']: + yield model, 'Can %s %s' % (op, model._meta.verbose_name) + grupo = Group.objects.get(name='Operador de %s' % app.verbose_name) + esperado = set(gerar_permissoes(app)) + + real = set((p.content_type.model_class(), p.name) + for p in grupo.permissions.all()) + assert real == esperado + + +@pytest.mark.parametrize('app_label', apps_com_permissao_padrao) +def test_permissoes_extras_sao_apagadas(app_label): + + app = apps.get_app_config(app_label) + grupo = Group.objects.create(name='Operador de %s' % app.verbose_name) + + permissao_errada = Permission.objects.create( + name='STUB', content_type=ContentType.objects.first()) + grupo.permissions.add(permissao_errada) + + # código testado + cria_grupos_permissoes() + + assert not grupo.permissions.filter(id=permissao_errada.id).exists()