Disambiguation in kfet's permission handling

In some places we used to refer to permissions based on their codename
only (the part after the dot "." in the following examples) which can be
ambiguous. Typically, we might define permissions like "bds.is_team" or
"cof.is_team" in the near future ;)
This commit is contained in:
Martin Pépin 2019-12-21 16:26:59 +01:00
parent 67e28c704f
commit 64c792b11f
No known key found for this signature in database
GPG key ID: E7520278B1774448
5 changed files with 37 additions and 25 deletions

View file

@ -6,7 +6,7 @@ import os
import random import random
from datetime import timedelta from datetime import timedelta
from django.contrib.auth.models import ContentType, Group, Permission, User from django.contrib.auth.models import Group, Permission, User
from django.core.management import call_command from django.core.management import call_command
from django.utils import timezone from django.utils import timezone
@ -41,11 +41,9 @@ class Command(MyBaseCommand):
group_chef.save() group_chef.save()
group_boy.save() group_boy.save()
permissions_chef = Permission.objects.filter( permissions_chef = Permission.objects.filter(content_type__app_label="kfet",)
content_type__in=ContentType.objects.filter(app_label="kfet")
)
permissions_boy = Permission.objects.filter( permissions_boy = Permission.objects.filter(
codename__in=["is_team", "perform_deposit"] content_type__app_label="kfet", codename__in=["is_team", "perform_deposit"]
) )
group_chef.permissions.add(*permissions_chef) group_chef.permissions.add(*permissions_chef)

View file

@ -84,7 +84,8 @@ class OpenKfetTest(ChannelTestCase):
def test_export_team(self): def test_export_team(self):
"""Export all values for a team member.""" """Export all values for a team member."""
user = User.objects.create_user("team", "", "team") user = User.objects.create_user("team", "", "team")
user.user_permissions.add(Permission.objects.get(codename="is_team")) is_team = Permission.objects.get_by_natural_key("is_team", "kfet", "account")
user.user_permissions.add(is_team)
export = self.kfet_open.export(user) export = self.kfet_open.export(user)
self.assertSetEqual(set(["status", "admin_status", "force_close"]), set(export)) self.assertSetEqual(set(["status", "admin_status", "force_close"]), set(export))
@ -114,8 +115,12 @@ class OpenKfetViewsTest(ChannelTestCase):
# get some permissions # get some permissions
perms = { perms = {
"kfet.is_team": Permission.objects.get(codename="is_team"), "kfet.is_team": Permission.objects.get_by_natural_key(
"kfet.can_force_close": Permission.objects.get(codename="can_force_close"), "is_team", "kfet", "account"
),
"kfet.can_force_close": Permission.objects.get_by_natural_key(
"can_force_close", "kfet", "account"
),
} }
# authenticated user and its client # authenticated user and its client
@ -199,7 +204,8 @@ class OpenKfetConsumerTest(ChannelTestCase):
"""Team user is added to kfet.open.team group.""" """Team user is added to kfet.open.team group."""
# setup team user and its client # setup team user and its client
t = User.objects.create_user("team", "", "team") t = User.objects.create_user("team", "", "team")
t.user_permissions.add(Permission.objects.get(codename="is_team")) is_team = Permission.objects.get_by_natural_key("is_team", "kfet", "account")
t.user_permissions.add(is_team)
c = WSClient() c = WSClient()
c.force_login(t) c.force_login(t)

View file

@ -18,7 +18,7 @@ class TestStats(TestCase):
user.set_password("foobar") user.set_password("foobar")
user.save() user.save()
Account.objects.create(trigramme="FOO", cofprofile=user.profile) Account.objects.create(trigramme="FOO", cofprofile=user.profile)
perm = Permission.objects.get(codename="is_team") perm = Permission.objects.get_by_natural_key("is_team", "kfet", "account")
user.user_permissions.add(perm) user.user_permissions.add(perm)
user2 = User.objects.create(username="Barfoo") user2 = User.objects.create(username="Barfoo")

View file

