diff --git a/apps/permission/admin.py b/apps/permission/admin.py index d5ef8b4f..42b9796b 100644 --- a/apps/permission/admin.py +++ b/apps/permission/admin.py @@ -4,7 +4,7 @@ from django.contrib import admin from note_kfet.admin import admin_site -from .models import Permission, PermissionMask, Role +from .models import Permission, PermissionVar, PermissionMask, Role @admin.register(PermissionMask, site=admin_site) @@ -15,6 +15,14 @@ class PermissionMaskAdmin(admin.ModelAdmin): list_display = ('description', 'rank', ) +@admin.register(PermissionVar, site=admin_site) +class PermissionVarAdmin(admin.ModelAdmin): + """ + Admin customisation for PermissionVar + """ + list_display = ('name', 'description',) + + @admin.register(Permission, site=admin_site) class PermissionAdmin(admin.ModelAdmin): """ diff --git a/apps/permission/migrations/0002_permissionvar.py b/apps/permission/migrations/0002_permissionvar.py new file mode 100644 index 00000000..a28a6d81 --- /dev/null +++ b/apps/permission/migrations/0002_permissionvar.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.28 on 2022-10-10 17:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('permission', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='PermissionVar', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.SlugField(unique=True, verbose_name='name')), + ('query', models.TextField(verbose_name='query')), + ('description', models.CharField(blank=True, max_length=255, verbose_name='description')), + ], + ), + ] diff --git a/apps/permission/models.py b/apps/permission/models.py index 7ca309ca..e2a83b6c 100644 --- a/apps/permission/models.py +++ b/apps/permission/models.py @@ -118,6 +118,25 @@ class PermissionMask(models.Model): verbose_name_plural = _("permission masks") +class PermissionVar(models.Model): + + name = models.SlugField( + unique=True, + blank=False, + verbose_name=_("name"), + ) + + query = models.TextField( + verbose_name=_("query"), + ) + + description = models.CharField( + max_length=255, + blank=True, + verbose_name=_("description"), + ) + + class Permission(models.Model): PERMISSION_TYPES = [ @@ -139,6 +158,7 @@ class Permission(models.Model): # query -> ["AND", query, …] AND multiple queries # | ["OR", query, …] OR multiple queries # | ["NOT", query] Opposite of query + # | ["VAR", query] A var name as defined in PermissionVar # query -> {key: value, …} A list of fields and values of a Q object # key -> string A field name # value -> int | string | bool | null Literal values @@ -150,6 +170,7 @@ class Permission(models.Model): # | ["MUL", oper, …] Multiply F objects or literals # | int | string | bool | null Literal values # | ["F", string] A field + # | ["VAR", string] A var name as defined in PermissionVar # # Examples: # Q(is_superuser=True) := {"is_superuser": true} @@ -215,6 +236,8 @@ class Permission(models.Model): return functools.reduce(operator.mul, [Permission.compute_f(oper, **kwargs) for oper in oper[1:]]) elif oper[0] == 'F': return F(oper[1]) + elif oper[0] == 'VAR': + return compute_f(json.loads(PermissionVar.objects.get(name=oper[1]).query), **kwargs) else: field = kwargs[oper[0]] for i in range(1, len(oper)): @@ -289,6 +312,8 @@ class Permission(models.Model): return functools.reduce(operator.or_, [Permission._about(query, **kwargs) for query in query[1:]]) elif query[0] == 'NOT': return ~Permission._about(query[1], **kwargs) + elif query[0] == 'VAR': + return Permission._about(json.loads(PermissionVar.objects.get(name=query[1]).query), **kwargs) else: return Q(pk=F("pk")) if Permission.compute_param(query, **kwargs) else ~Q(pk=F("pk")) elif isinstance(query, dict):