-
Notifications
You must be signed in to change notification settings - Fork 113
Description
Permission handling is inconsistent between the Tickets and Talk components.
In the Tickets component, users with Site Admin rights can activate Admin Mode as expected.
However, when moving to the Talk component, an info message appears claiming that the user has superuser rights, even though they are not Django superusers.
This indicates that the permission system is not aligned between components.
Site Admins should have the same level of access in both components, and standard users should remain standard users.
Superuser status should only apply to actual Django superusers (is_superuser=True
).
Goal
Unify the role model, checks, and UI indicators so that permissions behave identically across all Eventyay components.
- Site Admins (platform admins) in Tickets must be recognized as Site Admins in Talk.
- Standard users remain standard users in both components.
- The system should not conflate Site Admins with Django superusers.
- Permission checks, role handling, and admin mode toggling must use the same logic and helpers across components.
Expected Behavior
-
Establish a single shared source of truth for roles in
eventyay-common
:UserRole.SITE_ADMIN
UserRole.ORGANIZER
UserRole.STANDARD_USER
-
Both Tickets and Talk must use the same helper functions to determine:
- Whether a user is a site admin
- Whether a user is a superuser
- Whether a user is an organizer admin
-
The UI should show:
- “Admin Mode” toggle only for site admins (and organizer admins where appropriate)
- “Superuser” banner only for true Django superusers
Steps to Reproduce (Current)
- Log in as a Site Admin (not a Django superuser).
- Go to Tickets → Admin Mode toggle appears correctly.
- Go to Talk → An info message appears stating the user has superuser rights.
The behavior differs, and permission messages are inconsistent.
Technical Details and Implementation Plan
Relevant File Locations
Talk:
app/eventyay/orga/views/*.py
(view-level permission checks)app/eventyay/orga/templates/orga/**
(banner and admin messages)app/eventyay/common/context_processors.py
(permission context)app/eventyay/orga/templatetags/**
(template permission helpers if any)
Tickets (reference for correct behavior):
app/eventyay/base/views/**
app/eventyay/**/templates/**
where “Admin Mode” toggle logic exists
To identify all locations:
rg -n "(is_superuser|is_staff|Admin Mode|superuser)" app/eventyay -S
rg -n "(site_admin|siteadmin|role.*admin)" app/eventyay -S
Shared Helper Module
Create a shared module in app/eventyay/common/auth/permissions.py
:
from django.contrib.auth.models import Group
SITE_ADMIN_GROUP = "site_admin"
def is_superuser(user):
return bool(user and user.is_authenticated and user.is_superuser)
def is_site_admin(user):
if not (user and user.is_authenticated):
return False
try:
return user.groups.filter(name=SITE_ADMIN_GROUP).exists()
except Exception:
return False
def is_organizer_admin(user, organizer=None):
if not (user and user.is_authenticated and organizer):
return False
return organizer.admins.filter(pk=user.pk).exists()
If the project already uses User.is_site_admin
, use that field in is_site_admin(user)
instead of group logic.
Shared Context Processor
Add a context processor to inject permission flags into templates:
app/eventyay/common/context_processors.py
from .auth.permissions import is_site_admin, is_superuser
def permission_flags(request):
u = getattr(request, "user", None)
return {
"is_site_admin": is_site_admin(u),
"is_superuser": is_superuser(u),
}
In settings.py
for both components:
TEMPLATES[0]["OPTIONS"]["context_processors"] += [
"eventyay.common.context_processors.permission_flags",
]
Template Updates
Before (Talk):
{% if request.user.is_superuser %}
<div class="alert alert-info">You have superuser rights</div>
{% endif %}
After (Unified):
{% if is_site_admin %}
<div class="alert alert-info">You have site admin rights</div>
{% endif %}
{% if is_superuser %}
<div class="alert alert-warning">You are a Django superuser</div>
{% endif %}
View Updates
Replace direct permission checks:
if request.user.is_superuser:
# old logic
With:
from eventyay.common.auth.permissions import is_site_admin, is_superuser
if is_site_admin(request.user) or is_superuser(request.user):
# new logic
Admin Mode Toggle
Extract and centralize:
def can_toggle_admin_mode(user):
from eventyay.common.auth.permissions import is_site_admin, is_superuser
return is_site_admin(user) or is_superuser(user)
Use this in both Tickets and Talk headers or navigation bars.
Data Migration
Ensure all current site admins are recognized:
from django.contrib.auth.models import Group, User
g, _ = Group.objects.get_or_create(name="site_admin")
for u in User.objects.filter(is_staff=True):
u.groups.add(g)
If using User.is_site_admin
, verify it’s correctly set.
Testing Plan
Unit Tests
- Test
is_site_admin
,is_superuser
, andis_organizer_admin
helpers. - Test anonymous, standard, site admin, and superuser cases.
Template Tests
- Verify site admins see “Admin Mode” but not superuser banners.
- Verify superusers see both banners.
- Verify standard users see neither.
View Tests
- Test that endpoints restricted to admins are accessible only by site admins and superusers.
- Test that standard users receive 403 responses.
Integration and E2E Tests
- Log in as site admin → Tickets shows Admin Mode, Talk shows Admin Mode, no superuser banner.
- Log in as superuser → Both Admin Mode and superuser banner visible.
- Log in as standard user → No admin controls in either component.
Acceptance Criteria
Permission Model:
- Shared helper functions used consistently across components.
is_site_admin
returns true only for platform admins.is_superuser
used exclusively for Django superusers.- Organizer-scoped checks aligned.
Tickets Component:
- Admin Mode toggle appears correctly.
- No behavioral regressions.
Talk Component:
- Misleading superuser banner removed.
- Admin Mode and rights consistent with Tickets.
Cross-Component:
- UI and permission messages aligned.
- No regressions for standard users.
- Documentation updated.

