Browse Source

Refatora manutenção de usuário

- elimina view class independentes
- elimina form class independentes
- impl UserCrud e UserAdminForm
pull/3372/head
Leandro Roberto 4 years ago
parent
commit
acd43abf46
  1. 304
      sapl/base/forms.py
  2. 26
      sapl/base/urls.py
  3. 279
      sapl/base/views.py
  4. 2
      sapl/crud/base.py
  5. 51
      sapl/templates/auth/user_filter.html
  6. 35
      sapl/templates/auth/user_form.html
  7. 7
      sapl/templates/base/layouts.yaml
  8. 57
      sapl/templates/base/usuario_detail.html
  9. 20
      sapl/templates/base/usuario_edit.html
  10. 14
      sapl/templates/crud/detail.html
  11. 8
      sapl/templates/crud/list.html
  12. 2
      sapl/templates/materia/materialegislativa_detail.html
  13. 6
      sapl/templates/materia/materialegislativa_filter.html
  14. 2
      sapl/templates/materia/proposicao_detail.html
  15. 6
      sapl/templates/materia/tramitacao_detail.html
  16. 2
      sapl/templates/navbar.yaml
  17. 2
      sapl/templates/norma/normajuridica_detail.html
  18. 2
      sapl/templates/protocoloadm/documentoadministrativo_detail.html
  19. 6
      sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

304
sapl/base/forms.py

