From a96e98ca30d0676cc610c9c9a5300ddc73ee5c87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org>
Date: Mon, 1 May 2023 23:37:44 +0200
Subject: [PATCH] fix permissions mixin

---
 contracts/admin.py                            | 44 ++++++-------------
 .../0059_alter_contract_is_valid.py           | 18 ++++++++
 contracts/models.py                           |  1 +
 3 files changed, 33 insertions(+), 30 deletions(-)
 create mode 100644 contracts/migrations/0059_alter_contract_is_valid.py

diff --git a/contracts/admin.py b/contracts/admin.py
index 593e032..d80d314 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -42,16 +42,14 @@ class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
 def permissions_mixin_factory(
     change_permission: str,
     delete_permission: str,
-    obj_conditional: typing.Callable,
-    change_attr_func: typing.Callable = lambda obj: obj,
-    delete_attr_func: typing.Callable = lambda obj: obj,
+    obj_conditional: typing.Callable = lambda request, obj: True
 ) -> object:
     class Mixin:
         def has_change_permission(self, request, obj=None) -> bool:
             if (
                 obj is not None
                 and obj_conditional(request, obj)
-                and not request.user.has_perm(change_permission, change_attr_func(obj))
+                and not request.user.has_perm(change_permission)
             ):
                 return False
 
@@ -61,7 +59,7 @@ def permissions_mixin_factory(
             if (
                 obj is not None
                 and obj_conditional(request, obj)
-                and not request.user.has_perm(delete_permission, delete_attr_func(obj))
+                and not request.user.has_perm(change_permission)
             ):
                 return False
 
@@ -70,14 +68,14 @@ def permissions_mixin_factory(
     return Mixin
 
 
-get_obj_contract = lambda obj: obj.contract
+get_obj_contract = lambda request, obj: obj.contract
 
 
 class OwnPermissionsMixin(
     permissions_mixin_factory(
         "contracts.edit_others",
         "contracts.delete_others",
-        lambda request, obj: obj.created_by != request.user,
+        obj_conditional=lambda request, obj: obj.created_by != request.user,
     )
 ):
     def save_model(self, request, obj, form, change):
@@ -90,18 +88,14 @@ class OwnPermissionsMixin(
 ParentContractApprovedPermissionsMixin = permissions_mixin_factory(
     "contracts.edit_when_approved",
     "contracts.delete_when_approved",
-    lambda request, obj: get_obj_contract(obj).is_approved,
-    get_obj_contract,
-    get_obj_contract,
+    obj_conditional=lambda request, obj: get_obj_contract(obj).is_approved,
 )
 
 
 ParentContractOwnPermissionsMixin = permissions_mixin_factory(
     "contracts.edit_others",
     "contracts.delete_others",
-    lambda request, obj: get_obj_contract(obj).created_by != request.user,
-    get_obj_contract,
-    get_obj_contract,
+    obj_conditional=lambda request, obj: get_obj_contract(obj).created_by != request.user,
 )
 
 
@@ -162,7 +156,7 @@ class ContractAdmin(
     permissions_mixin_factory(
         "contracts.edit_when_approved",
         "contracts.delete_when_approved",
-        lambda request, obj: obj.is_approved,
+        obj_conditional=lambda request, obj: obj.is_approved,
     ),
     MarkdownxGuardedModelAdmin,
     NestedModelAdmin,
@@ -494,8 +488,8 @@ class SigneeAdmin(OwnPermissionsMixin, MarkdownxGuardedModelAdmin):
     load_ares_data_button.short_description = "ARES"
 
 
-get_obj_signee_contract = lambda obj: obj.signee.contract
-get_obj_contractee_contract = lambda obj: obj.contractee.contract
+get_obj_signee_contract = lambda request, obj: obj.signee.contract
+get_obj_contractee_contract = lambda request, obj: obj.contractee.contract
 
 
 class SigneeSignatureRepresentativeAdmin(
@@ -503,17 +497,12 @@ class SigneeSignatureRepresentativeAdmin(
     permissions_mixin_factory(
         "contracts.edit_when_approved",
         "contracts.delete_when_approved",
-        lambda request, obj: get_obj_signee_contract(obj).is_approved,
-        get_obj_signee_contract,
-        get_obj_signee_contract,
+        obj_conditional=lambda request, obj: get_obj_signee_contract(obj).is_approved,
     ),
     permissions_mixin_factory(
         "contracts.edit_others",
         "contracts.delete_others",
-        lambda request, obj: get_obj_contractee_contract(obj).created_by
-        != request.user,
-        get_obj_signee_contract,
-        get_obj_signee_contract,
+        obj_conditional=lambda request, obj: get_obj_contractee_contract(obj).created_by != request.user,
     ),
 ):
     pass
@@ -524,17 +513,12 @@ class ContracteeSignatureRepresentativeAdmin(
     permissions_mixin_factory(
         "contracts.edit_when_approved",
         "contracts.delete_when_approved",
-        lambda request, obj: get_obj_contractee_contract(obj).is_approved,
-        get_obj_contractee_contract,
-        get_obj_contractee_contract,
+        obj_conditional=lambda request, obj: get_obj_contractee_contract(obj).is_approved,
     ),
     permissions_mixin_factory(
         "contracts.edit_others",
         "contracts.delete_others",
-        lambda request, obj: get_obj_contractee_contract(obj).created_by
-        != request.user,
-        get_obj_contractee_contract,
-        get_obj_contractee_contract,
+        obj_conditional=lambda request, obj: get_obj_contractee_contract(obj).created_by != request.user,
     ),
 ):
     pass
diff --git a/contracts/migrations/0059_alter_contract_is_valid.py b/contracts/migrations/0059_alter_contract_is_valid.py
new file mode 100644
index 0000000..df29dad
--- /dev/null
+++ b/contracts/migrations/0059_alter_contract_is_valid.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.1.4 on 2023-05-01 20:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0058_alter_contract_options_alter_contractee_options_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='contract',
+            name='is_valid',
+            field=models.BooleanField(default=False, help_text='Právní vztah vyplývající ze smlouvy je aktuálně účinný a platný', verbose_name='Je právně platná'),
+        ),
+    ]
diff --git a/contracts/models.py b/contracts/models.py
index 114c3da..5e9719e 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -564,6 +564,7 @@ class Contract(NameStrMixin, models.Model):
     is_valid = models.BooleanField(
         default=False,
         verbose_name="Je právně platná",
+        help_text="Právní vztah vyplývající ze smlouvy je aktuálně účinný a platný",
     )
 
     is_public = models.BooleanField(
-- 
GitLab