mirror of https://github.com/interlegis/sapl.git
107 changed files with 2938 additions and 1306 deletions
@ -0,0 +1,8 @@ |
|||
TipoAutor: |
|||
descricao: des_tipo_autor |
|||
|
|||
Autor: |
|||
nome: nom_autor |
|||
cargo: des_cargo |
|||
tipo: tip_autor |
|||
username: col_username |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-27 13:23 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0058_auto_20161008_0143'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='dispositivo', |
|||
options={'ordering': ['ta', 'ordem'], 'permissions': (('change_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico.'), ('change_dispositivo_edicao_avancada', 'Permissão de edição de dispositivos originais via formulários de edição avançada.'), ('change_dispositivo_registros_compilacao', 'Permissão de registro de compilação via editor dinâmico.'), ('change_dispositivo_notificacoes', 'Permissão de acesso às notificações de pendências.')), 'verbose_name': 'Dispositivo', 'verbose_name_plural': 'Dispositivos'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-01 09:13 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0059_auto_20161027_1323'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='dispositivo', |
|||
options={'ordering': ['ta', 'ordem'], 'permissions': (('change_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico.'), ('change_dispositivo_edicao_avancada', 'Permissão de edição de dispositivos originais via formulários de edição avançada.'), ('change_dispositivo_registros_compilacao', 'Permissão de registro de compilação via editor dinâmico.'), ('view_dispositivo_notificacoes', 'Permissão de acesso às notificações de pendências.')), 'verbose_name': 'Dispositivo', 'verbose_name_plural': 'Dispositivos'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-01 10:25 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0060_auto_20161101_0913'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='dispositivo', |
|||
name='ta', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dispositivos_set', to='compilacao.TextoArticulado', verbose_name='Texto Articulado'), |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-01 12:21 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0061_auto_20161101_1025'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='dispositivo', |
|||
options={'ordering': ['ta', 'ordem'], 'permissions': (('change_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico.'), ('change_dispositivo_edicao_avancada', 'Permissão de edição de dispositivos originais via formulários de edição avançada.'), ('change_dispositivo_registros_compilacao', 'Permissão de registro de compilação via editor dinâmico.'), ('view_dispositivo_notificacoes', 'Permissão de acesso às notificações de pendências.'), ('change_dispositivo_de_vigencia_global', 'Permissão alteração global do dispositivo de vigência')), 'verbose_name': 'Dispositivo', 'verbose_name_plural': 'Dispositivos'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-03 11:06 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0062_auto_20161101_1221'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='tipotextoarticulado', |
|||
name='publicacao_func', |
|||
field=models.NullBooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, verbose_name='Histórico de Publicação'), |
|||
), |
|||
] |
|||
@ -0,0 +1,46 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-04 14:20 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.conf import settings |
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
|||
('compilacao', '0063_tipotextoarticulado_publicacao_func'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='textoarticulado', |
|||
options={'ordering': ['-data', '-numero'], 'permissions': (('view_restricted_textoarticulado', 'Pode ver qualquer Texto Articulado'),), 'verbose_name': 'Texto Articulado', 'verbose_name_plural': 'Textos Articulados'}, |
|||
), |
|||
migrations.AddField( |
|||
model_name='textoarticulado', |
|||
name='editable_only_by_owners', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, verbose_name='Editável apenas pelos donos do Texto Articulado'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='textoarticulado', |
|||
name='editing_locked', |
|||
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, verbose_name='Texto Articulado em Edição'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='textoarticulado', |
|||
name='owners', |
|||
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Donos do Texto Articulado'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='textoarticulado', |
|||
name='visibilidade', |
|||
field=models.IntegerField(choices=[(99, 'Privado'), (79, 'Restrito'), (89, 'Em Edição'), (0, 'Público')], default=99, verbose_name='Visibilidade'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='tipotextoarticulado', |
|||
name='publicacao_func', |
|||
field=models.NullBooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Histórico de Publicação'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-07 10:24 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0064_auto_20161104_1420'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RenameField( |
|||
model_name='textoarticulado', |
|||
old_name='visibilidade', |
|||
new_name='privacidade' |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-07 10:28 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0065_auto_20161107_1024'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='textoarticulado', |
|||
name='privacidade', |
|||
field=models.IntegerField(choices=[(99, 'Privado'), (79, 'Restrito'), (89, 'Em Edição'), (0, 'Público')], default=99, verbose_name='Privacidade'), |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-07 13:51 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0066_auto_20161107_1028'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='textoarticulado', |
|||
options={'ordering': ['-data', '-numero'], 'permissions': (('view_restricted_textoarticulado', 'Pode ver qualquer Texto Articulado'), ('lock_unlock_textoarticulado', 'Pode bloquear/desbloquear edição de Texto Articulado')), 'verbose_name': 'Texto Articulado', 'verbose_name_plural': 'Textos Articulados'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-07 15:46 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0067_auto_20161107_1351'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='dispositivo', |
|||
options={'ordering': ['ta', 'ordem'], 'permissions': (('change_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico.'), ('change_your_dispositivo_edicao_dinamica', 'Permissão de edição de dispositivos originais via editor dinâmico desde que seja dono.'), ('change_dispositivo_edicao_avancada', 'Permissão de edição de dispositivos originais via formulários de edição avançada.'), ('change_dispositivo_registros_compilacao', 'Permissão de registro de compilação via editor dinâmico.'), ('view_dispositivo_notificacoes', 'Permissão de acesso às notificações de pendências.'), ('change_dispositivo_de_vigencia_global', 'Permissão alteração global do dispositivo de vigência')), 'verbose_name': 'Dispositivo', 'verbose_name_plural': 'Dispositivos'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-07 19:32 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('compilacao', '0068_auto_20161107_1546'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='textoarticulado', |
|||
name='privacidade', |
|||
field=models.IntegerField(choices=[(99, 'Privado'), (79, 'Imotável Restrito'), (69, 'Imutável Público'), (89, 'Em Edição'), (0, 'Público')], default=99, verbose_name='Privacidade'), |
|||
), |
|||
] |
|||
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-27 14:19 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0015_auto_20160929_1635'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='assuntonormarelationship', |
|||
options={'verbose_name': 'Assunto', 'verbose_name_plural': 'Assuntos'}, |
|||
), |
|||
migrations.AlterUniqueTogether( |
|||
name='assuntonormarelationship', |
|||
unique_together=set([]), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-27 14:32 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0016_auto_20161027_1419'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='normajuridica', |
|||
name='assuntos', |
|||
field=models.ManyToManyField(through='norma.AssuntoNormaRelationship', to='norma.AssuntoNorma', verbose_name='Assuntos'), |
|||
), |
|||
] |
|||
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-27 14:34 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0017_auto_20161027_1432'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='assuntonormarelationship', |
|||
name='assunto', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.AssuntoNorma', verbose_name='Assunto'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='assuntonormarelationship', |
|||
name='norma', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='norma.NormaJuridica', verbose_name='Norma'), |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-28 02:32 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0018_auto_20161027_1434'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterUniqueTogether( |
|||
name='assuntonormarelationship', |
|||
unique_together=set([('assunto', 'norma')]), |
|||
), |
|||
] |
|||
@ -0,0 +1,39 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-28 13:35 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0019_auto_20161028_0232'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterUniqueTogether( |
|||
name='assuntonormarelationship', |
|||
unique_together=set([]), |
|||
), |
|||
migrations.RemoveField( |
|||
model_name='assuntonormarelationship', |
|||
name='assunto', |
|||
), |
|||
migrations.RemoveField( |
|||
model_name='assuntonormarelationship', |
|||
name='norma', |
|||
), |
|||
migrations.RemoveField( |
|||
model_name='normajuridica', |
|||
name='assuntos', |
|||
), |
|||
migrations.AddField( |
|||
model_name='normajuridica', |
|||
name='assuntos', |
|||
field=models.TextField(blank=True, null=True), |
|||
), |
|||
migrations.DeleteModel( |
|||
name='AssuntoNormaRelationship', |
|||
), |
|||
] |
|||
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-28 13:35 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('norma', '0020_auto_20161028_1335'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RemoveField( |
|||
model_name='normajuridica', |
|||
name='assuntos', |
|||
), |
|||
migrations.AddField( |
|||
model_name='normajuridica', |
|||
name='assuntos', |
|||
field=models.ManyToManyField(blank=True, to='norma.AssuntoNorma', verbose_name='Assuntos'), |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-10-27 17:41 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('protocoloadm', '0004_auto_20161023_1444'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='protocolo', |
|||
options={'permissions': (('action_anular_protocolo', 'Permissão para Anular Protocolo'),), 'verbose_name': 'Protocolo', 'verbose_name_plural': 'Protocolos'}, |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.9.7 on 2016-11-03 17:21 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('protocoloadm', '0005_auto_20161027_1741'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='protocolo', |
|||
name='tipo_protocolo', |
|||
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Tipo de Protocolo'), |
|||
), |
|||
] |
|||
@ -0,0 +1,38 @@ |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
|
|||
default_app_config = 'sapl.rules.apps.AppConfig' |
|||
|
|||
|
|||
SAPL_GROUP_ADMINISTRATIVO = _("Operador Administrativo") |
|||
SAPL_GROUP_PROTOCOLO = _("Operador de Protocolo Administrativo") |
|||
SAPL_GROUP_COMISSOES = _("Operador de Comissões") |
|||
SAPL_GROUP_MATERIA = _("Operador de Matéria") |
|||
SAPL_GROUP_NORMA = _("Operador de Norma Jurídica") |
|||
SAPL_GROUP_SESSAO = _("Operador de Sessão Plenária") |
|||
SAPL_GROUP_PAINEL = _("Operador de Painel Eletrônico") |
|||
SAPL_GROUP_GERAL = _("Operador Geral") |
|||
SAPL_GROUP_AUTOR = _("Autor") |
|||
SAPL_GROUP_PARLAMENTAR = _("Parlamentar") |
|||
|
|||
# TODO - funcionalidade ainda não existe mas está aqui para efeito de anotação |
|||
SAPL_GROUP_LOGIN_SOCIAL = _("Usuários com Login Social") |
|||
|
|||
# ANONYMOUS não é um grupo mas é uma variável usadas nas rules para anotar |
|||
# explicitamente models que podem ter ação de usuários anônimos |
|||
# como por exemplo AcompanhamentoMateria |
|||
SAPL_GROUP_ANONYMOUS = '' |
|||
|
|||
SAPL_GROUPS = [ |
|||
SAPL_GROUP_ADMINISTRATIVO, |
|||
SAPL_GROUP_PROTOCOLO, |
|||
SAPL_GROUP_COMISSOES, |
|||
SAPL_GROUP_MATERIA, |
|||
SAPL_GROUP_NORMA, |
|||
SAPL_GROUP_SESSAO, |
|||
SAPL_GROUP_PAINEL, |
|||
SAPL_GROUP_GERAL, |
|||
SAPL_GROUP_AUTOR, |
|||
SAPL_GROUP_PARLAMENTAR, |
|||
SAPL_GROUP_LOGIN_SOCIAL, |
|||
SAPL_GROUP_ANONYMOUS, |
|||
] |
|||
@ -0,0 +1,234 @@ |
|||
from builtins import LookupError |
|||
|
|||
import django |
|||
from django.apps import apps |
|||
from django.conf import settings |
|||
from django.contrib.auth import get_user_model |
|||
from django.contrib.auth.management import _get_all_permissions |
|||
from django.core import exceptions |
|||
from django.db import models, router |
|||
from django.db.utils import DEFAULT_DB_ALIAS |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from django.utils.translation import string_concat |
|||
|
|||
from sapl.rules import (SAPL_GROUP_ADMINISTRATIVO, SAPL_GROUP_COMISSOES, |
|||
SAPL_GROUP_GERAL, SAPL_GROUP_MATERIA, SAPL_GROUP_NORMA, |
|||
SAPL_GROUP_PAINEL, SAPL_GROUP_PROTOCOLO, |
|||
SAPL_GROUP_SESSAO) |
|||
|
|||
|
|||
class AppConfig(django.apps.AppConfig): |
|||
name = 'sapl.rules' |
|||
label = 'rules' |
|||
verbose_name = _('Regras de Acesso') |
|||
|
|||
|
|||
def create_proxy_permissions( |
|||
app_config, verbosity=2, interactive=True, |
|||
using=DEFAULT_DB_ALIAS, **kwargs): |
|||
if not app_config.models_module: |
|||
return |
|||
|
|||
# print(app_config) |
|||
|
|||
try: |
|||
Permission = apps.get_model('auth', 'Permission') |
|||
except LookupError: |
|||
return |
|||
|
|||
if not router.allow_migrate_model(using, Permission): |
|||
return |
|||
|
|||
from django.contrib.contenttypes.models import ContentType |
|||
|
|||
permission_name_max_length = Permission._meta.get_field('name').max_length |
|||
|
|||
# This will hold the permissions we're looking for as |
|||
# (content_type, (codename, name)) |
|||
searched_perms = list() |
|||
# The codenames and ctypes that should exist. |
|||
ctypes = set() |
|||
for klass in list(app_config.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.db_manager( |
|||
using).get_by_natural_key(app_label, model) |
|||
except: |
|||
ctype = ContentType.objects.db_manager( |
|||
using).create(app_label=app_label, model=model) |
|||
else: |
|||
ctype = ContentType.objects.db_manager(using).get_for_model(klass) |
|||
|
|||
ctypes.add(ctype) |
|||
for perm in _get_all_permissions(klass._meta, ctype): |
|||
searched_perms.append((ctype, perm)) |
|||
|
|||
# Find all the Permissions that have a content_type for a model we're |
|||
# looking for. We don't need to check for codenames since we already have |
|||
# a list of the ones we're going to create. |
|||
all_perms = set(Permission.objects.using(using).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 |
|||
] |
|||
# Validate the permissions before bulk_creation to avoid cryptic database |
|||
# error when the name is longer than 255 characters |
|||
for perm in perms: |
|||
if len(perm.name) > permission_name_max_length: |
|||
raise exceptions.ValidationError( |
|||
'The permission name %s of %s.%s ' |
|||
'is longer than %s characters' % ( |
|||
perm.name, |
|||
perm.content_type.app_label, |
|||
perm.content_type.model, |
|||
permission_name_max_length, |
|||
) |
|||
) |
|||
Permission.objects.using(using).bulk_create(perms) |
|||
if verbosity >= 2: |
|||
for perm in perms: |
|||
print("Adding permission '%s'" % perm) |
|||
|
|||
|
|||
def update_groups(app_config, verbosity=2, interactive=True, |
|||
using=DEFAULT_DB_ALIAS, **kwargs): |
|||
|
|||
if app_config != AppConfig and not isinstance(app_config, AppConfig): |
|||
return |
|||
|
|||
from sapl.rules.map_rules import rules_patterns |
|||
from django.contrib.auth.models import Group, Permission |
|||
from django.contrib.contenttypes.models import ContentType |
|||
|
|||
class Rules: |
|||
|
|||
def __init__(self, rules_patterns): |
|||
self.rules_patterns = rules_patterns |
|||
|
|||
def associar(self, g, model, tipo): |
|||
for t in tipo: |
|||
content_type = ContentType.objects.get_by_natural_key( |
|||
app_label=model._meta.app_label, |
|||
model=model._meta.model_name) |
|||
|
|||
codename = (t[1:] + model._meta.model_name)\ |
|||
if t[0] == '.' and t[-1] == '_' else t |
|||
|
|||
p = Permission.objects.get( |
|||
content_type=content_type, |
|||
codename=codename) |
|||
g.permissions.add(p) |
|||
g.save() |
|||
|
|||
def _config_group(self, group_name, rules_list): |
|||
if not group_name: |
|||
return |
|||
|
|||
g = Group.objects.get_or_create(name=group_name) |
|||
if not isinstance(g, Group): |
|||
g = g[0] |
|||
g.permissions.clear() |
|||
|
|||
try: |
|||
|
|||
print(' ', group_name) |
|||
for model, perms in rules_list: |
|||
self.associar(g, model, perms) |
|||
except Exception as e: |
|||
print(group_name, e) |
|||
|
|||
if settings.DEBUG: |
|||
user = '' |
|||
if group_name == SAPL_GROUP_ADMINISTRATIVO: |
|||
user = 'operador_administrativo' |
|||
elif group_name == SAPL_GROUP_PROTOCOLO: |
|||
user = 'operador_protocoloadm' |
|||
elif group_name == SAPL_GROUP_COMISSOES: |
|||
user = 'operador_comissoes' |
|||
elif group_name == SAPL_GROUP_MATERIA: |
|||
user = 'operador_materia' |
|||
elif group_name == SAPL_GROUP_NORMA: |
|||
user = 'operador_norma' |
|||
elif group_name == SAPL_GROUP_SESSAO: |
|||
user = 'operador_sessao' |
|||
elif group_name == SAPL_GROUP_PAINEL: |
|||
user = 'operador_painel' |
|||
elif group_name == SAPL_GROUP_GERAL: |
|||
user = 'operador_geral' |
|||
|
|||
if user: |
|||
self.cria_usuario(user, g) |
|||
|
|||
def groups_add_user(self, user, groups_name): |
|||
if not isinstance(groups_name, list): |
|||
groups_name = [groups_name, ] |
|||
for group_name in groups_name: |
|||
if not group_name or user.groups.filter( |
|||
name=group_name).exists(): |
|||
continue |
|||
g = Group.objects.get_or_create(name=group_name)[0] |
|||
user.groups.add(g) |
|||
|
|||
def groups_remove_user(self, user, groups_name): |
|||
if not isinstance(groups_name, list): |
|||
groups_name = [groups_name, ] |
|||
for group_name in groups_name: |
|||
if not group_name or not user.groups.filter( |
|||
name=group_name).exists(): |
|||
continue |
|||
g = Group.objects.get_or_create(name=group_name)[0] |
|||
user.groups.remove(g) |
|||
|
|||
def cria_usuario(self, nome, grupo): |
|||
nome_usuario = nome |
|||
usuario = get_user_model().objects.get_or_create( |
|||
username=nome_usuario)[0] |
|||
usuario.set_password('interlegis') |
|||
usuario.save() |
|||
grupo.user_set.add(usuario) |
|||
|
|||
def update_groups(self): |
|||
print('') |
|||
print(string_concat('\033[93m\033[1m', |
|||
_('Atualizando grupos:'), |
|||
'\033[0m')) |
|||
for rules_group in self.rules_patterns: |
|||
group_name = rules_group['group'] |
|||
rules_list = rules_group['rules'] |
|||
self._config_group(group_name, rules_list) |
|||
|
|||
rules = Rules(rules_patterns) |
|||
rules.update_groups() |
|||
|
|||
|
|||
models.signals.post_migrate.connect( |
|||
receiver=update_groups) |
|||
|
|||
|
|||
models.signals.post_migrate.connect( |
|||
receiver=create_proxy_permissions, |
|||
dispatch_uid="django.contrib.auth.management.create_permissions") |
|||
@ -0,0 +1,317 @@ |
|||
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 (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_PARLAMENTAR, |
|||
SAPL_GROUP_PROTOCOLO, SAPL_GROUP_SESSAO) |
|||
from sapl.sessao import models as sessao |
|||
|
|||
""" |
|||
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. |
|||
|
|||
Os cinco radicais de permissão completa são: |
|||
|
|||
RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\ |
|||
'.list_', '.detail_', '.add_', '.change_', '.delete_', |
|||
|
|||
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. |
|||
""" |
|||
|
|||
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] |
|||
|
|||
|
|||
rules_group_administrativo = { |
|||
'group': SAPL_GROUP_ADMINISTRATIVO, |
|||
'rules': [ |
|||
(protocoloadm.DocumentoAdministrativo, __base__), |
|||
(protocoloadm.DocumentoAcessorioAdministrativo, __base__), |
|||
(protocoloadm.TramitacaoAdministrativo, __base__), |
|||
] |
|||
} |
|||
|
|||
rules_group_protocolo = { |
|||
'group': SAPL_GROUP_PROTOCOLO, |
|||
'rules': [ |
|||
(protocoloadm.Protocolo, __base__ + [ |
|||
'action_anular_protocolo']), |
|||
(protocoloadm.DocumentoAdministrativo, |
|||
[RP_ADD] + __listdetailchange__), |
|||
(protocoloadm.DocumentoAcessorioAdministrativo, __listdetailchange__), |
|||
|
|||
(materia.MateriaLegislativa, __listdetailchange__), |
|||
(materia.DocumentoAcessorio, __listdetailchange__), |
|||
(materia.Anexada, __base__), |
|||
(materia.Autoria, __base__), |
|||
|
|||
(materia.Proposicao, __listdetailchange__), |
|||
(compilacao.TextoArticulado, ['view_restricted_textoarticulado']) |
|||
] |
|||
} |
|||
|
|||
rules_group_comissoes = { |
|||
'group': SAPL_GROUP_COMISSOES, |
|||
'rules': [ |
|||
(comissoes.Comissao, __base__), |
|||
(comissoes.Composicao, __base__), |
|||
(comissoes.Participacao, __base__), |
|||
] |
|||
} |
|||
|
|||
rules_group_materia = { |
|||
'group': SAPL_GROUP_MATERIA, |
|||
'rules': [ |
|||
(materia.Anexada, __base__), |
|||
(materia.Autoria, __base__), |
|||
(materia.DespachoInicial, __base__), |
|||
(materia.DocumentoAcessorio, __base__), |
|||
|
|||
(materia.MateriaLegislativa, __base__), |
|||
(materia.Numeracao, __base__), |
|||
(materia.Relatoria, __base__), |
|||
(materia.Tramitacao, __base__), |
|||
(materia.Relatoria, __base__), |
|||
(norma.LegislacaoCitada, __base__), |
|||
(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. |
|||
]) |
|||
] |
|||
} |
|||
|
|||
rules_group_norma = { |
|||
'group': SAPL_GROUP_NORMA, |
|||
'rules': [ |
|||
(norma.NormaJuridica, __base__), |
|||
(norma.VinculoNormaJuridica, __base__), |
|||
|
|||
# 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__), |
|||
(compilacao.Vide, __base__), |
|||
(compilacao.Nota, __base__), |
|||
(compilacao.Dispositivo, __base__ + [ |
|||
'view_dispositivo_notificacoes', |
|||
'change_dispositivo_edicao_dinamica', |
|||
'change_dispositivo_edicao_avancada', |
|||
'change_dispositivo_registros_compilacao', |
|||
'change_dispositivo_de_vigencia_global' |
|||
]) |
|||
] |
|||
} |
|||
|
|||
rules_group_sessao = { |
|||
'group': SAPL_GROUP_SESSAO, |
|||
'rules': [ |
|||
(sessao.SessaoPlenaria, __base__), |
|||
(sessao.SessaoPlenariaPresenca, __base__), |
|||
(sessao.ExpedienteMateria, __base__), |
|||
(sessao.IntegranteMesa, __base__), |
|||
(sessao.ExpedienteSessao, __base__), |
|||
(sessao.Orador, __base__), |
|||
(sessao.OradorExpediente, __base__), |
|||
(sessao.OrdemDia, __base__), |
|||
(sessao.PresencaOrdemDia, __base__), |
|||
(sessao.RegistroVotacao, __base__), |
|||
(sessao.VotoParlamentar, __base__), |
|||
] |
|||
} |
|||
|
|||
rules_group_painel = { |
|||
'group': SAPL_GROUP_PAINEL, |
|||
'rules': [ |
|||
(painel.Painel, __base__), |
|||
(painel.Cronometro, __base__), |
|||
] |
|||
} |
|||
|
|||
rules_group_autor = { |
|||
'group': SAPL_GROUP_AUTOR, |
|||
'rules': [ |
|||
(materia.Proposicao, __base__), |
|||
(compilacao.Dispositivo, __base__ + [ |
|||
'change_your_dispositivo_edicao_dinamica', |
|||
]) |
|||
] |
|||
} |
|||
|
|||
rules_group_parlamentar = { |
|||
'group': SAPL_GROUP_PARLAMENTAR, |
|||
'rules': [] |
|||
} |
|||
|
|||
rules_group_geral = { |
|||
'group': SAPL_GROUP_GERAL, |
|||
'rules': [ |
|||
(base.AppConfig, __base__ + [ |
|||
'menu_sistemas', |
|||
'view_tabelas_auxiliares' |
|||
]), |
|||
|
|||
(base.CasaLegislativa, __listdetailchange__), |
|||
(base.ProblemaMigracao, []), |
|||
(base.TipoAutor, __base__), |
|||
(base.Autor, __base__), |
|||
|
|||
(protocoloadm.StatusTramitacaoAdministrativo, __base__), |
|||
(protocoloadm.TipoDocumentoAdministrativo, __base__), |
|||
|
|||
(comissoes.CargoComissao, __base__), |
|||
(comissoes.TipoComissao, __base__), |
|||
(comissoes.Periodo, __base__), |
|||
|
|||
(materia.AssuntoMateria, __base__), # não há implementação |
|||
(materia.MateriaAssunto, __base__), # não há implementação |
|||
(materia.TipoProposicao, __base__), |
|||
(materia.TipoMateriaLegislativa, __base__), |
|||
(materia.RegimeTramitacao, __base__), |
|||
(materia.Origem, __base__), |
|||
(materia.TipoDocumento, __base__), |
|||
(materia.Orgao, __base__), |
|||
(materia.TipoFimRelatoria, __base__), |
|||
(materia.Parecer, __base__), |
|||
(materia.StatusTramitacao, __base__), |
|||
(materia.UnidadeTramitacao, __base__), |
|||
|
|||
(norma.AssuntoNorma, __base__), |
|||
(norma.TipoNormaJuridica, __base__), |
|||
|
|||
(parlamentares.Legislatura, __base__), |
|||
(parlamentares.SessaoLegislativa, __base__), |
|||
(parlamentares.Coligacao, __base__), |
|||
(parlamentares.ComposicaoColigacao, __base__), |
|||
(parlamentares.Partido, __base__), |
|||
(parlamentares.Municipio, __base__), |
|||
(parlamentares.NivelInstrucao, __base__), |
|||
(parlamentares.SituacaoMilitar, __base__), |
|||
(parlamentares.Parlamentar, __base__), |
|||
(parlamentares.TipoDependente, __base__), |
|||
(parlamentares.Dependente, __base__), |
|||
(parlamentares.Filiacao, __base__), |
|||
(parlamentares.TipoAfastamento, __base__), |
|||
(parlamentares.Mandato, __base__), |
|||
(parlamentares.CargoMesa, __base__), |
|||
(parlamentares.ComposicaoMesa, __base__), |
|||
(parlamentares.Frente, __base__), |
|||
|
|||
(sessao.CargoBancada, __base__), |
|||
(sessao.Bancada, __base__), |
|||
(sessao.TipoSessaoPlenaria, __base__), |
|||
(sessao.TipoResultadoVotacao, __base__), |
|||
(sessao.TipoExpediente, __base__), |
|||
(sessao.Bloco, __base__), |
|||
|
|||
(lexml.LexmlProvedor, __base__), |
|||
(lexml.LexmlPublicador, __base__), |
|||
|
|||
(compilacao.VeiculoPublicacao, __base__), |
|||
(compilacao.TipoTextoArticulado, __base__), |
|||
(compilacao.TipoNota, __base__), |
|||
(compilacao.TipoVide, __base__), |
|||
(compilacao.TipoPublicacao, __base__), |
|||
|
|||
# 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']), |
|||
|
|||
# estes tres models são complexos e a principio apenas o admin tem perm |
|||
(compilacao.TipoDispositivo, []), |
|||
(compilacao.TipoDispositivoRelationship, []), |
|||
(compilacao.PerfilEstruturalTextoArticulado, []), |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
] |
|||
} |
|||
|
|||
|
|||
# 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]), |
|||
] |
|||
} |
|||
|
|||
rules_group_login_social = { |
|||
'group': SAPL_GROUP_LOGIN_SOCIAL, |
|||
'rules': [] |
|||
} |
|||
|
|||
rules_group_geral['rules'] = (rules_group_geral['rules'] + |
|||
rules_group_administrativo['rules'] + |
|||
rules_group_protocolo['rules'] + |
|||
rules_group_comissoes['rules'] + |
|||
rules_group_materia['rules'] + |
|||
rules_group_norma['rules'] + |
|||
rules_group_sessao['rules'] + |
|||
rules_group_painel['rules'] + |
|||
rules_group_login_social['rules']) |
|||
|
|||
|
|||
rules_patterns = [ |
|||
rules_group_administrativo, |
|||
rules_group_protocolo, |
|||
rules_group_comissoes, |
|||
rules_group_materia, |
|||
rules_group_norma, |
|||
rules_group_sessao, |
|||
rules_group_painel, |
|||
rules_group_geral, |
|||
rules_group_autor, |
|||
rules_group_parlamentar, |
|||
|
|||
rules_group_anonymous, # anotação para validação do teste de rules |
|||
rules_group_login_social # TODO não implementado |
|||
] |
|||
@ -0,0 +1,255 @@ |
|||
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 _ |
|||
|
|||
from sapl.base.models import CasaLegislativa, ProblemaMigracao |
|||
from sapl.compilacao.models import (PerfilEstruturalTextoArticulado, |
|||
TipoDispositivo, |
|||
TipoDispositivoRelationship) |
|||
from sapl.materia.models import AcompanhamentoMateria |
|||
from sapl.rules import SAPL_GROUPS, map_rules |
|||
from sapl.test_urls import create_perms_post_migrate |
|||
from scripts.lista_permissions_in_decorators import \ |
|||
lista_permissions_in_decorators |
|||
from scripts.lista_urls import lista_urls |
|||
|
|||
sapl_appconfs = [apps.get_app_config(n[5:]) for n in settings.SAPL_APPS] |
|||
|
|||
sapl_models = [] |
|||
for app in sapl_appconfs: |
|||
sapl_models.extend(app.get_models()) |
|||
sapl_models.reverse() |
|||
|
|||
|
|||
@pytest.mark.parametrize('group_item', SAPL_GROUPS) |
|||
def test_groups_in_rules_patterns(group_item): |
|||
|
|||
test = False |
|||
for rules_group in map_rules.rules_patterns: |
|||
if rules_group['group'] == group_item: |
|||
test = True |
|||
|
|||
assert test, _('O grupo (%s) não foi a rules_patterns.') % (group_item) |
|||
|
|||
|
|||
@pytest.mark.parametrize('model_item', sapl_models) |
|||
def test_models_in_rules_patterns(model_item): |
|||
|
|||
test = False |
|||
for rules_group in map_rules.rules_patterns: |
|||
rules_model = rules_group['rules'] |
|||
for rm in rules_model: |
|||
if rm[0] == model_item: |
|||
test = True |
|||
break |
|||
|
|||
assert test, _('O model %s (%s) não foi adicionado em nenhum ' |
|||
'grupo padrão para regras de acesso.') % ( |
|||
str(model_item), |
|||
model_item._meta.verbose_name) |
|||
|
|||
# __falsos_positivos__ |
|||
__fp__in__test_permission_of_models_in_rules_patterns = { |
|||
map_rules.RP_ADD: [CasaLegislativa, |
|||
ProblemaMigracao, |
|||
TipoDispositivo, |
|||
TipoDispositivoRelationship, |
|||
PerfilEstruturalTextoArticulado], |
|||
|
|||
map_rules.RP_CHANGE: [ProblemaMigracao, |
|||
AcompanhamentoMateria, |
|||
TipoDispositivo, |
|||
TipoDispositivoRelationship, |
|||
PerfilEstruturalTextoArticulado], |
|||
|
|||
map_rules.RP_DELETE: [CasaLegislativa, |
|||
ProblemaMigracao, |
|||
TipoDispositivo, |
|||
TipoDispositivoRelationship, |
|||
PerfilEstruturalTextoArticulado], |
|||
|
|||
map_rules.RP_LIST: [ProblemaMigracao, |
|||
AcompanhamentoMateria, |
|||
TipoDispositivo, |
|||
TipoDispositivoRelationship, |
|||
PerfilEstruturalTextoArticulado], |
|||
|
|||
map_rules.RP_DETAIL: [ProblemaMigracao, |
|||
AcompanhamentoMateria, |
|||
TipoDispositivo, |
|||
TipoDispositivoRelationship, |
|||
PerfilEstruturalTextoArticulado] |
|||
|
|||
} |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
@pytest.mark.parametrize('model_item', sapl_models) |
|||
def test_permission_of_models_in_rules_patterns(model_item): |
|||
|
|||
create_perms_post_migrate(model_item._meta.app_config) |
|||
permissions = map_rules.__base__ + list( |
|||
filter( |
|||
lambda perm: not perm.startswith( |
|||
'detail_') and not perm.startswith('list_'), |
|||
map(lambda x: x[0], |
|||
model_item._meta.permissions)) |
|||
) |
|||
|
|||
__fp__ = __fp__in__test_permission_of_models_in_rules_patterns |
|||
for perm in permissions: |
|||
if perm in __fp__ and model_item in __fp__[perm]: |
|||
continue |
|||
|
|||
test = False |
|||
for rules_group in map_rules.rules_patterns: |
|||
rules_model = rules_group['rules'] |
|||
for rm in rules_model: |
|||
model = rm[0] |
|||
rules = rm[1] |
|||
if model == model_item: |
|||
if perm in rules: |
|||
test = True |
|||
break |
|||
|
|||
assert test, _('A permissão (%s) do model (%s) não foi adicionado em ' |
|||
'nenhum grupo padrão para regras de acesso.') % ( |
|||
perm, |
|||
str(model_item)) |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
@pytest.mark.parametrize('model_item', sapl_models) |
|||
def test_permission_of_rules_exists(model_item): |
|||
|
|||
print(model_item) |
|||
create_perms_post_migrate(model_item._meta.app_config) |
|||
|
|||
for rules_group in map_rules.rules_patterns: |
|||
rules_model = rules_group['rules'] |
|||
for rm in rules_model: |
|||
model = rm[0] |
|||
rules = rm[1] |
|||
|
|||
if model != model_item: |
|||
continue |
|||
|
|||
for r in rules: |
|||
content_type = ContentType.objects.get_by_natural_key( |
|||
app_label=model._meta.app_label, |
|||
model=model._meta.model_name) |
|||
|
|||
codename = (r[1:] + model._meta.model_name)\ |
|||
if r[0] == '.' and r[-1] == '_' else r |
|||
p = Permission.objects.filter( |
|||
content_type=content_type, |
|||
codename=codename).exists() |
|||
|
|||
assert p, _('Permissão (%s) associada ao model (%s) ' |
|||
'não está em _meta.permissions.') % ( |
|||
codename, |
|||
model_item) |
|||
|
|||
|
|||
_lista_urls = lista_urls() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
@pytest.mark.parametrize('url_item', _lista_urls) |
|||
def test_permission_required_of_views_exists(url_item): |
|||
""" |
|||
testa se, nas views que possuem atributo permission_required, |
|||
as permissões fixas escritas manualmente realmente exitem em Permission |
|||
|
|||
Obs: isso não testa permissões escritas em anotações de método ou classe |
|||
""" |
|||
|
|||
for app in sapl_appconfs: |
|||
# readequa permissões dos models adicionando |
|||
# list e detail permissions |
|||
create_perms_post_migrate(app) |
|||
|
|||
key, url, var, app_name = url_item |
|||
url = '/' + (url % {v: 1 for v in var}) |
|||
|
|||
assert '\n' not in url, """ |
|||
A url (%s) da app (%s) está mal formada. |
|||
""" % (app_name, url) |
|||
|
|||
view = None |
|||
if hasattr(key, 'view_class'): |
|||
view = key.view_class |
|||
|
|||
if hasattr(view, 'permission_required'): |
|||
if isinstance(view.permission_required, six.string_types): |
|||
perms = (view.permission_required, ) |
|||
else: |
|||
perms = view.permission_required |
|||
|
|||
if not perms: |
|||
return |
|||
|
|||
for perm in perms: |
|||
if perm[0] == '.' and perm[-1] == '_': |
|||
model = None |
|||
if hasattr(view, 'model') and view.model: |
|||
model = view.model |
|||
elif hasattr(view, 'filterset_class'): |
|||
model = view.fielterset_class._meta.model |
|||
elif hasattr(view, 'form_class'): |
|||
model = view.form_class._meta.model |
|||
|
|||
assert model, _('model %s não localizado em %s' |
|||
) % (model, view) |
|||
|
|||
codename = perm[1:] + view.model._meta.model_name |
|||
else: |
|||
codename = perm |
|||
|
|||
codename = codename.split('.') |
|||
|
|||
if len(codename) == 1: |
|||
content_type = ContentType.objects.get_by_natural_key( |
|||
app_label=model._meta.app_label, |
|||
model=model._meta.model_name) |
|||
p = Permission.objects.filter( |
|||
content_type=content_type, |
|||
codename=codename[0]).exists() |
|||
elif len(codename) == 2: |
|||
p = Permission.objects.filter( |
|||
content_type__app_label=codename[0], |
|||
codename=codename[1]).exists() |
|||
|
|||
assert p, _('Permissão (%s) na view (%s) não existe.') % ( |
|||
codename, |
|||
view) |
|||
|
|||
|
|||
_lista_permissions_in_decorators = lista_permissions_in_decorators() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
@pytest.mark.parametrize('permission', _lista_permissions_in_decorators) |
|||
def test_permission_required_of_decorators(permission): |
|||
""" |
|||
testa se, nos decorators permission_required com ou sem method_decorator |
|||
as permissões fixas escritas manualmente realmente exitem em Permission |
|||
""" |
|||
|
|||
for app in sapl_appconfs: |
|||
# readequa permissões dos models adicionando |
|||
# list e detail permissions |
|||
create_perms_post_migrate(app) |
|||
|
|||
codename = permission[0].split('.') |
|||
p = Permission.objects.filter( |
|||
content_type__app_label=codename[0], |
|||
codename=codename[1]).exists() |
|||
|
|||
assert p, _('Permissão (%s) na view (%s) não existe.') % ( |
|||
permission[0], |
|||
permission[1]) |
|||
@ -1,49 +0,0 @@ |
|||
{% extends "crud/list.html" %} |
|||
{% load i18n %} |
|||
{% load common_tags %} |
|||
|
|||
{% block base_content %} |
|||
<div class="actions btn-group pull-right" role="group"> |
|||
{% if user|get_config_not_exists %} |
|||
<a href="{{ view.create_url }}" class="btn btn-default"> |
|||
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %} |
|||
</a> |
|||
{% endif %} |
|||
{% block more_buttons %}{% endblock more_buttons %} |
|||
</div> |
|||
|
|||
<br/><br/> |
|||
{% block extra_content %} {% endblock %} |
|||
|
|||
{% if not rows %} |
|||
<p>{{ NO_ENTRIES_MSG }}</p> |
|||
{% else %} |
|||
<table class="table table-striped table-hover"> |
|||
<thead> |
|||
<tr> |
|||
{% for name in headers %} |
|||
<th>{{ name }}</th> |
|||
{% endfor %} |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
{% for value_list in rows %} |
|||
<tr> |
|||
{% for value, href in value_list %} |
|||
<td> |
|||
{% if href %} |
|||
<a href="{{ href }}">{{ value }}</a> |
|||
{% else %} |
|||
{{ value|safe }} |
|||
{% endif %} |
|||
</td> |
|||
{% endfor %} |
|||
</tr> |
|||
{% endfor %} |
|||
</tbody> |
|||
</table> |
|||
{% endif %} |
|||
|
|||
{% include "paginacao.html" %} |
|||
|
|||
{% endblock %} |
|||
@ -0,0 +1,21 @@ |
|||
{% extends "compilacao/text_list.html" %} |
|||
{% load i18n %} |
|||
{% load compilacao_filters %} |
|||
{% load common_tags %} |
|||
{% load staticfiles %} |
|||
{% load sass_tags %} |
|||
|
|||
{% block navigation %}{% endblock %} |
|||
{% block sections_nav %}{% endblock %} |
|||
{% block extra_sections_nav %}{% endblock %} |
|||
{% block actions %}{% endblock %} |
|||
{% block dsp_actions %}{% endblock %} |
|||
|
|||
{% block detail_content %}{% endblock %} |
|||
{% block footer_container %}{% endblock %} |
|||
|
|||
|
|||
{% block foot_js %}{{block.super}} |
|||
<script type="text/javascript" src="{% static 'js/compilacao.js' %}"></script> |
|||
<script type="text/javascript" src="{% static 'js/compilacao_view.js' %}"></script> |
|||
{% endblock %} |
|||
@ -0,0 +1,29 @@ |
|||
{% extends "crud/form.html" %} |
|||
{% load i18n %} |
|||
{% load crispy_forms_tags %} |
|||
{% load common_tags %} |
|||
|
|||
{% block extra_js %} |
|||
|
|||
<script language="Javascript"> |
|||
function recuperar_materia() { |
|||
var tipo_materia = $("#id_tipo_materia").val() |
|||
var numero_materia = $("#id_numero_materia").val() |
|||
var ano_materia = $("#id_ano_materia").val() |
|||
|
|||
if (tipo_materia && numero_materia && ano_materia) { |
|||
$.get("/sessao/recuperar-materia",{tipo_materia: tipo_materia, |
|||
numero_materia: numero_materia, |
|||
ano_materia: ano_materia}, |
|||
function(data, status) { |
|||
$("#id_ementa").val(data.ementa); |
|||
}); |
|||
} |
|||
} |
|||
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"] |
|||
for (i = 0; i < fields.length; i++) { |
|||
$(fields[i]).change(recuperar_materia); |
|||
} |
|||
</script> |
|||
|
|||
{% endblock %} |
|||
@ -0,0 +1,29 @@ |
|||
{% extends "base.html" %} |
|||
{% load i18n common_tags%} |
|||
|
|||
{% block base_content %} |
|||
<div class="alert alert-success alert-dismissible fade in" role="alert"> |
|||
<p align="center"><b><font color="green">Matéria procololada com sucesso!</font></b></p> |
|||
</div> |
|||
|
|||
<div align="center"> |
|||
|
|||
<div class="row" style="width:50%;"> |
|||
<div class="col-md-6"> |
|||
<a onclick="window.open('{% url 'sapl.relatorios:relatorio_etiqueta_protocolo' protocolo.numero protocolo.ano %}','Comprovante','width=400, height=200')"class="btn btn-secondary">Imprimir Etiqueta</a> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a target="popup" class="btn btn-secondary" onclick="window.open('{% url 'sapl.protocoloadm:comprovante_protocolo' protocolo.pk %}','Comprovante','width=800, height=700')">Imprimir Comprovante</a> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="row" style="width:50%;"> |
|||
<div class="col-md-6"> |
|||
<a href="{% url 'sapl.materia:materia_create_simplificado' protocolo.pk %}" class="btn btn-warning">Criar Matéria</a> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="{% url 'sapl.protocoloadm:protocolo_mostrar' protocolo.pk %}" class="btn btn-primary">Continuar</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
{% endblock base_content %} |
|||
@ -1,7 +1,17 @@ |
|||
{% extends "protocoloadm/protocoloadm_detail.html" %} |
|||
{% load i18n %} |
|||
{% load crispy_forms_tags %} |
|||
|
|||
|
|||
{% block actions %} |
|||
|
|||
{{ block.super }} |
|||
<div class="actions btn-group pull-right grid-gutter-width-right " role="group"> |
|||
<a href="{% url 'protocoloadm:protocolo' %}" class="btn btn-default">{% trans 'Fazer nova pesquisa' %}</a> |
|||
</div> |
|||
{% endblock %} |
|||
|
|||
{% block detail_content %} |
|||
<div>{{ message }} </div> |
|||
{% crispy form %} |
|||
{% endblock detail_content %} |
|||
{% endblock detail_content %} |
|||
|
|||
@ -1,9 +1,9 @@ |
|||
{% extends "crud/detail.html" %} |
|||
{% load i18n %} |
|||
{% block actions %} |
|||
<div class="actions btn-group pull-right" role="group"> |
|||
<a href="{% url 'protocoloadm:protocolar_doc' %}" class="btn btn-default">{% trans 'Protocolar Documento' %}</a> |
|||
<a href="{% url 'protocoloadm:protocolar_mat' %}" class="btn btn-default">{% trans 'Protocolar Matéria' %}</a> |
|||
<a href="{% url 'protocoloadm:anular_protocolo' %}" class="btn btn-default">{% trans 'Anular Protocolo' %}</a> |
|||
</div> |
|||
{% endblock actions %} |
|||
{% block editions %} |
|||
<div class="actions btn-group pull-right" role="group"> |
|||
<a href="{% url 'protocoloadm:protocolar_doc' %}" class="btn btn-default">{% trans 'Protocolar Documento' %}</a> |
|||
<a href="{% url 'protocoloadm:protocolar_mat' %}" class="btn btn-default">{% trans 'Protocolar Matéria' %}</a> |
|||
<a href="{% url 'protocoloadm:anular_protocolo' %}" class="btn btn-default btn-excluir">{% trans 'Anular Protocolo' %}</a> |
|||
</div> |
|||
{% endblock editions %} |
|||
|
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue