Allow superusers to bypass pattern based permissions
authorMagnus Hagander <magnus@hagander.net>
Mon, 2 Jun 2025 13:25:37 +0000 (15:25 +0200)
committerMagnus Hagander <magnus@hagander.net>
Mon, 2 Jun 2025 13:25:37 +0000 (15:25 +0200)
To avoid having to explicitlyg rant wildcard permissions across all
existing domains...

pgmailmgr/mailmgr/forms.py
pgmailmgr/mailmgr/views.py

index 2b6521a589020faa97ae50593fe963e57edd10bb..a3c59b7c593ba6b87bebdd48c047ac1b344d9e2a 100644 (file)
@@ -112,17 +112,18 @@ class VirtualUserForm(forms.ModelForm):
         if 'local_domain' not in self.cleaned_data:
             return {}
 
-        # Validate that the pattern is allowed
-        curs = connection.cursor()
-        curs.execute("SELECT 1 FROM mailmgr_userpermissions WHERE user_id=%(uid)s AND domain_id=%(domain)s AND %(lp)s ~* ('^'||pattern||'$')", {
-            'uid': self.user.pk,
-            'domain': self.cleaned_data['local_domain'].pk,
-            'lp': self.cleaned_data['local_part'],
-        })
-        perms = curs.fetchall()
-
-        if len(perms) < 1:
-            raise ValidationError("Permission denied to create that user for that domain!")
+        if not self.user.is_superuser:
+            # Validate that the pattern is allowed
+            curs = connection.cursor()
+            curs.execute("SELECT 1 FROM mailmgr_userpermissions WHERE user_id=%(uid)s AND domain_id=%(domain)s AND %(lp)s ~* ('^'||pattern||'$')", {
+                'uid': self.user.pk,
+                'domain': self.cleaned_data['local_domain'].pk,
+                'lp': self.cleaned_data['local_part'],
+            })
+            perms = curs.fetchall()
+
+            if len(perms) < 1:
+                raise ValidationError("Permission denied to create that user for that domain!")
 
         # If it's a new user, also check against if it already exists
         if not self.instance.pk:
@@ -167,17 +168,18 @@ class ForwarderForm(forms.ModelForm):
         if 'local_domain' not in self.cleaned_data:
             return {}
 
-        # Validate that the pattern is allowed
-        curs = connection.cursor()
-        curs.execute("SELECT 1 FROM mailmgr_userpermissions WHERE user_id=%(uid)s AND domain_id=%(domain)s AND %(lp)s ~* ('^'||pattern||'$')", {
-            'uid': self.user.pk,
-            'domain': self.cleaned_data['local_domain'].pk,
-            'lp': self.cleaned_data['local_part'],
-        })
-        perms = curs.fetchall()
-
-        if len(perms) < 1:
-            raise ValidationError("Permission denied to create that forwarder for that domain!")
+        if not self.user.is_superuser:
+            # Validate that the pattern is allowed
+            curs = connection.cursor()
+            curs.execute("SELECT 1 FROM mailmgr_userpermissions WHERE user_id=%(uid)s AND domain_id=%(domain)s AND %(lp)s ~* ('^'||pattern||'$')", {
+                'uid': self.user.pk,
+                'domain': self.cleaned_data['local_domain'].pk,
+                'lp': self.cleaned_data['local_part'],
+            })
+            perms = curs.fetchall()
+
+            if len(perms) < 1:
+                raise ValidationError("Permission denied to create that forwarder for that domain!")
 
         # If it's a new user, also check against if it already exists
         if not self.instance.pk:
index 343bdb12a74fd91d67ff742440ddc82871a311c6..85ef75d9046c7a796c201dfedc74d9e1cd16d4de 100644 (file)
@@ -1,5 +1,5 @@
 from django.shortcuts import render, get_object_or_404
-from django.http import HttpResponseRedirect
+from django.http import HttpResponseRedirect, Http404
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
 from django.db import transaction
@@ -18,7 +18,8 @@ def log(user, what):
 
 @login_required
 def home(request):
-    admperm = VirtualUser.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id]).exists() or \
+    admperm = request.user.is_superuser or \
+        VirtualUser.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id]).exists() or \
         Forwarder.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id]).exists()
     mailboxes = VirtualUser.objects.filter(account=request.user.id)
 
@@ -55,8 +56,12 @@ def mailbox(request, virtualid):
 
 @login_required
 def adm_home(request):
-    users = VirtualUser.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id])
-    forwards = Forwarder.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id])
+    if request.user.is_superuser:
+        users = VirtualUser.objects.all()
+        forwards = Forwarder.objects.all()
+    else:
+        users = VirtualUser.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id])
+        forwards = Forwarder.objects.extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id])
 
     if not forwards and not users:
         return render(request, 'noadm.html', {
@@ -73,6 +78,8 @@ def adm_home(request):
 def userform(request, userparam):
     if userparam == 'add':
         vu = VirtualUser()
+    elif request.user.is_superuser:
+        vu = get_object_or_404(VirtualUser, pk=userparam)
     else:
         vulist = VirtualUser.objects.filter(pk=userparam).extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id])
         if len(vulist) != 1:
@@ -110,6 +117,8 @@ def userform(request, userparam):
 def forwarderform(request, userparam):
     if userparam == 'add':
         fwd = Forwarder()
+    elif request.user.is_superuser:
+        fwd = get_object_or_404(Forwarder, pk=userparam)
     else:
         fwdlist = Forwarder.objects.filter(pk=userparam).extra(where=["EXISTS (SELECT 1 FROM mailmgr_userpermissions p WHERE p.user_id=%s AND p.domain_id = local_domain_id AND local_part ~* ('^'||p.pattern||'$'))" % request.user.id])
         if len(fwdlist) != 1: