{% if view.get_cargos_mesa %}
@@ -47,3 +47,18 @@
{% endblock detail_content %}
+
+{% block extra_js %}
+
+{% endblock extra_js %}
diff --git a/sapl/templates/sessao/sessaoplenaria_filter.html b/sapl/templates/sessao/sessaoplenaria_filter.html
index 5069735c7..b4aa4ca98 100644
--- a/sapl/templates/sessao/sessaoplenaria_filter.html
+++ b/sapl/templates/sessao/sessaoplenaria_filter.html
@@ -6,7 +6,7 @@
{% if perms.sessao %}
- {% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %}
+ {% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %}
{% endif %}
{% if filter_url %}
@@ -50,4 +50,4 @@
{% endif %}
{% endblock detail_content %}
{% block table_content %}
-{% endblock table_content %}
\ No newline at end of file
+{% endblock table_content %}
diff --git a/sapl/templates/sistema.html b/sapl/templates/sistema.html
index 837198e03..0b80f85ad 100644
--- a/sapl/templates/sistema.html
+++ b/sapl/templates/sistema.html
@@ -95,7 +95,6 @@
Módulo Administrativo
diff --git a/sapl/test_general.py b/sapl/test_general.py
index da2e17ae6..15b589a80 100644
--- a/sapl/test_general.py
+++ b/sapl/test_general.py
@@ -1,13 +1,81 @@
-import pytest
from django.apps import apps
+from django.contrib.auth import get_user_model
+from django.contrib.auth.management import _get_all_permissions
+from django.contrib.auth.models import Permission, User
+from django.contrib.contenttypes.models import ContentType
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.urlresolvers import reverse
from django.db.models import CharField, TextField
+from django.http.response import HttpResponseNotFound
+from django.utils.translation import string_concat
+from django.utils.translation import ugettext_lazy as _
from model_mommy import mommy
+import pytest
+
+from sapl.crud.base import PermissionRequiredForAppCrudMixin, CrudAux
+from scripts.inicializa_grupos_autorizacoes import cria_grupos_permissoes
+from scripts.lista_urls import lista_urls
from .settings import SAPL_APPS
+
pytestmark = pytest.mark.django_db
sapl_appconfs = [apps.get_app_config(n[5:]) for n in SAPL_APPS]
+_lista_urls = lista_urls()
+
+
+def create_perms_post_migrate(app):
+
+ searched_perms = list()
+ # The codenames and ctypes that should exist.
+ ctypes = set()
+
+ for klass in list(app.get_models()):
+ opts = klass._meta
+ permissions = (
+ ("list_" + opts.model_name,
+ string_concat(
+ _('Visualizaçao da lista de'), ' ',
+ opts.verbose_name_plural)),
+ ("detail_" + opts.model_name,
+ string_concat(
+ _('Visualização dos detalhes de'), ' ',
+ opts.verbose_name_plural)),
+ )
+ opts.permissions = tuple(
+ set(list(permissions) + list(opts.permissions)))
+
+ if opts.proxy:
+ # Force looking up the content types in the current database
+ # before creating foreign keys to them.
+ app_label, model = opts.app_label, opts.model_name
+
+ try:
+ ctype = ContentType.objects.get_by_natural_key(
+ app_label, model)
+ except:
+ ctype = ContentType.objects.create(
+ app_label=app_label, model=model)
+ else:
+ ctype = ContentType.objects.get_for_model(klass)
+
+ ctypes.add(ctype)
+ for perm in _get_all_permissions(klass._meta, ctype):
+ searched_perms.append((ctype, perm))
+
+ all_perms = set(Permission.objects.filter(
+ content_type__in=ctypes,
+ ).values_list(
+ "content_type", "codename"
+ ))
+
+ perms = [
+ Permission(codename=codename, name=name, content_type=ct)
+ for ct, (codename, name) in searched_perms
+ if (ct.pk, codename) not in all_perms
+ ]
+ Permission.objects.bulk_create(perms)
def test_charfield_textfield():
@@ -34,3 +102,190 @@ def test_str_sanity():
msg = '%s.%s.__str__ is broken.' % (
model.__module__, model.__name__)
raise AssertionError(msg, exc)
+
+btn_login = ('
')
+
+
+@pytest.mark.parametrize('url_item', _lista_urls)
+def test_crudaux_formato_inicio_urls_associadas(url_item):
+
+ # Verifica se um crud é do tipo CrudAux, se sim, sua url deve começar
+ # com /sistema/
+ key, url, var, app_name = url_item
+ url = '/' + (url % {v: 1 for v in var})
+
+ view_class = None
+ if hasattr(key, 'view_class'):
+ view_class = key.view_class
+
+ # se não tem view_class, possivelmente é não é uma classed base view
+ if not view_class:
+ return
+
+ # se não tem atributo crud, não é será nenhum tipo de crud
+ if not hasattr(view_class, 'crud'):
+ return
+
+ # se o crud da view_class relativa a url a ser testada,
+ # implementa a classe CrudAux, seu link deve iniciar com /sistema
+ for string_class in list(map(str, type.mro(view_class.crud))):
+
+ if 'CrudAux' in string_class:
+ assert url.startswith('/sistema'), """
+ A url (%s) foi gerada a partir de um CrudAux,
+ o que diz que está é uma implementação de uma
+ tabela auxiliar, porém a url em questão, está fora
+ do padrão, que é iniciar com /sistema.
+ """ % (url)
+
+
+@pytest.mark.parametrize('url_item', _lista_urls)
+def test_crudaux_list_do_crud_esta_na_pagina_sistema(url_item, admin_client):
+
+ # Verifica se um crud é do tipo CrudAux, se sim, sua url deve começar
+ # com /sistema/
+ key, url, var, app_name = url_item
+ url = '/' + (url % {v: 1 for v in var})
+
+ view_class = None
+ if hasattr(key, 'view_class'):
+ view_class = key.view_class
+
+ # se não tem view_class, possivelmente não é uma classed base view
+ if not view_class:
+ return
+
+ # se não tem atributo crud, não é será nenhum tipo de crud
+ if not hasattr(view_class, 'crud'):
+ return
+
+ herancas_crud = list(map(str, type.mro(view_class.crud)))
+ for string_class in herancas_crud:
+ if 'CrudAux' in string_class:
+
+ herancas_view = list(map(str, type.mro(view_class)))
+
+ for string_view_class in herancas_view:
+ # verifica se o link para manutenção do crud está em /sistema
+ if 'ListView' in string_view_class:
+ response = admin_client.get('/sistema', {}, follow=True)
+ assert url in str(response.content), """
+ A url (%s) não consta nas Tabelas Auxiliares,
+ porem é uma implementação de ListView de CrudAux.
+ Se encontra em %s.urls
+ """ % (url, app_name)
+
+
+@pytest.mark.parametrize('urls_app', _lista_urls)
+def em_construcao_crud_permissions_urls(urls_app, client):
+ if not get_user_model().objects.exists():
+ for app in sapl_appconfs:
+ # readequa permissões dos models adicionando
+ # list e detail permissions
+ create_perms_post_migrate(app)
+ # cria usuários de perfil do sapl
+ cria_grupos_permissoes()
+ users = get_user_model().objects.values_list('username', flat=True)
+
+ for url_item in _lista_urls[urls_app]:
+
+ key, url, var, app_name = url_item
+ url = '/' + (url % {v: 1 for v in var})
+
+ app_labels = app_name.split('.')[1]
+
+ view_class = None
+ if hasattr(key, 'view_class'):
+ view_class = key.view_class
+
+ """
+ A classe PermissionRequiredForAppCrudMixin pode ser usada em uma
+ app mas envolver permissoes para outras
+ como é o caso de PainelView que está na app 'sessao'
+ mas é um redirecionamento para 'painel'... aqui é feita
+ a troca a urls_app a ser testada, por essas outras possíveis
+ """
+ if PermissionRequiredForAppCrudMixin in type.mro(view_class):
+ # essa classe deve informar app_label
+ assert hasattr(view_class, 'app_label')
+ # app_label deve ter conteudo
+ assert view_class.app_label
+ app_labels = view_class.app_label
+
+ if isinstance(app_labels, str):
+ app_labels = app_labels,
+
+ for app in app_labels:
+
+ # monta o username correspondente de a app da url a ser testada
+ user_for_url_atual_app = 'operador_%s'
+ if app in ['base', 'parlamentares']:
+ user_for_url_atual_app = user_for_url_atual_app % 'geral'
+ elif app in 'protocoloadm':
+ user_for_url_atual_app = user_for_url_atual_app % 'administrativo'
+ elif app in ['compilacao']:
+ return # TODO implementar teste para compilacao
+ else:
+ user_for_url_atual_app = user_for_url_atual_app % app
+
+ for username in users:
+ print(username, user_for_url_atual_app, url)
+
+ client.login(username=username, password='interlegis')
+
+ rg = None
+ try:
+ rg = client.get(url, {}, follow=True)
+ except:
+ pass
+
+ rp = None
+ try:
+ rp = client.post(url, {}, follow=True)
+ except:
+ pass
+
+ """
+ devido às urls serem incompletas ou com pks e outras valores
+ inexistentes na base, iniciar a execução da view, seja por get,
+ post ou qualquer outro método pode causar o erro...
+ por isso o "try ... except" acima.
+ No entanto, o objetivo do teste é validar o acesso de toda url.
+ Independente do erro que vá acontecer, esse erro não ocorrerá
+ se o user não tiver permissão de acesso pelo fato de que "AS
+ VIEWS BEM FORMADAS PARA VALIDAÇÃO DE ACESSO DEVEM SEMPRE REDIRECIONAR PARA
+ LOGIN ANTES DE SUA EXECUÇÃO", desta forma nunca gerando erro
+ interno dada qualquer incoerência de parâmetros nas urls
+ """
+ if rg:
+ """
+ Se o usuário a ser testado é o usuário da app da url de get
+ espera-se que não tenha recebido uma tela de login
+ """
+ if username == user_for_url_atual_app and\
+ not url.startswith('/sistema/'):
+ assert btn_login not in str(rg.content)
+ elif username != 'operador_geral' and\
+ url.startswith('/sistema/'):
+ assert btn_login in str(rg.content)
+ elif username == 'operador_geral' and\
+ url.startswith('/sistema/'):
+ assert btn_login not in str(rg.content)
+
+ if rp:
+ """
+ Se o usuário a ser testado é o usuário da app da url de
+ post espera-se que não tenha recebido uma tela de login
+ """
+ if username == user_for_url_atual_app and\
+ not url.startswith('/sistema/'):
+ assert btn_login not in str(rp.content)
+ elif username != 'operador_geral' and\
+ url.startswith('/sistema/'):
+ assert btn_login in str(rp.content)
+ elif username == 'operador_geral' and\
+ url.startswith('/sistema/'):
+ assert btn_login not in str(rp.content)
+
+ logout = client.get('/logout/', follow=True)
diff --git a/scripts/lista_urls.py b/scripts/lista_urls.py
new file mode 100644
index 000000000..e53169080
--- /dev/null
+++ b/scripts/lista_urls.py
@@ -0,0 +1,48 @@
+import os
+
+if __name__ == '__main__':
+
+ import django
+
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sapl.settings")
+ django.setup()
+
+if True:
+ from django.apps import apps
+ from sapl.urls import urlpatterns
+ from django.core.urlresolvers import RegexURLResolver, RegexURLPattern
+
+
+class ListaUrls():
+
+ def lista_urls(self, _urls):
+ urls = []
+ for item in _urls:
+ if isinstance(item, RegexURLResolver) and \
+ item.app_name.startswith('sapl'):
+
+ for key, value in item.reverse_dict.items():
+ if not isinstance(key, str):
+ if value:
+ url = value[0][0][0]
+ var = value[0][0][1]
+ urls.append((key, url, var, item.app_name))
+ urls.sort(key=lambda x: x[1])
+ return urls
+
+ def __call__(self):
+ return self.lista_urls(urlpatterns)
+
+
+lista_urls = ListaUrls()
+if __name__ == '__main__':
+ _lista_urls = lista_urls()
+ for url_item in _lista_urls:
+
+ params = {}
+
+ for v in url_item[2]:
+ params[v] = 1
+
+ u = '/' + url_item[1] % params
+ print(url_item[3], u)