diff --git a/sapl/crud/base.py b/sapl/crud/base.py index 111735f95..15aaee98a 100644 --- a/sapl/crud/base.py +++ b/sapl/crud/base.py @@ -24,11 +24,10 @@ from django.views.generic.list import MultipleObjectMixin from sapl.base.models import AppConfig as ConfiguracoesAplicacao from sapl.crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display from sapl.crispy_layout_mixin import SaplFormHelper -from sapl.rules.map_rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, +from sapl.rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST) from sapl.utils import normalize - logger = logging.getLogger(settings.BASE_DIR.name) ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \ @@ -79,7 +78,6 @@ def make_pagination(index, num_pages): head = from_to(1, PAGINATION_LENGTH - len(tail) - 1) return head + [None] + tail - """ variáveis do crud: help_topic diff --git a/sapl/rules/__init__.py b/sapl/rules/__init__.py index 780e64311..7984f6ef5 100644 --- a/sapl/rules/__init__.py +++ b/sapl/rules/__init__.py @@ -3,7 +3,37 @@ from django.utils.translation import ugettext_lazy as _ default_app_config = 'sapl.rules.apps.AppConfig' """ -Os cinco radicais de permissão completa são: +Todas as permissões do django framework seguem o padrão + + [app_label].[radical_de_permissao]_[model] + +ou seja, em sapl.norma.NormaJuridica, por exemplo, o django framework cria +três permissões registadas na classe Permission: + + definição uso + + - add_normajuridica norma.add_normajuridica + - change_normajuridica norma.change_normajuridica + - delete_normajuridica norma.delete_normajuridica + + - view_normajuridica norma.view_normajuridica + # o radical .view_ não existia no django quando a app rules foi criada + # e portanto não é utilizada + +No SAPL foram acrescidas em todos os models as duas regras abaixo, adicionadas +com o Signal post_migrate `create_proxy_permissions` +localizado em sapl.rules.apps.py. + + - list_normajuridica norma.list_normajuridica + - detail_normajuridica norma.detail_normajuridica + +Tanto o Crud implementado em sapl.crud.base.py quanto o Signal post_migrate +`update_groups` que é responsável por ler o mapa do +arquivo (sapl.rules.map_rules.py) e criar os grupos definidos na regra de +negócio trabalham com os cinco radiais de permissão +e com qualquer outro tipo de permissão customizada, nesta ordem de precedência. + +Os cinco radicais de permissão são, portanto: RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ '.list_', '.detail_', '.add_', '.change_', '.delete_', @@ -12,13 +42,21 @@ Tanto a app crud quanto a app rules estão sempre ligadas a um model. Ao lidar com permissões, sempre é analisado se é apenas um radical ou permissão completa, sendo apenas um radical, a permissão completa é montada com base no model associado. + +NESTE ARQUIVO ESTÃO DEFINIDOS OS RADICAIS E OS GRUPOS DEFAULT DO SAPL + """ -RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ +RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE = \ '.list_', '.detail_', '.add_', '.change_', '.delete_', +__base__ = [RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE] +__listdetailchange__ = [RP_LIST, RP_DETAIL, RP_CHANGE] + +__perms_publicas__ = {RP_LIST, RP_DETAIL} SAPL_GROUP_ADMINISTRATIVO = _("Operador Administrativo") +SAPL_GROUP_AUDIENCIA = _("Operador de Audiência") SAPL_GROUP_PROTOCOLO = _("Operador de Protocolo Administrativo") SAPL_GROUP_COMISSOES = _("Operador de Comissões") SAPL_GROUP_MATERIA = _("Operador de Matéria") diff --git a/sapl/rules/group_administrativo.py b/sapl/rules/group_administrativo.py new file mode 100644 index 000000000..0e5ec2f78 --- /dev/null +++ b/sapl/rules/group_administrativo.py @@ -0,0 +1,16 @@ + +from sapl.materia import models as materia +from sapl.protocoloadm import models as protocoloadm +from sapl.rules import SAPL_GROUP_ADMINISTRATIVO, __base__, __perms_publicas__ + +rules_group_administrativo = { + 'group': SAPL_GROUP_ADMINISTRATIVO, + 'rules': [ + (materia.MateriaLegislativa, [ + 'can_access_impressos'], __perms_publicas__), + (protocoloadm.DocumentoAdministrativo, __base__, set()), + (protocoloadm.Anexado, __base__, set()), + (protocoloadm.DocumentoAcessorioAdministrativo, __base__, set()), + (protocoloadm.TramitacaoAdministrativo, __base__, set()), + ] +} diff --git a/sapl/rules/group_anonymous.py b/sapl/rules/group_anonymous.py new file mode 100644 index 000000000..47c7a14be --- /dev/null +++ b/sapl/rules/group_anonymous.py @@ -0,0 +1,14 @@ + +from sapl.materia import models as materia +from sapl.protocoloadm import models as protocoloadm +from sapl.rules import SAPL_GROUP_ANONYMOUS, RP_ADD, RP_DELETE + +# não possui efeito e é usada nos testes que verificam se todos os models estão +# neste arquivo rules.py +rules_group_anonymous = { + 'group': SAPL_GROUP_ANONYMOUS, + 'rules': [ + (materia.AcompanhamentoMateria, [RP_ADD, RP_DELETE], set()), + (protocoloadm.AcompanhamentoDocumento, [RP_ADD, RP_DELETE], set()), + ] +} diff --git a/sapl/rules/group_audiencia.py b/sapl/rules/group_audiencia.py new file mode 100644 index 000000000..870dc05c7 --- /dev/null +++ b/sapl/rules/group_audiencia.py @@ -0,0 +1,10 @@ +from sapl.audiencia import models as audiencia +from sapl.rules import SAPL_GROUP_AUDIENCIA, __base__, __perms_publicas__ +rules_group_audiencia = { + 'group': SAPL_GROUP_AUDIENCIA, + 'rules': [ + (audiencia.AudienciaPublica, __base__, __perms_publicas__), + (audiencia.TipoAudienciaPublica, __base__, __perms_publicas__), + (audiencia.AnexoAudienciaPublica, __base__, __perms_publicas__), + ] +} diff --git a/sapl/rules/group_autor.py b/sapl/rules/group_autor.py new file mode 100644 index 000000000..a555074a2 --- /dev/null +++ b/sapl/rules/group_autor.py @@ -0,0 +1,13 @@ +from sapl.compilacao import models as compilacao +from sapl.materia import models as materia +from sapl.rules import SAPL_GROUP_AUTOR, __base__, __perms_publicas__ +rules_group_autor = { + 'group': SAPL_GROUP_AUTOR, + 'rules': [ + (materia.Proposicao, __base__, set()), + (materia.HistoricoProposicao, __base__, set()), + (compilacao.Dispositivo, __base__ + [ + 'change_your_dispositivo_edicao_dinamica', + ], __perms_publicas__) + ] +} diff --git a/sapl/rules/group_comissoes.py b/sapl/rules/group_comissoes.py new file mode 100644 index 000000000..980cbd0eb --- /dev/null +++ b/sapl/rules/group_comissoes.py @@ -0,0 +1,16 @@ + +from sapl.comissoes import models as comissoes +from sapl.materia import models as materia +from sapl.rules import SAPL_GROUP_COMISSOES, __base__, __perms_publicas__ +rules_group_comissoes = { + 'group': SAPL_GROUP_COMISSOES, + 'rules': [ + (materia.PautaReuniao, __base__, __perms_publicas__), + (comissoes.Comissao, __base__, __perms_publicas__), + (comissoes.Composicao, __base__, __perms_publicas__), + (comissoes.Participacao, __base__, __perms_publicas__), + (materia.Relatoria, __base__, __perms_publicas__), + (comissoes.Reuniao, __base__, __perms_publicas__), + (comissoes.DocumentoAcessorio, __base__, __perms_publicas__), + ] +} diff --git a/sapl/rules/group_geral.py b/sapl/rules/group_geral.py new file mode 100644 index 000000000..0a7b2579a --- /dev/null +++ b/sapl/rules/group_geral.py @@ -0,0 +1,116 @@ +from sapl.audiencia import models as audiencia +from sapl.base import models as base +from sapl.comissoes import models as comissoes +from sapl.compilacao import models as compilacao +from sapl.lexml import models as lexml +from sapl.materia import models as materia +from sapl.norma import models as norma +from sapl.parlamentares import models as parlamentares +from sapl.protocoloadm import models as protocoloadm +from sapl.rules import SAPL_GROUP_GERAL, RP_ADD, __base__, __perms_publicas__, \ + __listdetailchange__ +from sapl.sessao import models as sessao + +rules_group_geral = { + 'group': SAPL_GROUP_GERAL, + 'rules': [ + (base.AppConfig, __base__ + [ + 'menu_sistemas', + 'view_tabelas_auxiliares' + ], set()), + + (base.CasaLegislativa, __listdetailchange__ + + [RP_ADD], __perms_publicas__), + (base.TipoAutor, __base__, __perms_publicas__), + (base.Autor, __base__, __perms_publicas__), + (base.OperadorAutor, __base__, __perms_publicas__), + (base.AuditLog, __base__, set()), + + (protocoloadm.StatusTramitacaoAdministrativo, __base__, set()), + (protocoloadm.TipoDocumentoAdministrativo, __base__, set()), + + (comissoes.CargoComissao, __base__, __perms_publicas__), + (comissoes.TipoComissao, __base__, __perms_publicas__), + (comissoes.Periodo, __base__, __perms_publicas__), + + (materia.AssuntoMateria, __base__, + __perms_publicas__), + (materia.MateriaAssunto, __base__, + __perms_publicas__), + (materia.MateriaLegislativa, [ + 'can_access_impressos'], __perms_publicas__), + (materia.TipoProposicao, __base__, __perms_publicas__), + (materia.TipoMateriaLegislativa, __base__, __perms_publicas__), + (materia.RegimeTramitacao, __base__, __perms_publicas__), + (materia.Origem, __base__, __perms_publicas__), + (materia.TipoDocumento, __base__, __perms_publicas__), + (materia.Orgao, __base__, __perms_publicas__), + (materia.TipoFimRelatoria, __base__, __perms_publicas__), + (materia.Parecer, __base__, __perms_publicas__), + (materia.StatusTramitacao, __base__, __perms_publicas__), + (materia.UnidadeTramitacao, __base__, __perms_publicas__), + (materia.ConfigEtiquetaMateriaLegislativa, __base__, set()), + + (norma.AssuntoNorma, __base__, __perms_publicas__), + (norma.TipoNormaJuridica, __base__, __perms_publicas__), + (norma.TipoVinculoNormaJuridica, __base__, __perms_publicas__), + (norma.NormaEstatisticas, __base__, __perms_publicas__), + + (parlamentares.Legislatura, __base__, __perms_publicas__), + (parlamentares.SessaoLegislativa, __base__, __perms_publicas__), + (parlamentares.Coligacao, __base__, __perms_publicas__), + (parlamentares.ComposicaoColigacao, __base__, __perms_publicas__), + (parlamentares.Partido, __base__, __perms_publicas__), + (parlamentares.NivelInstrucao, __base__, __perms_publicas__), + (parlamentares.SituacaoMilitar, __base__, __perms_publicas__), + (parlamentares.Parlamentar, __base__, __perms_publicas__), + (parlamentares.TipoDependente, __base__, __perms_publicas__), + (parlamentares.Dependente, __base__, __perms_publicas__), + (parlamentares.Filiacao, __base__, __perms_publicas__), + (parlamentares.TipoAfastamento, __base__, __perms_publicas__), + (parlamentares.Mandato, __base__, __perms_publicas__), + (parlamentares.CargoMesa, __base__, __perms_publicas__), + (parlamentares.ComposicaoMesa, __base__, __perms_publicas__), + (parlamentares.Frente, __base__, __perms_publicas__), + (parlamentares.FrenteCargo, __base__, __perms_publicas__), + (parlamentares.FrenteParlamentar, __base__, __perms_publicas__), + (parlamentares.Votante, __base__, __perms_publicas__), + (parlamentares.Bloco, __base__, __perms_publicas__), + (parlamentares.BlocoCargo, __base__, __perms_publicas__), + (parlamentares.BlocoMembro, __base__, __perms_publicas__), + + (sessao.CargoBancada, __base__, __perms_publicas__), + (sessao.Bancada, __base__, __perms_publicas__), + (sessao.TipoSessaoPlenaria, __base__, __perms_publicas__), + (sessao.TipoResultadoVotacao, __base__, __perms_publicas__), + (sessao.TipoExpediente, __base__, __perms_publicas__), + (sessao.TipoJustificativa, __base__, __perms_publicas__), + (sessao.JustificativaAusencia, __base__, __perms_publicas__), + (sessao.ResumoOrdenacao, __base__, __perms_publicas__), + (sessao.TipoRetiradaPauta, __base__, __perms_publicas__), + + (lexml.LexmlProvedor, __base__, set()), + (lexml.LexmlPublicador, __base__, set()), + + (compilacao.VeiculoPublicacao, __base__, __perms_publicas__), + (compilacao.TipoTextoArticulado, __base__, __perms_publicas__), + (compilacao.TipoNota, __base__, __perms_publicas__), + (compilacao.TipoVide, __base__, __perms_publicas__), + (compilacao.TipoPublicacao, __base__, __perms_publicas__), + + # este model é um espelho do model integrado e sua edição pode + # confundir Autores, operadores de matéria e/ou norma. + # Por isso está adicionado apenas para o operador geral + (compilacao.TextoArticulado, + __base__ + ['lock_unlock_textoarticulado'], set()), + + # estes tres models são complexos e a principio apenas o admin tem perm + (compilacao.TipoDispositivo, [], set()), + (compilacao.TipoDispositivoRelationship, [], set()), + (compilacao.PerfilEstruturalTextoArticulado, [], set()), + + (audiencia.AudienciaPublica, __base__, __perms_publicas__), + (audiencia.TipoAudienciaPublica, __base__, __perms_publicas__), + + ] +} diff --git a/sapl/rules/group_materia.py b/sapl/rules/group_materia.py new file mode 100644 index 000000000..c5e855a82 --- /dev/null +++ b/sapl/rules/group_materia.py @@ -0,0 +1,36 @@ + +from sapl.compilacao import models as compilacao +from sapl.materia import models as materia +from sapl.norma import models as norma +from sapl.rules import SAPL_GROUP_MATERIA, __base__, __perms_publicas__ + +rules_group_materia = { + 'group': SAPL_GROUP_MATERIA, + 'rules': [ + (materia.Anexada, __base__, __perms_publicas__), + (materia.Autoria, __base__, __perms_publicas__), + (materia.DespachoInicial, __base__, __perms_publicas__), + (materia.DocumentoAcessorio, __base__, __perms_publicas__), + (materia.MateriaAssunto, __base__, __perms_publicas__), + (materia.AssuntoMateria, __base__, __perms_publicas__), + + (materia.MateriaLegislativa, __base__ + + ['can_access_impressos'], __perms_publicas__), + (materia.Numeracao, __base__, __perms_publicas__), + (materia.Tramitacao, __base__, __perms_publicas__), + (materia.MateriaEmTramitacao, __base__, __perms_publicas__), + (norma.LegislacaoCitada, __base__, __perms_publicas__), + (norma.AutoriaNorma, __base__, __perms_publicas__), + (compilacao.Dispositivo, __base__ + [ + 'change_dispositivo_edicao_dinamica', + + # TODO: adicionar 'change_dispositivo_registros_compilacao' + # quando testes forem feitos para permtir que matérias possam + # ser vinculadas a outras matérias via registro de compilação. + # Normalmente emendas e/ou projetos substitutivos podem alterar + # uma matéria original. + # Fazer esse registro de compilação ofereceria + # um autografo eletrônico pronto para ser convertido em Norma. + ], __perms_publicas__) + ] +} diff --git a/sapl/rules/group_norma.py b/sapl/rules/group_norma.py new file mode 100644 index 000000000..13a201fd0 --- /dev/null +++ b/sapl/rules/group_norma.py @@ -0,0 +1,28 @@ +from sapl.compilacao import models as compilacao +from sapl.norma import models as norma +from sapl.rules import SAPL_GROUP_NORMA, __base__, __perms_publicas__ + +rules_group_norma = { + 'group': SAPL_GROUP_NORMA, + 'rules': [ + (norma.NormaJuridica, __base__, __perms_publicas__), + (norma.NormaRelacionada, __base__, __perms_publicas__), + (norma.AnexoNormaJuridica, __base__, __perms_publicas__), + (norma.AutoriaNorma, __base__, __perms_publicas__), + (norma.NormaEstatisticas, __base__, __perms_publicas__), + + # Publicacao está com permissão apenas para norma e não para matéria + # e proposições apenas por análise do contexto, não é uma limitação + # da ferramenta. + (compilacao.Publicacao, __base__, __perms_publicas__), + (compilacao.Vide, __base__, __perms_publicas__), + (compilacao.Nota, __base__, __perms_publicas__), + (compilacao.Dispositivo, __base__ + [ + 'view_dispositivo_notificacoes', + 'change_dispositivo_edicao_dinamica', + 'change_dispositivo_edicao_avancada', + 'change_dispositivo_registros_compilacao', + 'change_dispositivo_de_vigencia_global' + ], __perms_publicas__) + ] +} diff --git a/sapl/rules/group_painel.py b/sapl/rules/group_painel.py new file mode 100644 index 000000000..4e2504a86 --- /dev/null +++ b/sapl/rules/group_painel.py @@ -0,0 +1,10 @@ +from sapl.painel import models as painel +from sapl.rules import SAPL_GROUP_PAINEL, __base__, __perms_publicas__ + +rules_group_painel = { + 'group': SAPL_GROUP_PAINEL, + 'rules': [ + (painel.Painel, __base__, __perms_publicas__), + (painel.Cronometro, __base__, __perms_publicas__), + ] +} diff --git a/sapl/rules/group_protocolo.py b/sapl/rules/group_protocolo.py new file mode 100644 index 000000000..de23e5de7 --- /dev/null +++ b/sapl/rules/group_protocolo.py @@ -0,0 +1,26 @@ +from sapl.compilacao import models as compilacao +from sapl.materia import models as materia +from sapl.protocoloadm import models as protocoloadm +from sapl.rules import SAPL_GROUP_PROTOCOLO, RP_ADD, __base__, __listdetailchange__, \ + __perms_publicas__ + +rules_group_protocolo = { + 'group': SAPL_GROUP_PROTOCOLO, + 'rules': [ + (protocoloadm.Protocolo, __base__ + ['action_anular_protocolo'], set()), + (protocoloadm.DocumentoAdministrativo, [RP_ADD] + __listdetailchange__, set()), + (protocoloadm.DocumentoAcessorioAdministrativo, __listdetailchange__, set()), + + (materia.MateriaLegislativa, __listdetailchange__, __perms_publicas__), + (materia.MateriaLegislativa, ['can_access_impressos'], __perms_publicas__), + (materia.DocumentoAcessorio, __listdetailchange__, __perms_publicas__), + (materia.Anexada, __base__, __perms_publicas__), + (materia.Autoria, __base__, __perms_publicas__), + + (materia.Proposicao, ['detail_proposicao_enviada', + 'detail_proposicao_devolvida', + 'detail_proposicao_incorporada'], set()), # TODO: tratar em sapl.api questão de que proposições incorporadas serem públicas + (materia.HistoricoProposicao, __base__, set()), + (compilacao.TextoArticulado, ['view_restricted_textoarticulado'], __perms_publicas__) + ] +} diff --git a/sapl/rules/group_sessao.py b/sapl/rules/group_sessao.py new file mode 100644 index 000000000..92015eece --- /dev/null +++ b/sapl/rules/group_sessao.py @@ -0,0 +1,25 @@ + +from sapl.rules import SAPL_GROUP_SESSAO, __perms_publicas__, __base__ +from sapl.sessao import models as sessao + +rules_group_sessao = { + 'group': SAPL_GROUP_SESSAO, + 'rules': [ + (sessao.SessaoPlenaria, __base__, __perms_publicas__), + (sessao.SessaoPlenariaPresenca, __base__, __perms_publicas__), + (sessao.ExpedienteMateria, __base__, __perms_publicas__), + (sessao.OcorrenciaSessao, __base__, __perms_publicas__), + (sessao.IntegranteMesa, __base__, __perms_publicas__), + (sessao.ExpedienteSessao, __base__, __perms_publicas__), + (sessao.Orador, __base__, __perms_publicas__), + (sessao.OradorExpediente, __base__, __perms_publicas__), + (sessao.OradorOrdemDia, __base__, __perms_publicas__), + (sessao.OrdemDia, __base__, __perms_publicas__), + (sessao.PresencaOrdemDia, __base__, __perms_publicas__), + (sessao.RegistroVotacao, __base__, __perms_publicas__), + (sessao.VotoParlamentar, __base__, __perms_publicas__), + (sessao.JustificativaAusencia, __base__, __perms_publicas__), + (sessao.RetiradaPauta, __base__, __perms_publicas__), + (sessao.RegistroLeitura, __base__, __perms_publicas__), + ] +} diff --git a/sapl/rules/group_votante.py b/sapl/rules/group_votante.py new file mode 100644 index 000000000..430c1ea29 --- /dev/null +++ b/sapl/rules/group_votante.py @@ -0,0 +1,10 @@ + +from sapl.parlamentares import models as parlamentares +from sapl.rules import SAPL_GROUP_VOTANTE + +rules_group_votante = { + 'group': SAPL_GROUP_VOTANTE, + 'rules': [ + (parlamentares.Votante, ['can_vote'], set()) + ] +} diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index e4aa467dc..fb59e1e36 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -1,347 +1,74 @@ -""" -Todas as permissões do django framework seguem o padrão - - [app_label].[radical_de_permissao]_[model] - -ou seja, em sapl.norma.NormaJuridica, por exemplo, o django framework cria -três permissões registadas na classe Permission: - - definição uso - - - add_normajuridica norma.add_normajuridica - - change_normajuridica norma.change_normajuridica - - delete_normajuridica norma.delete_normajuridica - -No SAPL foram acrescidas em todos os models as duas regras abaixo, adicionadas -com o Signal post_migrate `create_proxy_permissions` -localizado em sapl.rules.apps.py. - - - list_normajuridica norma.list_normajuridica - - detail_normajuridica norma.detail_normajuridica - -Tanto o Crud implementado em sapl.crud.base.py quanto o Signal post_migrate -`update_groups` que é responsável por ler o mapa deste -arquivo (sapl.rules.map_rules.py) e criar os grupos definidos na regra de -negócio trabalham com os cinco radiais de permissão -e com qualquer outro tipo de permissão customizada, nesta ordem de precedência. - -""" -from sapl.audiencia import models as audiencia -from sapl.base import models as base -from sapl.comissoes import models as comissoes -from sapl.compilacao import models as compilacao -from sapl.lexml import models as lexml -from sapl.materia import models as materia -from sapl.norma import models as norma -from sapl.painel import models as painel -from sapl.parlamentares import models as parlamentares -from sapl.protocoloadm import models as protocoloadm -from sapl.rules import (RP_ADD, RP_CHANGE, RP_DELETE, RP_DETAIL, RP_LIST, - SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_ANONYMOUS, - SAPL_GROUP_AUTOR, SAPL_GROUP_COMISSOES, - SAPL_GROUP_GERAL, SAPL_GROUP_LOGIN_SOCIAL, - SAPL_GROUP_MATERIA, SAPL_GROUP_NORMA, - SAPL_GROUP_PAINEL, - SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO, - SAPL_GROUP_VOTANTE) -from sapl.sessao import models as sessao - +from sapl.rules import SAPL_GROUP_LOGIN_SOCIAL +from sapl.rules.group_administrativo import rules_group_administrativo +from sapl.rules.group_anonymous import rules_group_anonymous +from sapl.rules.group_audiencia import rules_group_audiencia +from sapl.rules.group_autor import rules_group_autor +from sapl.rules.group_comissoes import rules_group_comissoes +from sapl.rules.group_geral import rules_group_geral +from sapl.rules.group_materia import rules_group_materia +from sapl.rules.group_norma import rules_group_norma +from sapl.rules.group_painel import rules_group_painel +from sapl.rules.group_protocolo import rules_group_protocolo +from sapl.rules.group_sessao import rules_group_sessao +from sapl.rules.group_votante import rules_group_votante -__base__ = [RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE] -__listdetailchange__ = [RP_LIST, RP_DETAIL, RP_CHANGE] - -__perms_publicas__ = {RP_LIST, RP_DETAIL} - - -rules_group_administrativo = { - 'group': SAPL_GROUP_ADMINISTRATIVO, - 'rules': [ - (materia.MateriaLegislativa, [ - 'can_access_impressos'], __perms_publicas__), - # TODO: tratar em sapl.api a questão de ostencivo e restritivo - (protocoloadm.DocumentoAdministrativo, __base__, set()), - (protocoloadm.Anexado, __base__, set()), - (protocoloadm.DocumentoAcessorioAdministrativo, __base__, set()), - (protocoloadm.TramitacaoAdministrativo, __base__, set()), - ] -} - -rules_group_audiencia = { - 'group': SAPL_GROUP_GERAL, - 'rules': [ - (audiencia.AudienciaPublica, __base__, __perms_publicas__), - (audiencia.TipoAudienciaPublica, __base__, __perms_publicas__), - (audiencia.AnexoAudienciaPublica, __base__, __perms_publicas__), - ] -} - - -rules_group_protocolo = { - 'group': SAPL_GROUP_PROTOCOLO, - 'rules': [ - (protocoloadm.Protocolo, __base__ + [ - 'action_anular_protocolo'], set()), - (protocoloadm.DocumentoAdministrativo, - [RP_ADD] + __listdetailchange__, set()), - (protocoloadm.DocumentoAcessorioAdministrativo, __listdetailchange__, set()), - - (materia.MateriaLegislativa, __listdetailchange__, __perms_publicas__), - (materia.MateriaLegislativa, [ - 'can_access_impressos'], __perms_publicas__), - (materia.DocumentoAcessorio, __listdetailchange__, __perms_publicas__), - (materia.Anexada, __base__, __perms_publicas__), - (materia.Autoria, __base__, __perms_publicas__), - - (materia.Proposicao, ['detail_proposicao_enviada', - 'detail_proposicao_devolvida', - 'detail_proposicao_incorporada'], set()), # TODO: tratar em sapl.api questão de que proposições incorporadas serem públicas - (materia.HistoricoProposicao, __base__, set()), - (compilacao.TextoArticulado, [ - 'view_restricted_textoarticulado'], __perms_publicas__) - ] -} - -rules_group_comissoes = { - 'group': SAPL_GROUP_COMISSOES, - 'rules': [ - (materia.PautaReuniao, __base__, __perms_publicas__), - (comissoes.Comissao, __base__, __perms_publicas__), - (comissoes.Composicao, __base__, __perms_publicas__), - (comissoes.Participacao, __base__, __perms_publicas__), - (materia.Relatoria, __base__, __perms_publicas__), - (comissoes.Reuniao, __base__, __perms_publicas__), - (comissoes.DocumentoAcessorio, __base__, __perms_publicas__), - ] -} - -rules_group_materia = { - 'group': SAPL_GROUP_MATERIA, - 'rules': [ - (materia.Anexada, __base__, __perms_publicas__), - (materia.Autoria, __base__, __perms_publicas__), - (materia.DespachoInicial, __base__, __perms_publicas__), - (materia.DocumentoAcessorio, __base__, __perms_publicas__), - (materia.MateriaAssunto, __base__, __perms_publicas__), - (materia.AssuntoMateria, __base__, __perms_publicas__), - - (materia.MateriaLegislativa, __base__ + - ['can_access_impressos'], __perms_publicas__), - (materia.Numeracao, __base__, __perms_publicas__), - (materia.Tramitacao, __base__, __perms_publicas__), - (materia.MateriaEmTramitacao, __base__, __perms_publicas__), - (norma.LegislacaoCitada, __base__, __perms_publicas__), - (norma.AutoriaNorma, __base__, __perms_publicas__), - (compilacao.Dispositivo, __base__ + [ - 'change_dispositivo_edicao_dinamica', - - # TODO: adicionar 'change_dispositivo_registros_compilacao' - # quando testes forem feitos para permtir que matérias possam - # ser vinculadas a outras matérias via registro de compilação. - # Normalmente emendas e/ou projetos substitutivos podem alterar - # uma matéria original. - # Fazer esse registro de compilação ofereceria - # um autografo eletrônico pronto para ser convertido em Norma. - ], __perms_publicas__) - ] +rules_group_login_social = { + 'group': SAPL_GROUP_LOGIN_SOCIAL, + 'rules': [] } +""" +ESTRUTURA DAS RULES DEFINIDAS NOS ARQUIVOS GROUP_[DEFINICAO].PY -rules_group_norma = { - 'group': SAPL_GROUP_NORMA, - 'rules': [ - (norma.NormaJuridica, __base__, __perms_publicas__), - (norma.NormaRelacionada, __base__, __perms_publicas__), - (norma.AnexoNormaJuridica, __base__, __perms_publicas__), - (norma.AutoriaNorma, __base__, __perms_publicas__), - (norma.NormaEstatisticas, __base__, __perms_publicas__), - - # Publicacao está com permissão apenas para norma e não para matéria - # e proposições apenas por análise do contexto, não é uma limitação - # da ferramenta. - (compilacao.Publicacao, __base__, __perms_publicas__), - (compilacao.Vide, __base__, __perms_publicas__), - (compilacao.Nota, __base__, __perms_publicas__), - (compilacao.Dispositivo, __base__ + [ - 'view_dispositivo_notificacoes', - 'change_dispositivo_edicao_dinamica', - 'change_dispositivo_edicao_avancada', - 'change_dispositivo_registros_compilacao', - 'change_dispositivo_de_vigencia_global' - ], __perms_publicas__) - ] -} +todos as rules de groups são um dicionario com duas chaves: 'group' e 'rules' -rules_group_sessao = { - 'group': SAPL_GROUP_SESSAO, - 'rules': [ - (sessao.SessaoPlenaria, __base__, __perms_publicas__), - (sessao.SessaoPlenariaPresenca, __base__, __perms_publicas__), - (sessao.ExpedienteMateria, __base__, __perms_publicas__), - (sessao.OcorrenciaSessao, __base__, __perms_publicas__), - (sessao.IntegranteMesa, __base__, __perms_publicas__), - (sessao.ExpedienteSessao, __base__, __perms_publicas__), - (sessao.Orador, __base__, __perms_publicas__), - (sessao.OradorExpediente, __base__, __perms_publicas__), - (sessao.OradorOrdemDia, __base__, __perms_publicas__), - (sessao.OrdemDia, __base__, __perms_publicas__), - (sessao.PresencaOrdemDia, __base__, __perms_publicas__), - (sessao.RegistroVotacao, __base__, __perms_publicas__), - (sessao.VotoParlamentar, __base__, __perms_publicas__), - (sessao.JustificativaAusencia, __base__, __perms_publicas__), - (sessao.RetiradaPauta, __base__, __perms_publicas__), - (sessao.RegistroLeitura, __base__, __perms_publicas__), - ] -} +'group' precisa ser um dos grupos definidos em sapl.rules.__init__.py -rules_group_painel = { - 'group': SAPL_GROUP_PAINEL, - 'rules': [ - (painel.Painel, __base__, __perms_publicas__), - (painel.Cronometro, __base__, __perms_publicas__), - ] -} +'rules' é uma lista de tuplas de três posições, onde + 0 - de que model se trata + 1 - list - quais permissões possui um usuário ligado ao grupo para o model da posição 0 + - também indica ao CRUD que sua subclasse ligada a um radical precisa exigir credencial + 2 - set - indica a API quais permissões são públicas, ou seja, + se está no set é um o acesso ao endpoint é público -rules_group_autor = { - 'group': SAPL_GROUP_AUTOR, - 'rules': [ - (materia.Proposicao, __base__, set()), - (materia.HistoricoProposicao, __base__, set()), - (compilacao.Dispositivo, __base__ + [ - 'change_your_dispositivo_edicao_dinamica', - ], __perms_publicas__) - ] -} +exemplo: -rules_group_votante = { - 'group': SAPL_GROUP_VOTANTE, +rules_group_exemplo = { + 'group': SAPL_GROUP_EXEMPLO, 'rules': [ - (parlamentares.Votante, ['can_vote'], set()) + ( + model_exemplo1, + ( RP_LIST, RP_DETAIL ), + set() + ), + ( + model_exemplo2, + (RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE), + {RP_LIST, RP_DETAIL} + ), ] } -rules_group_geral = { - 'group': SAPL_GROUP_GERAL, - 'rules': [ - (base.AppConfig, __base__ + [ - 'menu_sistemas', - 'view_tabelas_auxiliares' - ], set()), - - (base.CasaLegislativa, __listdetailchange__ + - [RP_ADD], __perms_publicas__), - (base.TipoAutor, __base__, __perms_publicas__), - (base.Autor, __base__, __perms_publicas__), - (base.OperadorAutor, __base__, __perms_publicas__), - (base.AuditLog, __base__, set()), - - (protocoloadm.StatusTramitacaoAdministrativo, __base__, set()), - (protocoloadm.TipoDocumentoAdministrativo, __base__, set()), - - (comissoes.CargoComissao, __base__, __perms_publicas__), - (comissoes.TipoComissao, __base__, __perms_publicas__), - (comissoes.Periodo, __base__, __perms_publicas__), - - (materia.AssuntoMateria, __base__, - __perms_publicas__), # não há implementação - (materia.MateriaAssunto, __base__, - __perms_publicas__), # não há implementação - (materia.MateriaLegislativa, [ - 'can_access_impressos'], __perms_publicas__), - (materia.TipoProposicao, __base__, __perms_publicas__), - (materia.TipoMateriaLegislativa, __base__, __perms_publicas__), - (materia.RegimeTramitacao, __base__, __perms_publicas__), - (materia.Origem, __base__, __perms_publicas__), - (materia.TipoDocumento, __base__, __perms_publicas__), - (materia.Orgao, __base__, __perms_publicas__), - (materia.TipoFimRelatoria, __base__, __perms_publicas__), - (materia.Parecer, __base__, __perms_publicas__), - (materia.StatusTramitacao, __base__, __perms_publicas__), - (materia.UnidadeTramitacao, __base__, __perms_publicas__), - (materia.ConfigEtiquetaMateriaLegislativa, __base__, set()), - - - (norma.AssuntoNorma, __base__, __perms_publicas__), - (norma.TipoNormaJuridica, __base__, __perms_publicas__), - (norma.TipoVinculoNormaJuridica, __base__, __perms_publicas__), - (norma.NormaEstatisticas, __base__, __perms_publicas__), +rules_group_exemplo['rules'][0] + 1 significa q usuários que estão no grupo SAPL_GROUP_EXEMPLO + só podem acessar o que está em rules_group_exemplo['rules'][0][1], ou seja, + listar e ver os detalhes de model_exemplo1 - (parlamentares.Legislatura, __base__, __perms_publicas__), - (parlamentares.SessaoLegislativa, __base__, __perms_publicas__), - (parlamentares.Coligacao, __base__, __perms_publicas__), - (parlamentares.ComposicaoColigacao, __base__, __perms_publicas__), - (parlamentares.Partido, __base__, __perms_publicas__), - (parlamentares.NivelInstrucao, __base__, __perms_publicas__), - (parlamentares.SituacaoMilitar, __base__, __perms_publicas__), - (parlamentares.Parlamentar, __base__, __perms_publicas__), - (parlamentares.TipoDependente, __base__, __perms_publicas__), - (parlamentares.Dependente, __base__, __perms_publicas__), - (parlamentares.Filiacao, __base__, __perms_publicas__), - (parlamentares.TipoAfastamento, __base__, __perms_publicas__), - (parlamentares.Mandato, __base__, __perms_publicas__), - (parlamentares.CargoMesa, __base__, __perms_publicas__), - (parlamentares.ComposicaoMesa, __base__, __perms_publicas__), - (parlamentares.Frente, __base__, __perms_publicas__), - (parlamentares.FrenteCargo, __base__, __perms_publicas__), - (parlamentares.FrenteParlamentar, __base__, __perms_publicas__), - (parlamentares.Votante, __base__, __perms_publicas__), - (parlamentares.Bloco, __base__, __perms_publicas__), - (parlamentares.BlocoCargo, __base__, __perms_publicas__), - (parlamentares.BlocoMembro, __base__, __perms_publicas__), + 1 significa também que o crud exigirá tais credenciais no listview e detailview + 2 set() diz que, na API, não existe acesso anônimo - (sessao.CargoBancada, __base__, __perms_publicas__), - (sessao.Bancada, __base__, __perms_publicas__), - (sessao.TipoSessaoPlenaria, __base__, __perms_publicas__), - (sessao.TipoResultadoVotacao, __base__, __perms_publicas__), - (sessao.TipoExpediente, __base__, __perms_publicas__), - (sessao.TipoJustificativa, __base__, __perms_publicas__), - (sessao.JustificativaAusencia, __base__, __perms_publicas__), - (sessao.ResumoOrdenacao, __base__, __perms_publicas__), - (sessao.TipoRetiradaPauta, __base__, __perms_publicas__), +-------------------------- - (lexml.LexmlProvedor, __base__, set()), - (lexml.LexmlPublicador, __base__, set()), +rules_group_exemplo['rules'][1] + 1 significa q usuários que estão no grupo SAPL_GROUP_EXEMPLO + podem acessar o que está em rules_group_exemplo['rules'][1][1], ou seja, + listar, ver detalhes, editar, apagar e adicionar registros de model_exemplo2 - (compilacao.VeiculoPublicacao, __base__, __perms_publicas__), - (compilacao.TipoTextoArticulado, __base__, __perms_publicas__), - (compilacao.TipoNota, __base__, __perms_publicas__), - (compilacao.TipoVide, __base__, __perms_publicas__), - (compilacao.TipoPublicacao, __base__, __perms_publicas__), + 1 significa também que o crud exigirá tais credenciais em todos as suas views - # este model é um espelho do model integrado e sua edição pode - # confundir Autores, operadores de matéria e/ou norma. - # Por isso está adicionado apenas para o operador geral - (compilacao.TextoArticulado, - __base__ + ['lock_unlock_textoarticulado'], set()), + 2 {RP_LIST, RP_DETAIL} diz que, na API, só list e detail pode ser acessado sem credencial. - # estes tres models são complexos e a principio apenas o admin tem perm - (compilacao.TipoDispositivo, [], set()), - (compilacao.TipoDispositivoRelationship, [], set()), - (compilacao.PerfilEstruturalTextoArticulado, [], set()), - - (audiencia.AudienciaPublica, __base__, __perms_publicas__), - (audiencia.TipoAudienciaPublica, __base__, __perms_publicas__), - - - - - ] -} - - -# não possui efeito e é usada nos testes que verificam se todos os models estão -# neste arquivo rules.py -rules_group_anonymous = { - 'group': SAPL_GROUP_ANONYMOUS, - 'rules': [ - (materia.AcompanhamentoMateria, [RP_ADD, RP_DELETE], set()), - (protocoloadm.AcompanhamentoDocumento, [RP_ADD, RP_DELETE], set()), - ] -} - -rules_group_login_social = { - 'group': SAPL_GROUP_LOGIN_SOCIAL, - 'rules': [] -} +""" rules_group_geral['rules'] = (rules_group_geral['rules'] + rules_group_administrativo['rules'] + @@ -354,7 +81,6 @@ rules_group_geral['rules'] = (rules_group_geral['rules'] + rules_group_painel['rules'] + rules_group_login_social['rules']) - rules_patterns = [ rules_group_audiencia, rules_group_administrativo, @@ -368,11 +94,10 @@ rules_patterns = [ rules_group_autor, rules_group_votante, - rules_group_anonymous, # anotação para validação do teste de rules + rules_group_anonymous, # anotação para validação do teste de rules rules_group_login_social # TODO não implementado ] - rules_patterns_public = {} @@ -381,13 +106,13 @@ def _get_registration_key(model): for rules_group in rules_patterns: - for rules in rules_group['rules']: - key = _get_registration_key(rules[0]) + for rs in rules_group['rules']: + key = _get_registration_key(rs[0]) if key not in rules_patterns_public: rules_patterns_public[key] = set() - r = set(map(lambda x, m=rules[0]: '{}{}{}'.format( + r = set(map(lambda x, m=rs[0]: '{}{}{}'.format( m._meta.app_label, x, - m._meta.model_name), rules[2])) + m._meta.model_name), rs[2])) rules_patterns_public[key] = rules_patterns_public[key] | r diff --git a/sapl/rules/tests/test_rules.py b/sapl/rules/tests/test_rules.py index e1ed7f7e4..75baaacc9 100644 --- a/sapl/rules/tests/test_rules.py +++ b/sapl/rules/tests/test_rules.py @@ -1,10 +1,10 @@ -import pytest from django.apps import apps from django.conf import settings from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from django.utils import six from django.utils.translation import ugettext_lazy as _ +import pytest from sapl.base.models import CasaLegislativa from sapl.compilacao.models import (PerfilEstruturalTextoArticulado, @@ -12,7 +12,7 @@ from sapl.compilacao.models import (PerfilEstruturalTextoArticulado, TipoDispositivoRelationship) from sapl.materia.models import AcompanhamentoMateria from sapl.protocoloadm.models import AcompanhamentoDocumento -from sapl.rules import SAPL_GROUPS, map_rules +from sapl.rules import __base__, SAPL_GROUPS, map_rules, RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE from sapl.test_urls import create_perms_post_migrate from scripts.lista_permissions_in_decorators import \ lista_permissions_in_decorators @@ -56,29 +56,29 @@ def test_models_in_rules_patterns(model_item): # __falsos_positivos__ __fp__in__test_permission_of_models_in_rules_patterns = { - map_rules.RP_ADD: [CasaLegislativa, + RP_ADD: [CasaLegislativa, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado], - map_rules.RP_CHANGE: [AcompanhamentoMateria, + RP_CHANGE: [AcompanhamentoMateria, AcompanhamentoDocumento, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado], - map_rules.RP_DELETE: [CasaLegislativa, + RP_DELETE: [CasaLegislativa, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado], - map_rules.RP_LIST: [AcompanhamentoMateria, + RP_LIST: [AcompanhamentoMateria, AcompanhamentoDocumento, TipoDispositivo, TipoDispositivoRelationship, PerfilEstruturalTextoArticulado], - map_rules.RP_DETAIL: [AcompanhamentoMateria, + RP_DETAIL: [AcompanhamentoMateria, AcompanhamentoDocumento, TipoDispositivo, TipoDispositivoRelationship, @@ -92,7 +92,7 @@ __fp__in__test_permission_of_models_in_rules_patterns = { def test_permission_of_models_in_rules_patterns(model_item): create_perms_post_migrate(model_item._meta.app_config) - permissions = map_rules.__base__ + list( + permissions = __base__ + list( filter( lambda perm: not perm.startswith( 'detail_') and not perm.startswith('list_'), @@ -186,7 +186,7 @@ def test_permission_required_of_views_exists(url_item): if hasattr(view, 'permission_required'): if isinstance(view.permission_required, six.string_types): - perms = (view.permission_required, ) + perms = (view.permission_required,) else: perms = view.permission_required