From 7794210cc8b03423d1454af53d9ee789c14543d9 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Thu, 19 Mar 2020 18:53:06 +0100
Subject: [PATCH] Being superuser is not enough (must have the correct mask),
 add some initial fixtures

---
 apps/member/api/serializers.py        |   1 +
 apps/member/models.py                 |   3 +
 apps/note/api/serializers.py          |   4 +-
 apps/permission/admin.py              |   2 +-
 apps/permission/fixtures/initial.json | 286 ++++++++++++++++++++++++++
 apps/permission/models.py             |   8 +-
 apps/permission/signals.py            |  14 +-
 apps/permission/templatetags/perms.py |   5 -
 note_kfet/settings/base.py            |   1 -
 9 files changed, 305 insertions(+), 19 deletions(-)
 create mode 100644 apps/permission/fixtures/initial.json

diff --git a/apps/member/api/serializers.py b/apps/member/api/serializers.py
index 962841ae..a956a46b 100644
--- a/apps/member/api/serializers.py
+++ b/apps/member/api/serializers.py
@@ -15,6 +15,7 @@ class ProfileSerializer(serializers.ModelSerializer):
     class Meta:
         model = Profile
         fields = '__all__'
+        read_only_fields = ('user', )
 
 
 class ClubSerializer(serializers.ModelSerializer):
diff --git a/apps/member/models.py b/apps/member/models.py
index 24e58830..1a9bcee2 100644
--- a/apps/member/models.py
+++ b/apps/member/models.py
@@ -178,6 +178,9 @@ class RolePermissions(models.Model):
         'permission.Permission'
     )
 
+    def __str__(self):
+        return str(self.role)
+
 
 # @receiver(post_save, sender=settings.AUTH_USER_MODEL)
 # def save_user_profile(instance, created, **_kwargs):
diff --git a/apps/note/api/serializers.py b/apps/note/api/serializers.py
index 36696024..91dbb62a 100644
--- a/apps/note/api/serializers.py
+++ b/apps/note/api/serializers.py
@@ -4,6 +4,7 @@
 from rest_framework import serializers
 from rest_polymorphic.serializers import PolymorphicSerializer
 
+from member.backends import PermissionBackend
 from note_kfet.middlewares import get_current_authenticated_user
 from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
 from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
@@ -76,9 +77,10 @@ class AliasSerializer(serializers.ModelSerializer):
     class Meta:
         model = Alias
         fields = '__all__'
+        read_only_fields = ('note', )
 
     def get_note(self, alias):
-        if get_current_authenticated_user().has_perm("note.view_note", alias.note):
+        if PermissionBackend().has_perm(get_current_authenticated_user(), "note.view_note", alias.note):
             return NotePolymorphicSerializer().to_representation(alias.note)
         else:
             return alias.note.id
diff --git a/apps/permission/admin.py b/apps/permission/admin.py
index 2e6899fd..fe2e0e74 100644
--- a/apps/permission/admin.py
+++ b/apps/permission/admin.py
@@ -19,4 +19,4 @@ class PermissionAdmin(admin.ModelAdmin):
     """
     Admin customisation for Permission
     """