@ -6,10 +6,10 @@ from crispy_forms.bootstrap import FieldWithButtons, InlineRadios, StrictButton,
from crispy_forms.layout import HTML, Button, Div, Field, Fieldset, Layout, Row, Submit from crispy_forms.layout import HTML, Button, Div, Field, Fieldset, Layout, Row, Submit
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model, password_validation
from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm, from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
SetPasswordForm) SetPasswordForm)
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User, Permission
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Q from django.db.models import Q
@ -57,206 +57,160 @@ STATUS_USER_CHOICE = [
] ]
def get_roles(): class UserAdminForm(ModelForm):
roles = [(g.id, g.name) for g in Group.objects.all().order_by('name')
if g.name != 'Votante']
return roles
is_active = forms.TypedChoiceField(label=_('Usuário Ativo'),
choices=YES_NO_CHOICES,
coerce=lambda x: x == 'True')
class UsuarioCreateForm(ModelForm): new_password1 = forms.CharField(
logger = logging.getLogger(__name__) label='Nova senha',
firstname = forms.CharField( max_length=50,
required=True, strip=False,
label="Nome", required=False,
max_length=30 widget=forms.PasswordInput(),
) help_text='Deixe os campos em branco para não fazer alteração de senha')
lastname = forms.CharField(
required=True,
label="Sobrenome",
max_length=30
)
password1 = forms.CharField(
required=True,
widget=forms.PasswordInput,
label='Senha',
min_length=6,
max_length=128
)
password2 = forms.CharField(
required=True,
widget=forms.PasswordInput,
label='Confirmar senha',
min_length=6,
max_length=128
)
user_active = forms.ChoiceField(
required=True,
choices=YES_NO_CHOICES,
label="Usuário ativo?",
initial='True'
)
roles = forms.MultipleChoiceField(
required=True,
widget=forms.CheckboxSelectMultiple(),
choices=get_roles
)
class Meta:
model = get_user_model()
fields = [
get_user_model().USERNAME_FIELD, 'firstname', 'lastname',
'password1', 'password2', 'user_active', 'roles'
] + (['email']
if get_user_model().USERNAME_FIELD != 'email' else [])
def clean(self):
super().clean()
if not self.is_valid():
return self.cleaned_data
data = self.cleaned_data
if data['password1'] != data['password2']:
self.logger.warning(
'Erro de validação. Senhas informadas são diferentes.')
raise ValidationError('Senhas informadas são diferentes')
return data
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
row0 = to_row([('username', 12)])
row1 = to_row([('firstname', 6),
('lastname', 6)])
row2 = to_row([('email', 6),
('user_active', 6)])
row3 = to_row(
[('password1', 6),
('password2', 6)])
self.helper = SaplFormHelper()
self.helper.layout = Layout(
row0,
row1,
row3,
row2,
'roles',
form_actions(label='Confirmar'))
class UsuarioFilterSet(django_filters.FilterSet):
username = django_filters.CharFilter(
label=_('Nome de Usuário'),
lookup_expr='icontains')
class Meta:
model = User
fields = ['username']
def __init__(self, *args, **kwargs):
super(UsuarioFilterSet, self).__init__(*args, **kwargs)
row0 = to_row([('username', 12)])
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Usuário'),
row0,
form_actions(label='Pesquisar'))
)
new_password2 = forms.CharField(
label='Confirmar senha',
max_length=50,
strip=False,
required=False,
widget=forms.PasswordInput(),
help_text='Deixe os campos em branco para não fazer alteração de senha')
class UsuarioEditForm(ModelForm): autor = forms.ModelChoiceField(
logger = logging.getLogger(__name__) label=_('Operador de Autor'),
# ROLES = [(g.id, g.name) for g in Group.objects.all().order_by('name')] queryset=Autor.objects.all(),
ROLES = [] required=False)
token = forms.CharField( token = forms.CharField(
required=False, required=False,
label="Token", label="Token",
max_length=40, max_length=40,
widget=forms.TextInput(attrs={'readonly': 'readonly'})) widget=forms.TextInput(attrs={'readonly': 'readonly'}))
first_name = forms.CharField(
required=False,
label="Nome",
max_length=30)
last_name = forms.CharField(
required=False,
label="Sobrenome",
max_length=30)
password1 = forms.CharField(
required=False,
widget=forms.PasswordInput,
label='Senha')
password2 = forms.CharField(
required=False, widget=forms.PasswordInput,
label='Confirmar senha')
user_active = forms.ChoiceField(
choices=YES_NO_CHOICES,
required=True,
label="Usuário ativo?",
initial='True')
roles = forms.MultipleChoiceField(
required=True,
widget=forms.CheckboxSelectMultiple(),
choices=get_roles)
class Meta: class Meta:
model = get_user_model() model = get_user_model()
fields = [ fields = [
get_user_model().USERNAME_FIELD, get_user_model().USERNAME_FIELD,
"token", 'first_name',
"first_name", 'last_name',
"last_name", 'is_active',
'password1',
'password2', 'token',
'user_active',
'roles'] 'new_password1',
'new_password2',
'groups',
'user_permissions'
]
if get_user_model().USERNAME_FIELD != 'email': if get_user_model().USERNAME_FIELD != 'email':
fields.extend(['email']) fields.extend(['email'])
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(UsuarioEditForm, self).__init__(*args, **kwargs)
rows = to_row(( self.user_session = kwargs.pop('user_session', None)
('first_name', 6), self.granular = kwargs.pop('granular', None)
('last_name', 6),
('email', 6), row_pwd = to_row(
('user_active', 6), [
('password1', 6), ('username', 4),
('password2', 6), ('email', 6),
('roles', 12))) ('is_active', 2),
('first_name', 6),
('last_name', 6),
('new_password1', 3),
('new_password2', 3),
(
FieldWithButtons(
'token',
StrictButton(
'Renovar',
id="renovar-token",
css_class="btn-outline-primary")
),
6
),
('groups', 12),
] + ([('user_permissions', 12)] if not self.granular is None else [])
)
self.helper = SaplFormHelper() self.helper = SaplFormHelper()
self.helper.layout = Layout( self.helper.layout = SaplFormLayout(row_pwd)
'username', super(UserAdminForm, self).__init__(*args, **kwargs)
FieldWithButtons('token', StrictButton(
'Renovar', id="renovar-token", css_class="btn-outline-primary")), if self.instance.pk:
rows,
form_actions( self.fields['token'].initial = self.instance.auth_token.key
more=[
HTML("<a href='{% url 'sapl.base:user_detail' object.pk %}' " self.fields[
"class='btn btn-dark'>Cancelar</a>")], 'groups'].widget = forms.CheckboxSelectMultiple()
label='Salvar Alterações')) self.fields['groups'].choices = [
(g.id, g) for g in self.instance.groups.exclude(name='Votante').order_by('name')
] + [
(g.id, g) for g in Group.objects.exclude(
user=self.instance).exclude(name='Votante').order_by('name')
]
self.fields[
'user_permissions'].widget = forms.CheckboxSelectMultiple()
if not self.granular is None:
self.fields['user_permissions'].choices = [
(p.id, p) for p in self.instance.user_permissions.all(
).order_by('content_type__app_label',
'content_type__model',
'codename')
] + [
(p.id, p) for p in Permission.objects.filter(
content_type__app_label__in=list(
map(lambda x: x.split('.')[-1], settings.SAPL_APPS))
).exclude(
user=self.instance
).order_by('content_type__app_label',
'content_type__model',
'codename')
]
# self.fields['user_permissions'].queryset = self.fields[
# 'user_permissions'].queryset.all().order_by('name')
def save(self, commit=True):
if self.cleaned_data['new_password1']:
self.instance.set_password(self.cleaned_data['new_password1'])
votante = None
if self.instance.id:
inst_old = get_user_model().objects.get(pk=self.instance.pk)
votante = inst_old.groups.filter(name='Votante').first()
inst_new = super().save(commit)
if votante:
inst_new.groups.add(votante)
return inst_new
def clean(self): def clean(self):
super().clean() data = super().clean()
if not self.is_valid():
return self.cleaned_data
data = self.cleaned_data if self.errors:
if data['password1'] and data['password1'] != data['password2']: return data
self.logger.warning(
"Erro de validação. Senhas informadas são diferentes.") new_password1 = data.get('new_password1', '')
raise ValidationError('Senhas informadas são diferentes') new_password2 = data.get('new_password2', '')
if new_password1 != new_password2:
raise forms.ValidationError(
_("As senhas informadas são diferentes"),
)
else:
if new_password1 and new_password2:
password_validation.validate_password(
new_password2, self.instance)
return data return data

