Commit 23732800 authored by chirac's avatar chirac

Merge branch 'acl' into 'master'

Acl

See merge request federez/re2o!55
parents 09157a6a 2c6697a2
......@@ -21,3 +21,4 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from .acl import *
# -*- mode: python; coding: utf-8 -*-
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""cotisations.acl
Here are defined some functions to check acl on the application.
"""
def can_view(user):
"""Check if an user can view the application.
Args:
user: The user who wants to view the application.
Returns:
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_module_perms('cotisations')
return can, None if can else "Vous ne pouvez pas voir cette application."
......@@ -43,6 +43,8 @@ from django.forms import ModelForm, Form
from django.core.validators import MinValueValidator
from .models import Article, Paiement, Facture, Banque
from re2o.field_permissions import FieldPermissionFormMixin
class NewFactureForm(ModelForm):
"""Creation d'une facture, moyen de paiement, banque et numero
......@@ -141,27 +143,18 @@ class NewFactureFormPdf(Form):
)
class EditFactureForm(NewFactureForm):
class EditFactureForm(FieldPermissionFormMixin, NewFactureForm):
"""Edition d'une facture : moyen de paiement, banque, user parent"""
class Meta(NewFactureForm.Meta):
fields = ['paiement', 'banque', 'cheque', 'user']
model = Facture
fields = '__all__'
def __init__(self, *args, **kwargs):
super(EditFactureForm, self).__init__(*args, **kwargs)
self.fields['user'].label = 'Adherent'
self.fields['user'].empty_label = "Séléctionner\
l'adhérent propriétaire"
class TrezEditFactureForm(EditFactureForm):
"""Vue pour édition controle trésorier"""
class Meta(EditFactureForm.Meta):
fields = '__all__'
def __init__(self, *args, **kwargs):
super(TrezEditFactureForm, self).__init__(*args, **kwargs)
self.fields['valid'].label = 'Validité de la facture'
self.fields['control'].label = 'Contrôle de la facture'
class ArticleForm(ModelForm):
......@@ -180,11 +173,19 @@ class DelArticleForm(Form):
"""Suppression d'un ou plusieurs articles en vente. Choix
parmis les modèles"""
articles = forms.ModelMultipleChoiceField(
queryset=Article.objects.all(),
queryset=Article.objects.none(),
label="Articles actuels",
widget=forms.CheckboxSelectMultiple
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
super(DelArticleForm, self).__init__(*args, **kwargs)
if instances:
self.fields['articles'].queryset = instances
else:
self.fields['articles'].queryset = Article.objects.all()
class PaiementForm(ModelForm):
"""Creation d'un moyen de paiement, champ text moyen et type
......@@ -204,11 +205,19 @@ class DelPaiementForm(Form):
"""Suppression d'un ou plusieurs moyens de paiements, selection
parmis les models"""
paiements = forms.ModelMultipleChoiceField(
queryset=Paiement.objects.all(),
queryset=Paiement.objects.none(),
label="Moyens de paiement actuels",
widget=forms.CheckboxSelectMultiple
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
super(DelPaiementForm, self).__init__(*args, **kwargs)
if instances:
self.fields['paiements'].queryset = instances
else:
self.fields['paiements'].queryset = Paiement.objects.all()
class BanqueForm(ModelForm):
"""Creation d'une banque, field name"""
......@@ -225,7 +234,15 @@ class BanqueForm(ModelForm):
class DelBanqueForm(Form):
"""Selection d'une ou plusieurs banques, pour suppression"""
banques = forms.ModelMultipleChoiceField(
queryset=Banque.objects.all(),
queryset=Banque.objects.none(),
label="Banques actuelles",
widget=forms.CheckboxSelectMultiple
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
super(DelBanqueForm, self).__init__(*args, **kwargs)
if instances:
self.fields['banques'].queryset = instances
else:
self.fields['banques'].queryset = Banque.objects.all()
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-12-30 23:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0027_auto_20171029_1156'),
]
operations = [
migrations.AlterModelOptions(
name='article',
options={'permissions': (('view_article', 'Peut voir un objet article'),)},
),
migrations.AlterModelOptions(
name='banque',
options={'permissions': (('view_banque', 'Peut voir un objet banque'),)},
),
migrations.AlterModelOptions(
name='cotisation',
options={'permissions': (('view_cotisation', 'Peut voir un objet cotisation'), ('change_all_cotisation', 'Superdroit, peut modifier toutes les cotisations'))},
),
migrations.AlterModelOptions(
name='facture',
options={'permissions': (('change_facture_control', "Peut changer l'etat de controle"), ('change_facture_pdf', 'Peut éditer une facture pdf'), ('view_facture', 'Peut voir un objet facture'), ('change_all_facture', 'Superdroit, peut modifier toutes les factures'))},
),
migrations.AlterModelOptions(
name='paiement',
options={'permissions': (('view_paiement', 'Peut voir un objet paiement'),)},
),
migrations.AlterModelOptions(
name='vente',
options={'permissions': (('view_vente', 'Peut voir un objet vente'), ('change_all_vente', 'Superdroit, peut modifier toutes les ventes'))},
),
]
......@@ -56,8 +56,10 @@ from django.db.models import Max
from django.utils import timezone
from machines.models import regen
from re2o.field_permissions import FieldPermissionModelMixin
class Facture(models.Model):
class Facture(FieldPermissionModelMixin, models.Model):
""" Définition du modèle des factures. Une facture regroupe une ou
plusieurs ventes, rattachée à un user, et reliée à un moyen de paiement
et si il y a lieu un numero pour les chèques. Possède les valeurs
......@@ -76,6 +78,15 @@ class Facture(models.Model):
valid = models.BooleanField(default=True)
control = models.BooleanField(default=False)
class Meta:
abstract = False
permissions = (
("change_facture_control", "Peut changer l'etat de controle"),
("change_facture_pdf", "Peut éditer une facture pdf"),
("view_facture", "Peut voir un objet facture"),
("change_all_facture", "Superdroit, peut modifier toutes les factures"),
)
def prix(self):
"""Renvoie le prix brut sans les quantités. Méthode
dépréciée"""
......@@ -103,6 +114,59 @@ class Facture(models.Model):
).values_list('name', flat=True))
return name
def get_instance(factureid, *args, **kwargs):
return Facture.objects.get(pk=factureid)
def can_create(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.add_facture'), u"Vous n'avez pas le\
droit de créer des factures"
def can_edit(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.change_facture'):
return False, u"Vous n'avez pas le droit d'éditer les factures"
elif not user_request.has_perm('cotisations.change_all_facture') and\
(self.control or not self.valid):
return False, u"Vous n'avez pas le droit d'éditer une facture\
controlée ou invalidée par un trésorier"
else:
return True, None
def can_delete(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.delete_facture'):
return False, u"Vous n'avez pas le droit de supprimer une facture"
if self.control or not self.valid:
return False, u"Vous ne pouvez pas supprimer une facture\
contrôlée ou invalidée par un trésorier"
else:
return True, None
def can_view_all(user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_facture'):
return False, u"Vous n'avez pas le droit de voir les factures"
return True, None
def can_view(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_facture') and\
self.user != user_request:
return False, u"Vous ne pouvez pas afficher l'historique d'une\
facture d'un autre user que vous sans droit cableur"
elif not self.valid:
return False, u"La facture est invalidée et ne peut être affichée"
else:
return True, None
@staticmethod
def can_change_control(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_facture_control'), "Vous ne pouvez pas éditer le controle sans droit trésorier"
@staticmethod
def can_change_pdf(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_facture_pdf'), "Vous ne pouvez pas éditer une facture sans droit trésorier"
field_permissions = {
'control': can_change_control,
}
def __str__(self):
return str(self.user) + ' ' + str(self.date)
......@@ -149,6 +213,12 @@ class Vente(models.Model):
max_length=255
)
class Meta:
permissions = (
("view_vente", "Peut voir un objet vente"),
("change_all_vente", "Superdroit, peut modifier toutes les ventes"),
)
def prix_total(self):
"""Renvoie le prix_total de self (nombre*prix)"""
return self.prix*self.number
......@@ -201,6 +271,46 @@ class Vente(models.Model):
self.update_cotisation()
super(Vente, self).save(*args, **kwargs)
def get_instance(venteid, *args, **kwargs):
return Vente.objects.get(pk=venteid)
def can_create(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.add_vente'), u"Vous n'avez pas le\
droit de créer des ventes"
return True, None
def can_edit(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.change_vente'):
return False, u"Vous n'avez pas le droit d'éditer les ventes"
elif not user_request.has_perm('cotisations.change_all_vente') and\
(self.facture.control or not self.facture.valid):
return False, u"Vous n'avez pas le droit d'éditer une vente\
controlée ou invalidée par un trésorier"
else:
return True, None
def can_delete(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.delete_vente'):
return False, u"Vous n'avez pas le droit de supprimer une vente"
if self.facture.control or not self.facture.valid:
return False, u"Vous ne pouvez pas supprimer une vente\
contrôlée ou invalidée par un trésorier"
else:
return True, None
def can_view_all(user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_vente'):
return False, u"Vous n'avez pas le droit de voir les ventes"
return True, None
def can_view(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_vente') and\
self.facture.user != user_request:
return False, u"Vous ne pouvez pas afficher l'historique d'une\
facture d'un autre user que vous sans droit cableur"
else:
return True, None
def __str__(self):
return str(self.name) + ' ' + str(self.facture)
......@@ -269,6 +379,11 @@ class Article(models.Model):
unique_together = ('name', 'type_user')
class Meta:
permissions = (
("view_article", "Peut voir un objet article"),
)
def clean(self):
if self.name.lower() == "solde":
raise ValidationError("Solde est un nom d'article invalide")
......@@ -277,6 +392,29 @@ class Article(models.Model):
"La durée est obligatoire si il s'agit d'une cotisation"
)
def get_instance(articleid, *args, **kwargs):
return Article.objects.get(pk=articleid)
def can_create(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.add_article'), u"Vous n'avez pas le\
droit d'ajouter des articles"
def can_edit(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_article'), u"Vous n'avez pas le\
droit d'éditer des articles"
def can_delete(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.delete_article'), u"Vous n'avez pas le\
droit de supprimer des articles"
def can_view_all(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.view_article'), u"Vous n'avez pas le\
droit de voir des articles"
def can_view(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.view_article'), u"Vous n'avez pas le\
droit de voir des articles"
def __str__(self):
return self.name
......@@ -287,6 +425,34 @@ class Banque(models.Model):
name = models.CharField(max_length=255)
class Meta:
permissions = (
("view_banque", "Peut voir un objet banque"),
)
def get_instance(banqueid, *args, **kwargs):
return Banque.objects.get(pk=banqueid)
def can_create(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.add_banque'), u"Vous n'avez pas le\
droit d'ajouter des banques"
def can_edit(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_banque'), u"Vous n'avez pas le\
droit d'éditer des banques"
def can_delete(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.delete_banque'), u"Vous n'avez pas le\
droit de supprimer des banques"
def can_view_all(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.view_banque'), u"Vous n'avez pas le\
droit de voir des banques"
def can_view(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.view_banque'), u"Vous n'avez pas le\
droit de voir des banques"
def __str__(self):
return self.name
......@@ -302,6 +468,34 @@ class Paiement(models.Model):
moyen = models.CharField(max_length=255)
type_paiement = models.IntegerField(choices=PAYMENT_TYPES, default=0)
class Meta:
permissions = (
("view_paiement", "Peut voir un objet paiement"),
)
def get_instance(paiementid, *args, **kwargs):
return Paiement.objects.get(pk=paiementid)
def can_create(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.add_paiement'), u"Vous n'avez pas le\
droit d'ajouter des paiements"
def can_edit(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.change_paiement'), u"Vous n'avez pas le\
droit d'éditer des paiements"
def can_delete(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.delete_paiement'), u"Vous n'avez pas le\
droit de supprimer des paiements"
def can_view_all(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.view_paiement'), u"Vous n'avez pas le\
droit de voir des paiements"
def can_view(self, user_request, *args, **kwargs):
return user_request.has_perm('cotisations.view_paiement'), u"Vous n'avez pas le\
droit de voir des paiements"
def __str__(self):
return self.moyen
......@@ -334,6 +528,52 @@ class Cotisation(models.Model):
date_start = models.DateTimeField()
date_end = models.DateTimeField()
class Meta:
permissions = (
("view_cotisation", "Peut voir un objet cotisation"),
("change_all_cotisation", "Superdroit, peut modifier toutes les cotisations"),
)
def get_instance(cotisationid, *args, **kwargs):
return Cotisations.objects.get(pk=cotisationid)
def can_create(user_request, *args, **kwargs):
return user_request.has_perm('cotisations.add_cotisation'), u"Vous n'avez pas le\
droit de créer des cotisations"
return True, None
def can_edit(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.change_cotisation'):
return False, u"Vous n'avez pas le droit d'éditer les cotisations"
elif not user_request.has_perm('cotisations.change_all_cotisation') and\
(self.vente.facture.control or not self.vente.facture.valid):
return False, u"Vous n'avez pas le droit d'éditer une cotisation\
controlée ou invalidée par un trésorier"
else:
return True, None
def can_delete(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.delete_cotisation'):
return False, u"Vous n'avez pas le droit de supprimer une cotisations"
if self.vente.facture.control or not self.vente.facture.valid:
return False, u"Vous ne pouvez pas supprimer une cotisations\
contrôlée ou invalidée par un trésorier"
else:
return True, None
def can_view_all(user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_cotisation'):
return False, u"Vous n'avez pas le droit de voir les cotisations"
return True, None
def can_view(self, user_request, *args, **kwargs):
if not user_request.has_perm('cotisations.view_cotisation') and\
self.vente.facture.user != user_request:
return False, u"Vous ne pouvez pas afficher l'historique d'une\
cotisation d'un autre user que vous sans droit cableur"
else:
return True, None
def __str__(self):
return str(self.vente)
......
......@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}
<table class="table table-striped">
<thead>
<tr>
......@@ -41,11 +43,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ article.duration }}</td>
<td>{{ article.type_user }}</td>
<td class="text-right">
{% if is_trez %}
{% can_edit article %}
<a class="btn btn-primary btn-sm" role="button" title="Éditer" href="{% url 'cotisations:edit-article' article.id %}">
<i class="glyphicon glyphicon-edit"></i>
</a>
{% endif %}
{% acl_end %}
<a class="btn btn-info btn-sm" role="button" title="Historique" href="{% url 'cotisations:history' 'article' article.id %}">
<i class="glyphicon glyphicon-time"></i>
</a>
......
......@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}
<table class="table table-striped">
<thead>
<tr>
......@@ -33,11 +35,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<tr>
<td>{{ banque.name }}</td>
<td class="text-right">
{% if is_trez %}
{% can_edit banque %}
<a class="btn btn-primary btn-sm" role="button" title="Éditer" href="{% url 'cotisations:edit-banque' banque.id %}">
<i class="glyphicon glyphicon-edit"></i>
</a>
{% endif %}
{% acl_end %}
<a class="btn btn-info btn-sm" role="button" title="Historique" href="{% url 'cotisations:history' 'banque' banque.id %}">
<i class="glyphicon glyphicon-time"></i>
</a>
......
......@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}
{% if facture_list.paginator %}
{% include "pagination.html" with list=facture_list %}
{% endif %}
......@@ -47,7 +49,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ facture.paiement }}</td>
<td>{{ facture.date }}</td>
<td>{{ facture.id }}</td>
{% if is_cableur %}
<td>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="editionfacture" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
......@@ -55,17 +56,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="editionfacture">
{% if facture.valid and not facture.control or is_trez %}
{% can_edit facture %}
<li><a href="{% url 'cotisations:edit-facture' facture.id %}"><i class="glyphicon glyphicon-bitcoin"></i> Modifier</a></li>
{% acl_else %}
<li>Facture controlée</li>
{% acl_end %}
{% can_delete facture %}
<li><a href="{% url 'cotisations:del-facture' facture.id %}"><i class="glyphicon glyphicon-trash"></i> Supprimer</a></li>
{% acl_end %}
<li><a href="{% url 'cotisations:history' 'facture' facture.id %}"><i class="glyphicon glyphicon-time"></i> Historique</a></li>
{% else %}
<li>Facture controlée</li>
{% endif %}
</ul>
</div>
</td>
{% endif %}
<td>
{% if facture.valid %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:facture-pdf' facture.id %}">
......
......@@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}