|
|
|
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
|
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from django.utils.translation import string_concat
|
|
|
|
|
|
|
|
from sapl.crud.base import PermissionRequiredForAppCrudMixin
|
|
|
|
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)
|
|
|
|
|
|
|
|
btn_login = ('<input class="btn btn-success btn-sm" ' +
|
|
|
|
'type="submit" value="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('url_item', _lista_urls)
|
|
|
|
def test_urlpatterns(url_item, admin_client):
|
|
|
|
|
|
|
|
key, url, var, app_name = url_item
|
|
|
|
url = '/' + (url % {v: 1 for v in var})
|
|
|
|
app_name = app_name[5:]
|
|
|
|
|
|
|
|
apps_url_patterns_prefixs = {
|
|
|
|
'base': [
|
|
|
|
'/sistema',
|
|
|
|
'/login',
|
|
|
|
'/logout'
|
|
|
|
],
|
|
|
|
'comissoes': [
|
|
|
|
'/comissao',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'compilacao': [
|
|
|
|
'/ta',
|
|
|
|
],
|
|
|
|
'lexml': [
|
|
|
|
'/lexml',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'materia': [
|
|
|
|
'/materia',
|
|
|
|
'/proposicao',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'norma': [
|
|
|
|
'/norma',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'painel': [
|
|
|
|
'/painel',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'parlamentares': [
|
|
|
|
'/parlamentar',
|
|
|
|
'/mesa-diretora',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'protocoloadm': [
|
|
|
|
'/protocoloadm',
|
|
|
|
'/sistema'
|
|
|
|
],
|
|
|
|
'relatorios': [
|
|
|
|
'/relatorios',
|
|
|
|
],
|
|
|
|
'sessao': [
|
|
|
|
'/sessao',
|
|
|
|
'/sistema',
|
|
|
|
],
|
|
|
|
}
|
|
|
|
assert app_name in apps_url_patterns_prefixs, """
|
|
|
|
A app (%s) da url (%s) não consta na lista de prefixos do teste
|
|
|
|
""" % (app_name, url)
|
|
|
|
|
|
|
|
if app_name in apps_url_patterns_prefixs:
|
|
|
|
prefixs = apps_url_patterns_prefixs[app_name]
|
|
|
|
|
|
|
|
isvalid = False
|
|
|
|
for prefix in prefixs:
|
|
|
|
if url.startswith(prefix):
|
|
|
|
isvalid = True
|
|
|
|
break
|
|
|
|
|
|
|
|
assert isvalid, """
|
|
|
|
O prefixo da url (%s) não está no padrão de sua app (%s).
|
|
|
|
Os prefixos permitidos são:
|
|
|
|
%s
|
|
|
|
""" % (url, app_name, prefixs)
|
|
|
|
|
|
|
|
|
|
|
|
@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)
|
|
|
|
|
|
|
|
client.get('/logout/', follow=True)
|