26
sapl/base/urls.py

@ -3,22 +3,19 @@ import os
from django.conf.urls import include, url from django.conf.urls import include, url
from django.contrib.auth import views from django.contrib.auth import views
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.views import (PasswordResetView, PasswordResetCompleteView, PasswordResetConfirmView,
PasswordResetDoneView)
from django.urls.base import reverse_lazy
from django.views.generic.base import RedirectView, TemplateView from django.views.generic.base import RedirectView, TemplateView
from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView, from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica,
PesquisarAutorView, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView, PesquisarAutorView, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView,
RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView, RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView,
IndexView) IndexView, UserCrud)
from sapl.settings import EMAIL_SEND_USER, MEDIA_URL, LOGOUT_REDIRECT_URL from sapl.settings import MEDIA_URL, LOGOUT_REDIRECT_URL
from .apps import AppConfig from .apps import AppConfig
from .forms import LoginForm, NovaSenhaForm, RecuperarSenhaForm from .forms import LoginForm
from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, CreateUsuarioView, DeleteUsuarioView, from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
EditUsuarioView, HelpTopicView, PesquisarUsuarioView, LogotipoView, RelatorioAtasView, HelpTopicView, LogotipoView, RelatorioAtasView,
RelatorioAudienciaView, RelatorioDataFimPrazoTramitacaoView, RelatorioHistoricoTramitacaoView, RelatorioAudienciaView, RelatorioDataFimPrazoTramitacaoView, RelatorioHistoricoTramitacaoView,
RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAutorView, RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAutorView,
RelatorioMateriasTramitacaoView, RelatorioPresencaSessaoView, RelatorioReuniaoView, SaplSearchView, RelatorioMateriasTramitacaoView, RelatorioPresencaSessaoView, RelatorioReuniaoView, SaplSearchView,
@ -35,15 +32,8 @@ from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, CreateUsua
app_name = AppConfig.name app_name = AppConfig.name
admin_user = [ admin_user = [
url(r'^sistema/usuario/$', PesquisarUsuarioView.as_view(), name='usuario'), url(r'^sistema/usuario/', include(UserCrud.get_urls())),
url(r'^sistema/usuario/create$',
CreateUsuarioView.as_view(), name='user_create'),
url(r'^sistema/usuario/(?P<pk>\d+)$',
DetailUsuarioView.as_view(), name='user_detail'),
url(r'^sistema/usuario/(?P<pk>\d+)/edit$',
EditUsuarioView.as_view(), name='user_edit'),
url(r'^sistema/usuario/(?P<pk>\d+)/delete$',
DeleteUsuarioView.as_view(), name='user_delete')
] ]
alterar_senha = [ alterar_senha = [

279
sapl/base/views.py

@ -36,13 +36,14 @@ from rest_framework.authtoken.models import Token
from sapl import settings from sapl import settings
from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica
from sapl.base.forms import (AutorForm, AutorFormForAdmin, TipoAutorForm, AutorFilterSet, RecuperarSenhaForm, from sapl.base.forms import (AutorForm, AutorFormForAdmin, TipoAutorForm, AutorFilterSet, RecuperarSenhaForm,
NovaSenhaForm) NovaSenhaForm, UserAdminForm)
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.comissoes.models import Comissao, Reuniao from sapl.comissoes.models import Comissao, Reuniao
from sapl.crud.base import CrudAux, make_pagination from sapl.crud.base import CrudAux, make_pagination, Crud,\
ListWithSearchForm
from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio, MateriaEmTramitacao, MateriaLegislativa, from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio, MateriaEmTramitacao, MateriaLegislativa,
Proposicao, StatusTramitacao, TipoDocumento, TipoMateriaLegislativa, UnidadeTramitacao, Proposicao, StatusTramitacao, TipoDocumento, TipoMateriaLegislativa, UnidadeTramitacao,
MateriaAssunto, Tramitacao) MateriaAssunto)
from sapl.norma.models import NormaJuridica, TipoNormaJuridica from sapl.norma.models import NormaJuridica, TipoNormaJuridica
from sapl.parlamentares.models import ( from sapl.parlamentares.models import (
Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa) Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa)
@ -66,9 +67,9 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm,
RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet, RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet,
RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet, RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet,
RelatorioMateriasPorAutorFilterSet, RelatorioMateriasTramitacaoFilterSet, RelatorioMateriasPorAutorFilterSet, RelatorioMateriasTramitacaoFilterSet,
RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, UsuarioCreateForm, UsuarioEditForm, RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet,
RelatorioNormasMesFilterSet, RelatorioNormasVigenciaFilterSet, EstatisticasAcessoNormasForm, RelatorioNormasMesFilterSet, RelatorioNormasVigenciaFilterSet, EstatisticasAcessoNormasForm,
UsuarioFilterSet, RelatorioHistoricoTramitacaoAdmFilterSet, RelatorioDocumentosAcessoriosFilterSet, RelatorioHistoricoTramitacaoAdmFilterSet, RelatorioDocumentosAcessoriosFilterSet,
RelatorioNormasPorAutorFilterSet) RelatorioNormasPorAutorFilterSet)
from .models import AppConfig, CasaLegislativa from .models import AppConfig, CasaLegislativa
@ -1936,208 +1937,118 @@ class ListarProtocolosDuplicadosView(PermissionRequiredMixin, ListView):
return context return context
class PesquisarUsuarioView(PermissionRequiredMixin, FilterView): class UserCrud(Crud):
model = get_user_model() model = get_user_model()
filterset_class = UsuarioFilterSet
permission_required = ('base.list_appconfig',)
paginate_by = 10
def get_filterset_kwargs(self, filterset_class):
super(PesquisarUsuarioView,
self).get_filterset_kwargs(filterset_class)
kwargs = {'data': self.request.GET or None}
qs = self.get_queryset().order_by('username').distinct()
kwargs.update({
'queryset': qs,
})
return kwargs
def get_context_data(self, **kwargs):
context = super(PesquisarUsuarioView, self).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context.update({
"page_range": make_pagination(page_obj.number, paginator.num_pages),
"NO_ENTRIES_MSG": "Nenhum usuário encontrado!",
"title": _("Usuários")
})
return context
def get(self, request, *args, **kwargs):
super(PesquisarUsuarioView, self).get(request)
data = self.filterset.data
url = ''
if data:
url = "&" + str(self.request.META['QUERY_STRING'])
if url.startswith("&page"):
ponto_comeco = url.find('username=') - 1
url = url[ponto_comeco:]
context = self.get_context_data(filter=self.filterset,
object_list=self.object_list,
filter_url=url,
numero_res=len(self.object_list)
)
context['show_results'] = show_results_filter_set(
self.request.GET.copy())
return self.render_to_response(context)
class BaseMixin(Crud.BaseMixin):
list_field_names = [
'usuario', 'groups', 'is_active'
]
class DetailUsuarioView(PermissionRequiredMixin, DetailView): def resolve_url(self, suffix, args=None):
model = get_user_model() return reverse('sapl.base:%s' % self.url_name(suffix),
template_name = "base/usuario_detail.html" args=args)
permission_required = ('base.detail_appconfig',)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = get_user_model().objects.get(id=self.kwargs['pk'])
context.update({
"user": user,
"token": Token.objects.filter(user=user)[0],
"roles": [
{
"checked": "checked" if g in user.groups.all() else "unchecked",
"group": g.name
} for g in Group.objects.all().order_by("name") if g.name != 'Votante']
})
return context def get_layout(self):
return super().get_layout(
'base/layouts.yaml'
class CreateUsuarioView(PermissionRequiredMixin, CreateView): )
model = get_user_model()
form_class = UsuarioCreateForm
success_message = 'Usuário criado com sucesso!'
fail_message = 'Usuário não criado!'
permission_required = ('base.add_appconfig',)
def get_success_url(self, pk): def get_context_object_name(self, *args, **kwargs):
return reverse('sapl.base:user_detail', kwargs={"pk": pk}) return None
def form_valid(self, form): class CreateView(Crud.CreateView):
data = form.cleaned_data form_class = UserAdminForm
new_user = get_user_model().objects.create(
username=data['username'],
email=data['email'],
first_name=data['firstname'],
last_name=data['lastname'],
is_superuser=False,
is_staff=False
)
new_user.set_password(data['password1'])
new_user.save()
groups = Group.objects.filter(id__in=data['roles']) class UpdateView(Crud.UpdateView):
for g in groups: form_class = UserAdminForm
g.user_set.add(new_user) layout_key = None
messages.success(self.request, self.success_message) def get_form_kwargs(self):
return HttpResponseRedirect(self.get_success_url(new_user.pk)) kwargs = Crud.UpdateView.get_form_kwargs(self)
kwargs['user_session'] = self.request.user
granular = self.request.GET.get('granular', None)
if not granular is None:
kwargs['granular'] = granular
return kwargs
class DetailView(Crud.DetailView):
layout_key = 'UserDetail'
def hook_usuario(self, obj):
return 'Usuário', '{}<br><small>{}</small>'.format(
obj.get_full_name() or '...',
obj.email
)
def form_invalid(self, form): def hook_auth_token(self, obj):
messages.error(self.request, self.fail_message) return 'Token', str(obj.auth_token)
return super().form_invalid(form)
def hook_username(self, obj):
return 'username', obj.username
class DeleteUsuarioView(PermissionRequiredMixin, DeleteView): def get_context_data(self, **kwargs):
model = get_user_model() context = Crud.DetailView.get_context_data(self, **kwargs)
template_name = "crud/confirm_delete.html" context['title'] = '{} <i>({})</i><br><small>{}</small>'.format(
permission_required = ('base.delete_appconfig',) self.object.get_full_name() or '...',
success_url = reverse_lazy('sapl.base:usuario') self.object.username,
success_message = "Usuário removido com sucesso!" self.object.email
)
return context
def delete(self, request, *args, **kwargs): @property
try: def extras_url(self):
super(DeleteUsuarioView, self).delete(request, *args, **kwargs) btns = [
except ProtectedError as exception: (
error_url = reverse_lazy('sapl.base:user_delete', kwargs={ '{}?granular'.format(reverse('sapl.base:user_update',
'pk': self.kwargs['pk']}) kwargs={'pk': self.object.pk})),
error_message = "O usuário não pode ser removido, pois é referenciado por:<br><ul>" 'btn-outline-primary',
_('Edição granular')
for e in exception.protected_objects:
error_message += '<li>{} - {}</li>'.format(
e._meta.verbose_name, e
) )
error_message += '</ul>' ]
messages.error(self.request, error_message)
return HttpResponseRedirect(error_url)
messages.success(self.request, self.success_message) return btns
return HttpResponseRedirect(self.success_url)
@property class ListView(Crud.ListView):
def cancel_url(self): form_search_class = ListWithSearchForm
return reverse('sapl.base:user_edit', ordered_list = None
kwargs={'pk': self.kwargs['pk']}) paginate_by = 300
def get_context_data(self, **kwargs):
context = Crud.ListView.get_context_data(self, **kwargs)
context['subnav_template_name'] = None
return context
class EditUsuarioView(PermissionRequiredMixin, UpdateView): def hook_header_usuario(self, *args, **kwargs):
model = get_user_model() return 'Usuário'
form_class = UsuarioEditForm
template_name = "base/usuario_edit.html"
success_message = 'Usuário editado com sucesso!'
permission_required = ('base.change_appconfig',)
def get_success_url(self):
return reverse('sapl.base:user_detail', kwargs={"pk": self.kwargs['pk']})
def get_initial(self):
initial = super().get_initial()
user = get_user_model().objects.get(id=self.kwargs['pk'])
roles = [str(g.id) for g in user.groups.all()]
initial.update({
"token": Token.objects.filter(user=user)[0],
"first_name": user.first_name,
"last_name": user.last_name,
"roles": roles,
"user_active": user.is_active
})
return initial
def form_valid(self, form):
user = form.save(commit=False)
data = form.cleaned_data
if 'first_name' in data and data['first_name'] != user.first_name:
user.first_name = data['first_name']
if 'last_name' in data and data['last_name'] != user.last_name:
user.last_name = data['last_name']
if data['password1']: def hook_header_groups(self, *args, **kwargs):
user.set_password(data['password1']) return 'Grupos'
if data['user_active'] == 'True' and not user.is_active: def hook_header_active(self, *args, **kwargs):
user.is_active = True return 'is_active'
elif data['user_active'] == 'False' and user.is_active:
user.is_active = False
user.save() def hook_usuario(self, *args, **kwargs):
return '{} <i>({})</i><br><small>{}</small>'.format(
args[0].get_full_name() or '...',
args[0].username,
args[0].email
), args[2]
for g in user.groups.all().exclude(name='Votante'): def get_queryset(self):
g.user_set.remove(user) qs = self.model.objects.all()
q_param = self.request.GET.get('q', '')
if q_param:
q = Q(first_name__icontains=q_param)
q |= Q(last_name__icontains=q_param)
q |= Q(email__icontains=q_param)
q |= Q(username__icontains=q_param)
qs = qs.filter(q)
groups = Group.objects.filter(id__in=data['roles']) return qs
for g in groups:
g.user_set.add(user)
messages.success(self.request, self.success_message) def dispatch(self, request, *args, **kwargs):
return super(EditUsuarioView, self).form_valid(form) return Crud.ListView.dispatch(self, request, *args, **kwargs)
class CasaLegislativaCrud(CrudAux): class CasaLegislativaCrud(CrudAux):