-    list_display = ('type', 'model', 'field', 'description')
+    list_display = ('type', 'model', 'field', 'mask', 'description')
diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json
new file mode 100644
index 00000000..e1262673
--- /dev/null
+++ b/apps/permission/fixtures/initial.json
@@ -0,0 +1,286 @@
+[
+  {
+    "model": "permission.permissionmask",
+    "pk": 1,
+    "fields": {
+      "rank": 0,
+      "description": "Droits basiques"
+    }
+  },
+  {
+    "model": "permission.permissionmask",
+    "pk": 2,
+    "fields": {
+      "rank": 1,
+      "description": "Droits note seulement"
+    }
+  },
+  {
+    "model": "permission.permissionmask",
+    "pk": 3,
+    "fields": {
+      "rank": 42,
+      "description": "Tous mes droits"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 1,
+    "fields": {
+      "model": 21,
+      "query": "{\"pk\": [\"user\", \"pk\"]}",
+      "type": "view",
+      "mask": 1,
+      "field": "",
+      "description": "View our User object"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 2,
+    "fields": {
+      "model": 31,
+      "query": "{\"user\": [\"user\"]}",
+      "type": "view",
+      "mask": 1,
+      "field": "",
+      "description": "View our profile"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 3,
+    "fields": {
+      "model": 35,
+      "query": "{\"pk\": [\"user\", \"note\", \"pk\"]}",
+      "type": "view",
+      "mask": 1,
+      "field": "",
+      "description": "View our own note"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 4,
+    "fields": {
+      "model": 25,
+      "query": "{\"user\": [\"user\"]}",
+      "type": "view",
+      "mask": 1,
+      "field": "",
+      "description": "View our API token"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 5,
+    "fields": {
+      "model": 37,
+      "query": "[\"OR\", {\"source\": [\"user\", \"note\"]}, {\"destination\": [\"user\", \"note\"]}]",
+      "type": "view",
+      "mask": 1,
+      "field": "",
+      "description": "View our own transactions"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 6,
+    "fields": {
+      "model": 34,
+      "query": "[\"OR\", {\"note__in\": [\"NoteUser\", \"objects\", [\"filter\", {\"user__membership__club__name\": \"Kfet\"}], [\"all\"]]}, {\"note__in\": [\"NoteClub\", \"objects\", [\"all\"]]}]",
+      "type": "view",
+      "mask": 1,
+      "field": "",
+      "description": "View aliases of clubs and members of Kfet club"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 7,
+    "fields": {
+      "model": 21,
+      "query": "{\"pk\": [\"user\", \"pk\"]}",
+      "type": "change",
+      "mask": 1,
+      "field": "last_login",
+      "description": "Change myself's last login"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 8,
+    "fields": {
+      "model": 21,
+      "query": "{\"pk\": [\"user\", \"pk\"]}",
+      "type": "change",
+      "mask": 1,
+      "field": "username",
+      "description": "Change myself's username"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 9,
+    "fields": {
+      "model": 21,
+      "query": "{\"pk\": [\"user\", \"pk\"]}",
+      "type": "change",
+      "mask": 1,
+      "field": "first_name",
+      "description": "Change myself's first name"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 10,
+    "fields": {
+      "model": 21,
+      "query": "{\"pk\": [\"user\", \"pk\"]}",
+      "type": "change",
+      "mask": 1,
+      "field": "last_name",
+      "description": "Change myself's last name"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 11,
+    "fields": {
+      "model": 21,
+      "query": "{\"pk\": [\"user\", \"pk\"]}",
+      "type": "change",
+      "mask": 1,
+      "field": "email",
+      "description": "Change myself's email"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 12,
+    "fields": {
+      "model": 25,
+      "query": "{\"user\": [\"user\"]}",
+      "type": "delete",
+      "mask": 1,
+      "field": "",
+      "description": "Delete API Token"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 13,
+    "fields": {
+      "model": 25,
+      "query": "{\"user\": [\"user\"]}",
+      "type": "add",
+      "mask": 1,
+      "field": "",
+      "description": "Create API Token"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 14,
+    "fields": {
+      "model": 34,
+      "query": "{\"note\": [\"user\", \"note\"]}",
+      "type": "delete",
+      "mask": 1,
+      "field": "",
+      "description": "Remove alias"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 15,
+    "fields": {
+      "model": 34,
+      "query": "{\"note\": [\"user\", \"note\"]}",
+      "type": "add",
+      "mask": 1,
+      "field": "",
+      "description": "Add alias"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 16,
+    "fields": {
+      "model": 35,
+      "query": "{\"pk\": [\"user\", \"note\", \"pk\"]}",
+      "type": "change",
+      "mask": 1,
+      "field": "display_image",
+      "description": "Change myself's display image"
+    }
+  },
+  {
+    "model": "permission.permission",
+    "pk": 17,
+    "fields": {
+      "model": 37,
+      "query": "[\"AND\", {\"source\": [\"user\", \"note\"]}, {\"amount__lte\": [\"user\", \"note\", \"balance\"]}]",
+      "type": "add",
+      "mask": 1,
+      "field": "",
+      "description": "Transfer from myself's note"
+    }
+  },
+  {
+    "model": "member.role",
+    "pk": 1,
+    "fields": {
+      "name": "Adh\u00e9rent BDE"
+    }
+  },
+  {
+    "model": "member.role",
+    "pk": 2,
+    "fields": {
+      "name": "Adh\u00e9rent Kfet"
+    }
+  },
+  {
+    "model": "member.rolepermissions",
+    "pk": 1,
+    "fields": {
+      "role": 1,
+      "permissions": [
+        1,
+        2,
+        7,
+        8,
+        9,
+        10,
+        11
+      ]
+    }
+  },
+  {
+    "model": "member.rolepermissions",
+    "pk": 2,
+    "fields": {
+      "role": 2,
+      "permissions": [
+        1,
+        2,
+        3,
+        4,
+        5,
+        6,
+        7,
+        8,
+        9,
+        10,
+        11,
+        12,
+        13,
+        14,
+        15,
+        16,
+        17
+      ]
+    }
+  }
+]
diff --git a/apps/permission/models.py b/apps/permission/models.py
index 62a1d0c3..43f62ac2 100644
--- a/apps/permission/models.py
+++ b/apps/permission/models.py
@@ -14,18 +14,20 @@ from django.utils.translation import gettext_lazy as _
 
 class InstancedPermission:
 
-    def __init__(self, model, query, type, field):
+    def __init__(self, model, query, type, field, mask):
         self.model = model
         self.query = query
         self.type = type
         self.field = field
+        self.mask = mask
 
     def applies(self, obj, permission_type, field_name=None):
         """
         Returns True if the permission applies to
         the field `field_name` object `obj`
         """
-        if ContentType.objects.get_for_model(obj) != self.model:
+
+        if not isinstance(obj, self.model.model_class()):
             # The permission does not apply to the model
             return False
 
@@ -247,7 +249,7 @@ class Permission(models.Model):
         """
         query = json.loads(self.query)
         query = self._about(query, **kwargs)
-        return InstancedPermission(self.model, query, self.type, self.field)
+        return InstancedPermission(self.model, query, self.type, self.field, self.mask)
 
     def __str__(self):
         if self.field:
diff --git a/apps/permission/signals.py b/apps/permission/signals.py
index 6d4f5f19..f18f35e0 100644
--- a/apps/permission/signals.py
+++ b/apps/permission/signals.py
@@ -2,6 +2,8 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
 from django.core.exceptions import PermissionDenied
+
+from member.backends import PermissionBackend
 from note_kfet.middlewares import get_current_authenticated_user
 
 
@@ -14,10 +16,6 @@ EXCLUDED = [
     'contenttypes.contenttype',
     'logs.changelog',
     'migrations.migration',
-    'note.note',
-    'note.noteuser',
-    'note.noteclub',
-    'note.notespecial',
     'sessions.session',
 ]
 
@@ -41,7 +39,7 @@ def pre_save_object(sender, instance, **kwargs):
     model_name = model_name_full[1]
 
     if qs.exists():
-        if user.has_perm(app_label + ".change_" + model_name, instance):
+        if PermissionBackend().has_perm(user, app_label + ".change_" + model_name, instance):
             return
 
         previous = qs.get()
@@ -51,10 +49,10 @@ def pre_save_object(sender, instance, **kwargs):
             new_value = getattr(instance, field.name)
             if old_value == new_value:
                 continue
-            if not user.has_perm(app_label + ".change_" + model_name + "_" + field_name, instance):
+            if not PermissionBackend().has_perm(user, app_label + ".change_" + model_name + "_" + field_name, instance):
                 raise PermissionDenied
     else:
-        if not user.has_perm(app_label + ".add_" + model_name, instance):
+        if not PermissionBackend().has_perm(user, app_label + ".add_" + model_name, instance):
             raise PermissionDenied
 
 
@@ -75,5 +73,5 @@ def pre_delete_object(sender, instance, **kwargs):
     app_label = model_name_full[0]
     model_name = model_name_full[1]
 
-    if not user.has_perm(app_label + ".delete_" + model_name, instance):
+    if not PermissionBackend().has_perm(user, app_label + ".delete_" + model_name, instance):
         raise PermissionDenied
diff --git a/apps/permission/templatetags/perms.py b/apps/permission/templatetags/perms.py
index f65b606e..859f1ef2 100644
--- a/apps/permission/templatetags/perms.py
+++ b/apps/permission/templatetags/perms.py
@@ -10,10 +10,6 @@ from django import template
 from member.backends import PermissionBackend
 
 
-def has_perm(value):
-    return get_current_authenticated_user().has_perm(value)
-
-
 @stringfilter
 def not_empty_model_list(model_name):
     user = get_current_authenticated_user()
@@ -41,6 +37,5 @@ def not_empty_model_change_list(model_name):
 
 
 register = template.Library()
-register.filter('has_perm', has_perm)
 register.filter('not_empty_model_list', not_empty_model_list)
 register.filter('not_empty_model_change_list', not_empty_model_change_list)
diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py
index 800c798e..1ebaf2b9 100644
--- a/note_kfet/settings/base.py
+++ b/note_kfet/settings/base.py
@@ -130,7 +130,6 @@ PASSWORD_HASHERS = [
 # Django Guardian object permissions
 
 AUTHENTICATION_BACKENDS = (
-    #  'django.contrib.auth.backends.ModelBackend',  # this is default
     'member.backends.PermissionBackend',
     'cas.backends.CASBackend',
 )
-- 
GitLab