diff --git a/base/forms.py b/base/forms.py
index 798b40e11..23a7864e7 100644
--- a/base/forms.py
+++ b/base/forms.py
@@ -89,7 +89,7 @@ class CasaLegislativaTabelaAuxForm(ModelForm):
row4,
row5,
HTML("""
- {% if form.logotipo.value %}
+ {% if not form.fotografia.errors and form.fotografia.value %}
diff --git a/materia/forms.py b/materia/forms.py
index 47138fbea..c50dfad79 100644
--- a/materia/forms.py
+++ b/materia/forms.py
@@ -70,6 +70,17 @@ class ProposicaoForm(ModelForm):
self.helper.layout = Layout(
Fieldset(_('Incluir Proposição'),
row1, row2, row3, row4,
+ HTML("""
+
+
+
+
+ """, ),
form_actions(more=more))
)
super(ProposicaoForm, self).__init__(
diff --git a/materia/models.py b/materia/models.py
index 56b480162..bd007594d 100644
--- a/materia/models.py
+++ b/materia/models.py
@@ -4,7 +4,8 @@ from model_utils import Choices
from comissoes.models import Comissao
from parlamentares.models import Parlamentar, Partido
-from sapl.utils import RANGE_ANOS, YES_NO_CHOICES, xstr
+from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES,
+ restringe_tipos_de_arquivo_txt, xstr)
class TipoMateriaLegislativa(models.Model):
@@ -122,7 +123,8 @@ class MateriaLegislativa(models.Model):
blank=True,
null=True,
upload_to=texto_upload_path,
- verbose_name=_('Texto Original (PDF)'))
+ verbose_name=_('Texto Original (PDF)'),
+ validators=[restringe_tipos_de_arquivo_txt])
class Meta:
verbose_name = _('Matéria Legislativa')
@@ -457,7 +459,8 @@ class Proposicao(models.Model):
blank=True,
null=True,
upload_to=texto_upload_path,
- verbose_name=_('Texto Original (PDF)'))
+ verbose_name=_('Texto Original (PDF)'),
+ validators=[restringe_tipos_de_arquivo_txt])
class Meta:
verbose_name = _('Proposição')
diff --git a/materia/views.py b/materia/views.py
index 9cee72ad5..14ad129db 100644
--- a/materia/views.py
+++ b/materia/views.py
@@ -1,3 +1,4 @@
+import os
from datetime import datetime
from random import choice
from string import ascii_letters, digits
@@ -1358,8 +1359,10 @@ class ProposicaoEditView(CreateView):
proposicao.save()
else:
proposicao.delete()
- elif 'salvar' in request.POST:
+ if 'salvar' or "remover-foto" in request.POST:
if 'texto_original' in request.FILES:
+ # if os.unlink(proposicao.texto_original.path):
+ # proposicao.texto_original = None
proposicao.texto_original = request.FILES['texto_original']
tipo = TipoProposicao.objects.get(id=form.data['tipo'])
proposicao.tipo = tipo
@@ -1379,6 +1382,12 @@ class ProposicaoEditView(CreateView):
proposicao.materia = materia
if not proposicao.data_envio:
proposicao.data_envio = datetime.now()
+ if "remover-texto" in request.POST:
+ try:
+ os.unlink(proposicao.texto_original.path)
+ except OSError:
+ pass # Should log this error!!!!!
+ proposicao.texto_original = None
proposicao.save()
return redirect(self.get_success_url())
else:
diff --git a/parlamentares/forms.py b/parlamentares/forms.py
index ff47bee33..43377bbe6 100644
--- a/parlamentares/forms.py
+++ b/parlamentares/forms.py
@@ -60,12 +60,12 @@ class ParlamentaresForm (ModelForm):
'cpf': forms.TextInput(attrs={'class': 'cpf'}),
'rg': forms.TextInput(attrs={'class': 'rg'}),
'titulo_eleitor': forms.TextInput(attrs={
- 'class': 'titulo_eleitor'}),
+ 'class': 'titulo_eleitor'}),
'telefone': forms.TextInput(attrs={'class': 'telefone'}),
'fax': forms.TextInput(attrs={'class': 'telefone'}),
'cep_residencia': forms.TextInput(attrs={'class': 'cep'}),
'telefone_residencia': forms.TextInput(attrs={
- 'class': 'telefone'}),
+ 'class': 'telefone'}),
'fax_residencia': forms.TextInput(attrs={'class': 'telefone'}),
'fotografia': forms.FileInput,
'biografia': forms.Textarea(attrs={'id': 'biografia-parlamentar'})
@@ -131,18 +131,19 @@ class ParlamentaresForm (ModelForm):
row6, row7, row8, row9, row10,
row11, row12, row13,
HTML("""
- {% if form.fotografia.value %}
-
-
-
- {% endif %}
-
""", ),
+ {% if not form.fotografia.errors %}
+ {% if form.fotografia.value %}
+
+
+
+ {% endif %}
+ {% endif %}
+
""", ),
row14,
form_actions())
)
diff --git a/parlamentares/models.py b/parlamentares/models.py
index c72762e0b..70fe89583 100644
--- a/parlamentares/models.py
+++ b/parlamentares/models.py
@@ -4,7 +4,7 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
-from sapl.utils import UF, YES_NO_CHOICES
+from sapl.utils import UF, YES_NO_CHOICES, restringe_tipos_de_arquivo_img
class Legislatura(models.Model):
@@ -244,7 +244,8 @@ class Parlamentar(models.Model):
blank=True,
null=True,
upload_to=foto_upload_path,
- verbose_name=_('Fotografia'))
+ verbose_name=_('Fotografia'),
+ validators=[restringe_tipos_de_arquivo_img])
class Meta:
verbose_name = _('Parlamentar')
diff --git a/parlamentares/views.py b/parlamentares/views.py
index 1f2a888f5..eda0452ec 100644
--- a/parlamentares/views.py
+++ b/parlamentares/views.py
@@ -72,7 +72,7 @@ def validate(form, parlamentar, filiacao, request):
break
if (data_desfiliacao and
- data_init < data_desfiliacao < data_fim):
+ data_init < data_desfiliacao < data_fim):
error_msg = _("A data de filiação e \
desfiliação não podem estar no intervalo \
@@ -206,7 +206,7 @@ class ParlamentaresEditarView(UpdateView):
elif 'excluir' in self.request.POST:
Mandato.objects.get(parlamentar=parlamentar).delete()
parlamentar.delete()
- elif "remover" in self.request.POST:
+ elif "remover-foto" in self.request.POST:
try:
os.unlink(parlamentar.fotografia.path)
except OSError:
@@ -227,7 +227,7 @@ class ParlamentaresDependentesView(CreateView):
def get_context_data(self, **kwargs):
context = super(ParlamentaresDependentesView, self).\
- get_context_data(**kwargs)
+ get_context_data(**kwargs)
pk = self.kwargs['pk']
parlamentar = Parlamentar.objects.get(pk=pk)
dependentes = Dependente.objects.filter(
@@ -265,12 +265,12 @@ class ParlamentaresDependentesEditView(UpdateView):
def get_context_data(self, **kwargs):
context = super(ParlamentaresDependentesEditView, self).\
- get_context_data(**kwargs)
+ get_context_data(**kwargs)
parlamentar = Parlamentar.objects.get(id=self.kwargs['pk'])
context.update({
- 'object': parlamentar,
- 'legislatura_id': parlamentar.mandato_set.last(
- ).legislatura_id})
+ 'object': parlamentar,
+ 'legislatura_id': parlamentar.mandato_set.last(
+ ).legislatura_id})
return context
def form_valid(self, form):
@@ -522,7 +522,7 @@ class MandatoEditView(UpdateView):
context.update(
{'object': parlamentar,
'legislatura_id': parlamentar.mandato_set.last(
- ).legislatura_id})
+ ).legislatura_id})
return context
def form_valid(self, form):
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index 3e2575f11..3e7e04641 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -18,3 +18,4 @@ pytz==2015.7
pyyaml==3.11
rtyaml==0.0.2
unipath==1.1
+python-magic==0.4.10
diff --git a/sapl/settings.py b/sapl/settings.py
index 903a7a016..dcf35823a 100644
--- a/sapl/settings.py
+++ b/sapl/settings.py
@@ -9,15 +9,13 @@ https://docs.djangoproject.com/en/1.8/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""
+from decouple import config
+from dj_database_url import parse as db_url
from unipath import Path
from .temp_suppress_crispy_form_warnings import \
SUPRESS_CRISPY_FORM_WARNINGS_LOGGING
-from decouple import config
-
-from dj_database_url import parse as db_url
-
BASE_DIR = Path(__file__).ancestor(2)
diff --git a/sapl/utils.py b/sapl/utils.py
index 77840dd76..71f640578 100644
--- a/sapl/utils.py
+++ b/sapl/utils.py
@@ -1,8 +1,10 @@
from datetime import date
from functools import wraps
+import magic
from django.apps import apps
from django.contrib import admin
+from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
@@ -123,3 +125,60 @@ UF = [
]
RANGE_ANOS = [(year, year) for year in range(date.today().year, 1889, -1)]
+
+TIPOS_TEXTO_PERMITIDOS = (
+ 'application/vnd.oasis.opendocument.text',
+ 'application/x-vnd.oasis.opendocument.text',
+ 'application/pdf',
+ 'application/x-pdf',
+ 'application/acrobat',
+ 'applications/vnd.pdf',
+ 'text/pdf',
+ 'text/x-pdf',
+ 'text/plain',
+ 'application/txt',
+ 'browser/internal',
+ 'text/anytext',
+ 'widetext/plain',
+ 'widetext/paragraph',
+ 'application/msword',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'application/xml',
+ 'text/xml',
+ 'text/html',
+ )
+
+TIPOS_IMG_PERMITIDOS = (
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/jpe_',
+ 'image/pjpeg',
+ 'image/vnd.swiftview-jpeg',
+ 'application/jpg',
+ 'application/x-jpg',
+ 'image/pjpeg',
+ 'image/pipeg',
+ 'image/vnd.swiftview-jpeg',
+ 'image/x-xbitmap',
+ 'image/bmp',
+ 'image/x-bmp',
+ 'image/x-bitmap',
+ 'image/png',
+ 'application/png',
+ 'application/x-png',
+)
+
+
+def fabrica_validador_de_tipos_de_arquivo(lista):
+
+ def restringe_tipos_de_arquivo(value):
+ mime = magic.from_buffer(value.read(), mime=True)
+ mime = mime.decode()
+ if mime not in lista:
+ raise ValidationError(_('Tipo de arquivo não suportado'))
+ return restringe_tipos_de_arquivo
+
+restringe_tipos_de_arquivo_txt = fabrica_validador_de_tipos_de_arquivo(
+ TIPOS_TEXTO_PERMITIDOS)
+restringe_tipos_de_arquivo_img = fabrica_validador_de_tipos_de_arquivo(
+ TIPOS_IMG_PERMITIDOS)
diff --git a/sessao/forms.py b/sessao/forms.py
index a8b7fef88..dd9c1ab34 100644
--- a/sessao/forms.py
+++ b/sessao/forms.py
@@ -1,7 +1,6 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Fieldset, Layout
from django import forms
-from django.core.exceptions import ValidationError
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
@@ -94,20 +93,6 @@ class SessaoForm(ModelForm):
'hora_fim': forms.TextInput(attrs={'class': 'hora'}),
}
- def clean_url_audio(self):
- url_audio = self.cleaned_data.get('url_audio', False)
- if url_audio:
- if url_audio.size > MAX_DOC_UPLOAD_SIZE:
- raise ValidationError("Arquivo muito grande. ( > 5mb )")
- return url_audio
-
- def clean_url_video(self):
- url_video = self.cleaned_data.get('url_video', False)
- if url_video:
- if url_video.size > MAX_DOC_UPLOAD_SIZE:
- raise ValidationError("Arquivo muito grande. ( > 5mb )")
- return url_video
-
def __init__(self, *args, **kwargs):
row1 = crispy_layout_mixin.to_row(
diff --git a/sessao/models.py b/sessao/models.py
index e38e87f63..6e7e2e86f 100644
--- a/sessao/models.py
+++ b/sessao/models.py
@@ -5,7 +5,7 @@ from model_utils import Choices
from materia.models import MateriaLegislativa
from parlamentares.models import (CargoMesa, Legislatura, Parlamentar,
SessaoLegislativa)
-from sapl.utils import YES_NO_CHOICES
+from sapl.utils import YES_NO_CHOICES, restringe_tipos_de_arquivo_txt
class TipoSessaoPlenaria(models.Model):
@@ -63,12 +63,14 @@ class SessaoPlenaria(models.Model):
blank=True,
null=True,
upload_to=pauta_upload_path,
- verbose_name=_('Pauta da Sessão'))
+ verbose_name=_('Pauta da Sessão'),
+ validators=[restringe_tipos_de_arquivo_txt])
upload_ata = models.FileField(
blank=True,
null=True,
upload_to=ata_upload_path,
- verbose_name=_('Ata da Sessão'))
+ verbose_name=_('Ata da Sessão'),
+ validators=[restringe_tipos_de_arquivo_txt])
iniciada = models.NullBooleanField(blank=True,
choices=YES_NO_CHOICES,
verbose_name=_('Sessão iniciada?'))
diff --git a/templates/materia/proposicao/proposicao_list.html b/templates/materia/proposicao/proposicao_list.html
index d666badbe..cb04c5bf0 100644
--- a/templates/materia/proposicao/proposicao_list.html
+++ b/templates/materia/proposicao/proposicao_list.html
@@ -3,16 +3,16 @@
{% load crispy_forms_tags %}
{% block actions %}{% endblock %}
-
+
{% block detail_content %}
+
+
Proposições
diff --git a/templates/sessao/sessao_list.html b/templates/sessao/sessao_list.html
index e005802a1..f85faa389 100644
--- a/templates/sessao/sessao_list.html
+++ b/templates/sessao/sessao_list.html
@@ -3,8 +3,8 @@
{% load crispy_forms_tags %}
{% block base_content %}
+Sessões Plenárias