Clean permissions objects

- Define default permissions of kfet models.
- Unused default permissions are deleted.
- `kfet.manage_perms` is now splitted as `kfetauth.(view|add|change)_group` permissions.
This commit is contained in:
Aurélien Delobelle 2017-10-15 20:48:15 +02:00
parent df7594a105
commit 5502c6876a
10 changed files with 453 additions and 11 deletions

View file

@ -20,6 +20,9 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', auto_created=True, serialize=False, primary_key=True)), ('id', models.AutoField(verbose_name='ID', auto_created=True, serialize=False, primary_key=True)),
('token', models.CharField(unique=True, max_length=50)), ('token', models.CharField(unique=True, max_length=50)),
], ],
options={
'default_permissions': (),
},
), ),
migrations.CreateModel( migrations.CreateModel(
name='Group', name='Group',
@ -27,6 +30,7 @@ class Migration(migrations.Migration):
('group_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, auto_created=True, to='auth.Group')), ('group_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, auto_created=True, to='auth.Group')),
], ],
options={ options={
'default_permissions': ('view', 'add', 'change'),
'verbose_name': 'Groupe', 'verbose_name': 'Groupe',
'verbose_name_plural': 'Groupes', 'verbose_name_plural': 'Groupes',
}, },

View file

@ -23,6 +23,7 @@ class Migration(migrations.Migration):
dependencies = [ dependencies = [
('kfetauth', '0001_initial'), ('kfetauth', '0001_initial'),
('auth', '0006_require_contenttypes_0002'),
] ]
operations = [ operations = [

View file

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
from django.db import migrations
from django.db.models import Q
def convert_manage_perms(apps, schema_editor):
"""
Use the permissions of `kfet.auth.models.Group` model, instead of using the
`manage_perms` permission, which is deleted, of `kfet.models.Account`.
`Group` which have this last permission will get the permissions:
`kfetauth.view_group`, `kfetauth.add_group` and `kfetauth.change_group`.
"""
Group = apps.get_model('auth', 'Group')
Permission = apps.get_model('auth', 'Permission')
ContentType = apps.get_model('contenttypes', 'ContentType')
try:
old_p = Permission.objects.get(
content_type__app_label='kfet',
content_type__model='account',
codename='manage_perms',
)
except Permission.DoesNotExist:
return
groups = old_p.group_set.all()
ct_group, _ = ContentType.objects.get_or_create(
app_label='kfetauth',
model='group',
)
view_p, _ = Permission.objects.get_or_create(
content_type=ct_group, codename='view_group',
defaults={'name': 'Can view Groupe'})
add_p, _ = Permission.objects.get_or_create(
content_type=ct_group, codename='add_group',
defaults={'name': 'Can add Groupe'})
change_p, _ = Permission.objects.get_or_create(
content_type=ct_group, codename='change_group',
defaults={'name': 'Can change Group'})
GroupPermission = Group.permissions.through
GroupPermission.objects.bulk_create([
GroupPermission(permission=p, group=g)
for g in groups
for p in (view_p, add_p, change_p)
])
old_p.delete()
def delete_unused_permissions(apps, schema_editor):
Permission = apps.get_model('auth', 'Permission')
to_delete_q = Q(content_type__model='genericteamtoken') | Q(
content_type__model='group',
codename='delete_group',
)
to_delete_q &= Q(content_type__app_label='kfetauth')
Permission.objects.filter(to_delete_q).delete()
class Migration(migrations.Migration):
"""
Data migration about permissions.
"""
dependencies = [
('kfetauth', '0002_existing_groups'),
('auth', '0006_require_contenttypes_0002'),
('contenttypes', '0002_remove_content_type_name'),
]
operations = [
migrations.RunPython(convert_manage_perms),
migrations.RunPython(delete_unused_permissions),
]

View file

@ -20,6 +20,9 @@ class GenericTeamToken(models.Model):
objects = GenericTeamTokenManager() objects = GenericTeamTokenManager()
class Meta:
default_permissions = ()
class Group(DjangoGroup): class Group(DjangoGroup):
@ -35,6 +38,7 @@ class Group(DjangoGroup):
class Meta: class Meta:
verbose_name = _("Groupe") verbose_name = _("Groupe")
verbose_name_plural = _("Groupes") verbose_name_plural = _("Groupes")
default_permissions = ('view', 'add', 'change')
KFET_CORE_APP_LABELS = ['kfet', 'kfetauth'] KFET_CORE_APP_LABELS = ['kfet', 'kfetauth']

View file

@ -104,7 +104,7 @@ class GenericLoginView(View):
login_generic = GenericLoginView.as_view() login_generic = GenericLoginView.as_view()
@permission_required('kfet.manage_perms') @permission_required('kfetauth.view_group')
def account_group(request): def account_group(request):
user_pre = Prefetch( user_pre = Prefetch(
'user_set', 'user_set',

View file

@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('kfet', '0059_create_generic'),
]
operations = [
migrations.AlterModelOptions(
name='account',
options={
'permissions': (
('is_team', "Membre de l'équipe"),
('manage_addcosts', 'Gérer les majorations'),
(
'edit_balance_account',
"Modifier la balance d'un compte"
),
(
'change_account_password',
"Modifier le mot de passe d'une personne de l'équipe"
),
(
'special_add_account',
'Créer un compte avec une balance initiale'
),
('can_force_close', 'Fermer manuellement la K-Fêt')
),
'default_permissions': ('add', 'change'),
'verbose_name_plural': 'Comptes',
'verbose_name': 'Compte',
},
),
migrations.AlterModelOptions(
name='accountnegative',
options={
'default_permissions': ('view', 'change',),
'verbose_name_plural': 'Comptes en négatif',
'verbose_name': 'Compte en négatif',
},
),
migrations.AlterModelOptions(
name='article',
options={
'default_permissions': ('add', 'change'),
'verbose_name_plural': 'Articles',
'verbose_name': 'Article',
},
),
migrations.AlterModelOptions(
name='articlecategory',
options={
'default_permissions': ('change',),
'verbose_name_plural': "Catégories d'articles",
'verbose_name': "Catégorie d'articles",
},
),
migrations.AlterModelOptions(
name='articlerule',
options={
'default_permissions': (),
},
),
migrations.AlterModelOptions(
name='checkout',
options={
'default_permissions': ('add', 'change'),
'ordering': ['-valid_to'],
'verbose_name_plural': 'Caisses',
'verbose_name': 'Caisse',
},
),
migrations.AlterModelOptions(
name='checkoutstatement',
options={
'default_permissions': ('add', 'change'),
'verbose_name_plural': 'Relevés de caisses',
'verbose_name': 'Relevé de caisse',
},
),
migrations.AlterModelOptions(
name='checkouttransfer',
options={
'default_permissions': (),
},
),
migrations.AlterModelOptions(
name='inventory',
options={
'permissions': (
(
'order_to_inventory',
"Générer un inventaire à partir d'une commande"
),
),
'ordering': ['-at'],
'verbose_name_plural': 'Inventaires',
'default_permissions': ('add',),
'verbose_name': 'Inventaire',
},
),
migrations.AlterModelOptions(
name='inventoryarticle',
options={
'default_permissions': (),
},
),
migrations.AlterModelOptions(
name='operation',
options={
'permissions': (
('perform_deposit', 'Effectuer une charge'),
(
'perform_negative_operations',
'Enregistrer des commandes en négatif'
),
(
'override_frozen_protection',
"Forcer le gel d'un compte"
),
(
'cancel_old_operations',
'Annuler des commandes non récentes'
),
(
'perform_commented_operations',
'Enregistrer des commandes avec commentaires'
),
),
'default_permissions': (),
'verbose_name_plural': 'Opérations',
'verbose_name': 'Opération',
},
),
migrations.AlterModelOptions(
name='operationgroup',
options={
'default_permissions': (),
},
),
migrations.AlterModelOptions(
name='order',
options={
'default_permissions': ('add',),
'ordering': ['-at'],
'verbose_name_plural': 'Commandes',
'verbose_name': 'Commande',
},
),
migrations.AlterModelOptions(
name='orderarticle',
options={
'default_permissions': (),
},
),
migrations.AlterModelOptions(
name='supplier',
options={
'default_permissions': ('change',),
'verbose_name_plural': 'Fournisseurs',
'verbose_name': 'Fournisseur',
},
),
migrations.AlterModelOptions(
name='supplierarticle',
options={
'default_permissions': (),
},
),
migrations.AlterModelOptions(
name='transfer',
options={
'default_permissions': ('add',),
'verbose_name_plural': 'Transferts',
'verbose_name': 'Transfert',
},
),
migrations.AlterModelOptions(
name='transfergroup',
options={
'default_permissions': (),
},
),
]

View file

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
from django.db.models import Q
def update_permissions(apps, schema_editor):
Permission = apps.get_model('auth', 'Permission')
ContentType = apps.get_model('contenttypes', 'ContentType')
Account = apps.get_model('kfet', 'Account')
# If `kfet.is_team` permission exists, rename it.
Permission.objects.filter(
content_type__app_label='kfet',
content_type__model='account',
codename='is_team',
).update(name="Membre de l'équipe")
# If `kfet.view_negs` permission exists, move it as
# `kfet.view_accountnegative`.
try:
view_negs_p = Permission.objects.get(
content_type__app_label='kfet',
content_type__model='accountnegative',
codename='view_negs',
)
except Permission.DoesNotExist:
pass
else:
# Avoid failure due to unicity constraint if migrations were partially
# applied.
# Because `view_negs` still exists here, it should be safe to consider
# that nothing uses `view_accountnegative` so that it can be deleted.
Permission.objects.filter(
content_type__app_label='kfet',
content_type__model='accountnegative',
codename='view_accountnegative',
).delete()
view_negs_p.codename = 'view_accountnegative'
view_negs_p.name = 'Can view Compte en négatif'
view_negs_p.save()
# Delete unused permissions.
to_delete = {
'account': ['delete_account'],
'accountnegative': [
'add_accountnegative', 'delete_accountnegative', 'view_negs'],
'article': ['delete_article'],
'articlecategory': ['add_articlecategory', 'delete_articlecategory'],
'articlerule': '__all__',
'checkout': ['delete_checkout'],
'checkoutstatement': ['delete_checkoutstatement'],
'checkouttransfer': '__all__',
'inventory': ['change_inventory', 'delete_inventory'],
'inventoryarticle': '__all__',
'operation': ['add_operation', 'change_operation', 'delete_operation'],
'operationgroup': '__all__',
'order': ['change_order', 'delete_order'],
'orderarticle': '__all__',
'supplier': ['add_supplier', 'delete_supplier'],
'supplierarticle': '__all__',
'transfer': ['change_transfer', 'delete_transfer'],
'transfergroup': '__all__',
}
to_delete_q = Q()
for model_name, codenames in to_delete.items():
if codenames == '__all__':
to_delete_q |= Q(content_type__model=model_name)
else:
to_delete_q |= Q(
content_type__model=model_name,
codename__in=codenames,
)
to_delete_q &= Q(content_type__app_label='kfet')
Permission.objects.filter(to_delete_q).delete()
class Migration(migrations.Migration):
"""
Data migration which performs permissions cleaning.
"""
dependencies = [
('kfet', '0060_change_models_opts'),
('auth', '0006_require_contenttypes_0002'),
('contenttypes', '0002_remove_content_type_name'),
]
operations = [
migrations.RunPython(update_permissions),
]

View file

@ -8,6 +8,7 @@ from gestioncof.models import CofProfile
from django.utils.six.moves import reduce from django.utils.six.moves import reduce
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django.db import transaction from django.db import transaction
from django.db.models import F from django.db.models import F
from datetime import date from datetime import date
@ -83,9 +84,11 @@ class Account(models.Model):
blank = True, null = True, default = None) blank = True, null = True, default = None)
class Meta: class Meta:
verbose_name = _("Compte")
verbose_name_plural = _("Comptes")
default_permissions = ('add', 'change')
permissions = ( permissions = (
('is_team', 'Is part of the team'), ('is_team', "Membre de l'équipe"),
('manage_perms', 'Gérer les permissions K-Fêt'),
('manage_addcosts', 'Gérer les majorations'), ('manage_addcosts', 'Gérer les majorations'),
('edit_balance_account', "Modifier la balance d'un compte"), ('edit_balance_account', "Modifier la balance d'un compte"),
('change_account_password', ('change_account_password',
@ -329,9 +332,9 @@ class AccountNegative(models.Model):
comment = models.CharField("commentaire", max_length=255, blank=True) comment = models.CharField("commentaire", max_length=255, blank=True)
class Meta: class Meta:
permissions = ( verbose_name = _("Compte en négatif")
('view_negs', 'Voir la liste des négatifs'), verbose_name_plural = _("Comptes en négatif")
) default_permissions = ('view', 'change')
@property @property
def until_default(self): def until_default(self):
@ -355,7 +358,10 @@ class Checkout(models.Model):
return reverse('kfet.checkout.read', kwargs={'pk': self.pk}) return reverse('kfet.checkout.read', kwargs={'pk': self.pk})
class Meta: class Meta:
verbose_name = _("Caisse")
verbose_name_plural = _("Caisses")
ordering = ['-valid_to'] ordering = ['-valid_to']
default_permissions = ('add', 'change')
def __str__(self): def __str__(self):
return self.name return self.name
@ -370,6 +376,10 @@ class CheckoutTransfer(models.Model):
amount = models.DecimalField( amount = models.DecimalField(
max_digits = 6, decimal_places = 2) max_digits = 6, decimal_places = 2)
class Meta:
default_permissions = ()
@python_2_unicode_compatible @python_2_unicode_compatible
class CheckoutStatement(models.Model): class CheckoutStatement(models.Model):
by = models.ForeignKey( by = models.ForeignKey(
@ -408,6 +418,11 @@ class CheckoutStatement(models.Model):
"montant des chèques", "montant des chèques",
default=0, max_digits=6, decimal_places=2) default=0, max_digits=6, decimal_places=2)
class Meta:
verbose_name = _("Relevé de caisse")
verbose_name_plural = _("Relevés de caisses")
default_permissions = ('add', 'change')
def __str__(self): def __str__(self):
return '%s %s' % (self.checkout, self.at) return '%s %s' % (self.checkout, self.at)
@ -448,6 +463,11 @@ class ArticleCategory(models.Model):
"appliquée aux articles de " "appliquée aux articles de "
"cette catégorie.") "cette catégorie.")
class Meta:
verbose_name = _("Catégorie d'articles")
verbose_name_plural = _("Catégories d'articles")
default_permissions = ('change',)
def __str__(self): def __str__(self):
return self.name return self.name
@ -484,6 +504,11 @@ class Article(models.Model):
"capacité du contenant", "capacité du contenant",
blank = True, null = True, default = None) blank = True, null = True, default = None)
class Meta:
verbose_name = _("Article")
verbose_name_plural = _("Articles")
default_permissions = ('add', 'change')
def __str__(self): def __str__(self):
return '%s - %s' % (self.category.name, self.name) return '%s - %s' % (self.category.name, self.name)
@ -503,6 +528,10 @@ class ArticleRule(models.Model):
related_name = "rule_to") related_name = "rule_to")
ratio = models.PositiveSmallIntegerField() ratio = models.PositiveSmallIntegerField()
class Meta:
default_permissions = ()
class Inventory(models.Model): class Inventory(models.Model):
articles = models.ManyToManyField( articles = models.ManyToManyField(
Article, Article,
@ -519,7 +548,10 @@ class Inventory(models.Model):
blank = True, null = True, default = None) blank = True, null = True, default = None)
class Meta: class Meta:
verbose_name = _("Inventaire")
verbose_name_plural = _("Inventaires")
ordering = ['-at'] ordering = ['-at']
default_permissions = ('add',)
permissions = ( permissions = (
('order_to_inventory', "Générer un inventaire à partir d'une commande"), ('order_to_inventory', "Générer un inventaire à partir d'une commande"),
) )
@ -534,6 +566,9 @@ class InventoryArticle(models.Model):
stock_new = models.IntegerField() stock_new = models.IntegerField()
stock_error = models.IntegerField(default = 0) stock_error = models.IntegerField(default = 0)
class Meta:
default_permissions = ()
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# S'il s'agit d'un inventaire provenant d'une livraison, il n'y a pas # S'il s'agit d'un inventaire provenant d'une livraison, il n'y a pas
# d'erreur # d'erreur
@ -553,6 +588,11 @@ class Supplier(models.Model):
phone = models.CharField("téléphone", max_length = 10) phone = models.CharField("téléphone", max_length = 10)
comment = models.TextField("commentaire") comment = models.TextField("commentaire")
class Meta:
verbose_name = _("Fournisseur")
verbose_name_plural = _("Fournisseurs")
default_permissions = ('change',)
def __str__(self): def __str__(self):
return self.name return self.name
@ -572,6 +612,9 @@ class SupplierArticle(models.Model):
max_digits = 7, decimal_places = 4, max_digits = 7, decimal_places = 4,
blank = True, null = True, default = None) blank = True, null = True, default = None)
class Meta:
default_permissions = ()
class Order(models.Model): class Order(models.Model):
supplier = models.ForeignKey( supplier = models.ForeignKey(
Supplier, on_delete = models.PROTECT, Supplier, on_delete = models.PROTECT,
@ -585,7 +628,10 @@ class Order(models.Model):
max_digits = 6, decimal_places = 2, default = 0) max_digits = 6, decimal_places = 2, default = 0)
class Meta: class Meta:
verbose_name = _("Commande")
verbose_name_plural = _("Commandes")
ordering = ['-at'] ordering = ['-at']
default_permissions = ('add',)
class OrderArticle(models.Model): class OrderArticle(models.Model):
order = models.ForeignKey( order = models.ForeignKey(
@ -595,6 +641,9 @@ class OrderArticle(models.Model):
quantity_ordered = models.IntegerField() quantity_ordered = models.IntegerField()
quantity_received = models.IntegerField(default = 0) quantity_received = models.IntegerField(default = 0)
class Meta:
default_permissions = ()
class TransferGroup(models.Model): class TransferGroup(models.Model):
at = models.DateTimeField(default=timezone.now) at = models.DateTimeField(default=timezone.now)
# Optional # Optional
@ -606,6 +655,9 @@ class TransferGroup(models.Model):
related_name = "+", related_name = "+",
blank = True, null = True, default = None) blank = True, null = True, default = None)
class Meta:
default_permissions = ()
class Transfer(models.Model): class Transfer(models.Model):
group = models.ForeignKey( group = models.ForeignKey(
@ -626,6 +678,11 @@ class Transfer(models.Model):
canceled_at = models.DateTimeField( canceled_at = models.DateTimeField(
null=True, blank=True, default=None) null=True, blank=True, default=None)
class Meta:
verbose_name = _("Transfert")
verbose_name_plural = _("Transferts")
default_permissions = ('add',)
def __str__(self): def __str__(self):
return '{} -> {}: {}'.format(self.from_acc, self.to_acc, self.amount) return '{} -> {}: {}'.format(self.from_acc, self.to_acc, self.amount)
@ -651,6 +708,9 @@ class OperationGroup(models.Model):
related_name = "+", related_name = "+",
blank = True, null = True, default = None) blank = True, null = True, default = None)
class Meta:
default_permissions = ()
def __str__(self): def __str__(self):
return ', '.join(map(str, self.opes.all())) return ', '.join(map(str, self.opes.all()))
@ -701,6 +761,9 @@ class Operation(models.Model):
blank=True, null=True, default=None) blank=True, null=True, default=None)
class Meta: class Meta:
verbose_name = _("Opération")
verbose_name_plural = _("Opérations")
default_permissions = ()
permissions = ( permissions = (
('perform_deposit', 'Effectuer une charge'), ('perform_deposit', 'Effectuer une charge'),
('perform_negative_operations', ('perform_negative_operations',

View file

@ -22,11 +22,11 @@
</a> </a>
</div> </div>
{% if perms.kfet.manage_perms %} {% if perms.kfetauth.view_group %}
<a class="btn btn-primary" href="{% url 'kfet.account.group' %}">Permissions</a> <a class="btn btn-primary" href="{% url 'kfet.account.group' %}">Permissions</a>
{% endif %} {% endif %}
{% if perms.kfet.view_negs %} {% if perms.kfet.view_accountnegative %}
<a class="btn btn-primary" href="{% url 'kfet.account.negative' %}">Négatifs</a> <a class="btn btn-primary" href="{% url 'kfet.account.negative' %}">Négatifs</a>
{% endif %} {% endif %}
</div> </div>

View file

@ -54,16 +54,17 @@ urlpatterns = [
url(r'^accounts/groups$', views.account_group, url(r'^accounts/groups$', views.account_group,
name='kfet.account.group'), name='kfet.account.group'),
url(r'^accounts/groups/new$', url(r'^accounts/groups/new$',
permission_required('kfet.manage_perms') permission_required('kfetauth.add_group')
(views.AccountGroupCreate.as_view()), (views.AccountGroupCreate.as_view()),
name='kfet.account.group.create'), name='kfet.account.group.create'),
url(r'^accounts/groups/(?P<pk>\d+)/edit$', url(r'^accounts/groups/(?P<pk>\d+)/edit$',
permission_required('kfet.manage_perms') permission_required('kfetauth.change_group')
(views.AccountGroupUpdate.as_view()), (views.AccountGroupUpdate.as_view()),
name='kfet.account.group.update'), name='kfet.account.group.update'),
url(r'^accounts/negatives$', url(r'^accounts/negatives$',
permission_required('kfet.view_negs') permission_required('kfet.view_accountnegative')
(views.AccountNegativeList.as_view()), (views.AccountNegativeList.as_view()),
name='kfet.account.negative'), name='kfet.account.negative'),