2
sapl/crud/base.py

@ -157,7 +157,7 @@ class ListWithSearchForm(forms.Form):
FieldWithButtons( FieldWithButtons(
Field('q', Field('q',
placeholder=_('Filtrar Lista'), placeholder=_('Filtrar Lista'),
css_class='input-lg'), css_class='form-control-lg'),
StrictButton( StrictButton(
_('Filtrar'), css_class='btn-outline-primary btn-lg', _('Filtrar'), css_class='btn-outline-primary btn-lg',
type='submit')) type='submit'))

51
sapl/templates/auth/user_filter.html

@ -1,51 +0,0 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags staticfiles %}
{% block base_content %}
{% if not show_results %}
{% crispy filter.form %}
<a href="{% url 'sapl.base:user_create' %}" class="btn btn-outline-primary">{% trans 'Criar usuário' %}</a>
{% endif %}
{% if show_results %}
<div class="actions btn-group float-right" role="group">
<a href="{% url 'sapl.base:usuario' %}" class="btn btn-outline-primary">{% trans 'Fazer nova pesquisa' %}</a>
<a href="{% url 'sapl.base:user_create' %}" class="btn btn-outline-primary">{% trans 'Criar usuário' %}</a>
</div>
<br /><br />
{% if numero_res > 0 %}
{% if numero_res == 1 %}
<p>Foi encontrado {{ numero_res }} resultado</p>
{% else %}
<p>Foram encontrados {{ numero_res }} resultados</p>
{% endif %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Nome de Usuário</th>
<th>Nome</th>
<th>E-mail do Usuário</th>
</tr>
</thead>
<tbody>
{% for usuario in page_obj %}
<tr>
<td>
<a href="{% url 'sapl.base:user_detail' usuario.pk %}">{{ usuario.username }}</a>
</td>
<td>{{ usuario.first_name }} {{ usuario.last_name }}</td>
<td>{{ usuario.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<font size="4"><p align="center">{{ NO_ENTRIES_MSG }}</p></font>
{% endif %}
{% endif %}
<br/>
{% include 'paginacao.html'%}
<br /><br /><br />
{% endblock base_content %}

35
sapl/templates/auth/user_form.html

@ -1,19 +1,20 @@
{% extends "base.html" %} {% extends "crud/form.html" %}
{% load i18n crispy_forms_tags %} {% load i18n %}
{% block base_content %} {% block extra_js %}
<script type="text/javascript">
$(() => {
var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
$("#renovar-token").click(() => {
$.ajax({
url: "{% url 'sapl.api:recria_token' object.id %}",
type: "POST",
headers: { "X-CSRFToken": $crf_token },
dataType: "json",
success: (res) => $("#id_token").val(res.token)
});
});
});
</script>
<form action="" method="post"> {% endblock %}
{% csrf_token %}
{% if object.pk %}
<div class="actions btn-group float-left" role="group">
<a href="{% url 'sapl.base:usuario' %}" class="btn btn-outline-primary">{% trans 'Pesquisar usuários' %}</a>
<a href="{% url 'sapl.base:user_create' %}" class="btn btn-outline-primary">{% trans 'Criar usuário' %}</a>
</div>
<a href="{% url 'sapl.base:user_delete' object.pk %}" class="btn btn-outline-danger float-right">{% trans 'Remover usuário' %}</a>
<br /> <br />
{% endif %}
{% crispy form %}
</form>
<br /><br /><br />
{% endblock base_content %}

7
sapl/templates/base/layouts.yaml

@ -10,6 +10,13 @@ CasaLegislativa:
- email - email
- informacao_geral - informacao_geral
UserDetail:
{% trans 'Usuário' %}:
- usuario username:3 is_active:2
- auth_token
- groups
- user_permissions
AppConfig: AppConfig:
{% trans 'Configurações Gerais' %}: {% trans 'Configurações Gerais' %}:

57
sapl/templates/base/usuario_detail.html

@ -1,57 +0,0 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags cropping %}
{% block base_content %}
<div class="actions btn-group float-right " role="group" style="margin: 0px 0px 20px">
<a href="{% url 'sapl.base:usuario' %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Fazer nova pesquisa {% endblocktrans %}
</a>
<a href="{% url 'sapl.base:user_edit' user.pk %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Editar usuário {% endblocktrans %}
</a>
</div>
<div>
<table class="table table-striped">
<tbody>
<tr>
<th scope="row">Usuário</th>
<td>{{ user.username }}</td>
</tr>
<tr>
<th scope="row">Token</th>
<td>{{ token }}</td>
</tr>
<tr>
<th scope="row">Nome</th>
<td>{% firstof user.first_name "-" %}</td>
</tr>
<tr>
<th scope="row">Sobrenome</th>
<td>{% firstof user.last_name "-" %}</td>
</tr>
<tr>
<th scope="row">Endereço de e-mail</th>
<td>{% firstof user.email "-" %}</td>
</tr>
<tr>
<th scope="row">Usuário ativo?</th>
<td>{% if user.is_active %} Sim {% else %} Não {% endif %}</td>
</tr>
<tr>
<th scope="row">Último acesso</th>
<td>{{ user.last_login }}</td>
</tr>
<tr>
<th scope="row">Roles</th>
<td><ul style="list-style-type:none">
{% for r in roles %}
<li><input type="checkbox" {{ r.checked }} disabled> {{r.group }}</li>
{% endfor %}
</ul></td>
</tr>
</tbody>
</table>
</div>
{% endblock base_content %}

20
sapl/templates/base/usuario_edit.html

@ -1,20 +0,0 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% block extra_js %}
<script type="text/javascript">
$(() => {
var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
$("#renovar-token").click(() => {
$.ajax({
url: "{% url 'sapl.api:recria_token' user.id %}",
type: "POST",
headers: { "X-CSRFToken": $crf_token },
dataType: "json",
success: (res) => $("#id_token").val(res.token)
});
});
});
</script>
{% endblock %}

14
sapl/templates/crud/detail.html

@ -3,11 +3,9 @@
{% block base_content %} {% block base_content %}
<div class="d-flex context-actions justify-content-between align-items-center"> <div class="context-actions clearfix">
{% block actions %} {% block actions %}
{% block sub_actions %} {% block sub_actions %}
<div class="actions btn-group btn-group-sm" role="group"> <div class="actions btn-group btn-group-sm" role="group">
{% if view.list_url %} {% if view.list_url %}
<a href="{{ view.list_url }}" class="btn btn-outline-primary">{% trans 'Listar' %} {{view.verbose_name_plural}}</a> <a href="{{ view.list_url }}" class="btn btn-outline-primary">{% trans 'Listar' %} {{view.verbose_name_plural}}</a>
@ -23,10 +21,10 @@
</div> </div>
{% if view.extras_url %} {% if view.extras_url %}
<div class="actions btn-group btn-group-sm" role="group"> <div class="actions btn-group btn-group-sm" role="group">
{% for href, css_class, text in view.extras_url %} {% for href, css_class, text in view.extras_url %}
<a href="{{href}}" class="btn btn-outline-primary {{css_class}}"> <a href="{{href}}" class="btn btn-outline-primary {{css_class}}">
{{text}} {{text}}
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
@ -35,7 +33,7 @@
{% block extra_actions %} {% block extra_actions %}
{% endblock extra_actions %} {% endblock extra_actions %}
<div class="editons"> <div class="editons float-right">
{% block editions %} {% block editions %}
{% if view.update_url or view.delete_url %} {% if view.update_url or view.delete_url %}
<div class="actions btn-group" role="group"> <div class="actions btn-group" role="group">

8
sapl/templates/crud/list.html

@ -3,16 +3,14 @@
{% block base_content %} {% block base_content %}
<div class="context-actions clearfix"> <div class="d-flex context-actions justify-content-between align-items-start">
<div class="actions search flex-grow-1 pr-3">
<div class="actions search">
{% if form %} {% if form %}
{% crispy form %} {% crispy form %}
{% endif %} {% endif %}
</div> </div>
{% block actions %} {% block actions %}
<div class="actions btn-group float-right btn-group-lg" role="group"> <div class="actions btn-group btn-group-lg" role="group">
{% if view.create_url %} {% if view.create_url %}
<a href="{{ view.create_url }}" class="btn btn-outline-primary"> <a href="{{ view.create_url }}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %} {% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}

2
sapl/templates/materia/materialegislativa_detail.html

@ -60,7 +60,7 @@
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' materia.user.pk %}"> <a href="{% url 'sapl.base:user_update' materia.user.pk %}">
{{ materia.user }} {{ materia.user }}
</a> </a>
</div> </div>

6
sapl/templates/materia/materialegislativa_filter.html

@ -5,7 +5,7 @@
{% block actions %} {% block actions %}
<div class="actions btn-group float-right" role="group"> <div class="actions btn-group" role="group">
{% if USE_SOLR %} {% if USE_SOLR %}
<a href="{% url 'sapl.base:haystack_search' %}" class="btn btn-outline-primary"> <a href="{% url 'sapl.base:haystack_search' %}" class="btn btn-outline-primary">
Pesquisa Textual Pesquisa Textual
@ -79,9 +79,9 @@
{% endfor %} {% endfor %}
</br> </br>
{% endif %} {% endif %}
{% if not tipo_listagem or tipo_listagem == '1' %} {% if not tipo_listagem or tipo_listagem == '1' %}
{% if m.tramitacao_set.first.unidade_tramitacao_destino %} {% if m.tramitacao_set.first.unidade_tramitacao_destino %}
<strong>Localização Atual:</strong> &nbsp;{{m.tramitacao_set.first.unidade_tramitacao_destino}}</br> <strong>Localização Atual:</strong> &nbsp;{{m.tramitacao_set.first.unidade_tramitacao_destino}}</br>
{% endif %} {% endif %}

2
sapl/templates/materia/proposicao_detail.html

@ -173,7 +173,7 @@
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' proposicao.user.pk %}">{{ proposicao.user }}</a> <a href="{% url 'sapl.base:user_update' proposicao.user.pk %}">{{ proposicao.user }}</a>
</div> </div>
</div> </div>
</div> </div>

6
sapl/templates/materia/tramitacao_detail.html

@ -8,11 +8,11 @@
{% if tramitacao.user %} {% if tramitacao.user %}
<div class="col-sm-4"> <div class="col-sm-4">
<div id="div_id_user" class="form-group"> <div id="div_id_user" class="form-group">
<p class="control-label">Usuário</p> <p class="control-label">Usuário</p>
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' tramitacao.user.pk %}"> <a href="{% url 'sapl.base:user_update' tramitacao.user.pk %}">
{{ tramitacao.user }} {{ tramitacao.user }}
</a> </a>
</div> </div>
@ -24,7 +24,7 @@
{% if tramitacao.ip %} {% if tramitacao.ip %}
<div class="col-sm-4"> <div class="col-sm-4">
<div id="div_ip_user" class="form-group"> <div id="div_ip_user" class="form-group">
<p class="control-label">IP</p> <p class="control-label">IP</p>
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">

2
sapl/templates/navbar.yaml

@ -92,7 +92,7 @@
url: '/sistema' url: '/sistema'
check_permission: base.view_tabelas_auxiliares check_permission: base.view_tabelas_auxiliares
- title: {% trans 'Administração de Usuários' %} - title: {% trans 'Administração de Usuários' %}
url: {% url 'sapl.base:usuario' %} url: {% url 'sapl.base:user_list' %}
check_permission: user.is_superuser check_permission: user.is_superuser
- title: {% trans 'Inconsistências de Dados' %} - title: {% trans 'Inconsistências de Dados' %}
url: {% url 'sapl.base:lista_inconsistencias' %} url: {% url 'sapl.base:lista_inconsistencias' %}

2
sapl/templates/norma/normajuridica_detail.html

@ -93,7 +93,7 @@
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' object.user.pk %}"> <a href="{% url 'sapl.base:user_update' object.user.pk %}">
{{ object.user }} {{ object.user }}
</a> </a>
</div> </div>

2
sapl/templates/protocoloadm/documentoadministrativo_detail.html

@ -12,7 +12,7 @@
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' documentoadministrativo.user.pk %}"> <a href="{% url 'sapl.base:user_update' documentoadministrativo.user.pk %}">
{{ documentoadministrativo.user }} {{ documentoadministrativo.user }}
</a> </a>
</div> </div>

6
sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

@ -22,11 +22,11 @@
{% if tramitacaoadministrativo.user %} {% if tramitacaoadministrativo.user %}
<div class="col-sm-4"> <div class="col-sm-4">
<div id="div_id_user" class="form-group"> <div id="div_id_user" class="form-group">
<p class="control-label">Usuário</p> <p class="control-label">Usuário</p>
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' tramitacaoadministrativo.user.pk %}"> <a href="{% url 'sapl.base:user_update' tramitacaoadministrativo.user.pk %}">
{{ tramitacaoadministrativo.user }} {{ tramitacaoadministrativo.user }}
</a> </a>
</div> </div>
@ -38,7 +38,7 @@
{% if tramitacaoadministrativo.ip %} {% if tramitacaoadministrativo.ip %}
<div class="col-sm-4"> <div class="col-sm-4">
<div id="div_ip_user" class="form-group"> <div id="div_ip_user" class="form-group">
<p class="control-label">IP</p> <p class="control-label">IP</p>
<div class="controls"> <div class="controls">
<div class="form-control-static"> <div class="form-control-static">
<div class="dont-break-out"> <div class="dont-break-out">

Loading…
Cancel
Save