@ -1855,7 +1855,7 @@ class KPsulPerformOperationsViewTests(ViewTestCaseMixin, TestCase):
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual( self.assertEqual(
json_data["errors"]["missing_perms"], json_data["errors"]["missing_perms"],
["Enregistrer des commandes avec commentaires"], ["[kfet] Enregistrer des commandes avec commentaires"],
) )
def test_group_on_acc_frozen(self): def test_group_on_acc_frozen(self):
@ -1898,7 +1898,7 @@ class KPsulPerformOperationsViewTests(ViewTestCaseMixin, TestCase):
self.assertEqual(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual( self.assertEqual(
json_data["errors"]["missing_perms"], ["Forcer le gel d'un compte"] json_data["errors"]["missing_perms"], ["[kfet] Forcer le gel d'un compte"]
) )
def test_invalid_group_checkout(self): def test_invalid_group_checkout(self):
@ -2373,7 +2373,9 @@ class KPsulPerformOperationsViewTests(ViewTestCaseMixin, TestCase):
self.assertEqual(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual(json_data["errors"]["missing_perms"], ["Effectuer une charge"]) self.assertEqual(
json_data["errors"]["missing_perms"], ["[kfet] Effectuer une charge"]
)
def test_withdraw(self): def test_withdraw(self):
data = dict( data = dict(
@ -2648,7 +2650,8 @@ class KPsulPerformOperationsViewTests(ViewTestCaseMixin, TestCase):
self.assertEqual(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual( self.assertEqual(
json_data["errors"]["missing_perms"], ["Modifier la balance d'un compte"] json_data["errors"]["missing_perms"],
["[kfet] Modifier la balance d'un compte"],
) )
def test_invalid_edit_expects_comment(self): def test_invalid_edit_expects_comment(self):
@ -2956,7 +2959,7 @@ class KPsulPerformOperationsViewTests(ViewTestCaseMixin, TestCase):
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual( self.assertEqual(
json_data["errors"], json_data["errors"],
{"missing_perms": ["Enregistrer des commandes en négatif"]}, {"missing_perms": ["[kfet] Enregistrer des commandes en négatif"]},
) )
def test_invalid_negative_exceeds_allowed_duration_from_config(self): def test_invalid_negative_exceeds_allowed_duration_from_config(self):
@ -3780,7 +3783,7 @@ class KPsulCancelOperationsViewTests(ViewTestCaseMixin, TestCase):
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual( self.assertEqual(
json_data["errors"], json_data["errors"],
{"missing_perms": ["Annuler des commandes non récentes"]}, {"missing_perms": ["[kfet] Annuler des commandes non récentes"]},
) )
def test_already_canceled(self): def test_already_canceled(self):
@ -3926,7 +3929,7 @@ class KPsulCancelOperationsViewTests(ViewTestCaseMixin, TestCase):
json_data = json.loads(resp.content.decode("utf-8")) json_data = json.loads(resp.content.decode("utf-8"))
self.assertEqual( self.assertEqual(
json_data["errors"], json_data["errors"],
{"missing_perms": ["Enregistrer des commandes en négatif"]}, {"missing_perms": ["[kfet] Enregistrer des commandes en négatif"]},
) )
def test_partial_0(self): def test_partial_0(self):

View file

@ -3,6 +3,7 @@ import heapq
import statistics import statistics
from collections import defaultdict from collections import defaultdict
from decimal import Decimal from decimal import Decimal
from typing import List
from urllib.parse import urlencode from urllib.parse import urlencode
from django.contrib import messages from django.contrib import messages
@ -993,15 +994,19 @@ def kpsul_update_addcost(request):
return JsonResponse(data) return JsonResponse(data)
def get_missing_perms(required_perms, user): def get_missing_perms(required_perms: List[str], user: User) -> List[str]:
missing_perms_codenames = [ def get_perm_description(app_label: str, codename: str) -> str:
(perm.split("."))[1] for perm in required_perms if not user.has_perm(perm) name = Permission.objects.values_list("name", flat=True).get(
codename=codename, content_type__app_label=app_label
)
return "[{}] {}".format(app_label, name)
missing_perms = [
get_perm_description(*perm.split("."))
for perm in required_perms
if not user.has_perm(perm)
] ]
missing_perms = list(
Permission.objects.filter(codename__in=missing_perms_codenames).values_list(
"name", flat=True
)
)
return missing_perms return missing_perms