Permissions & Access Control
Permission system for managing access to church scheduling features.
Quick Reference
| User Type | Access Level |
|---|---|
| Anonymous | /on-duty/ view only |
| Member | Personal dashboard + calendar feed |
| Elder/Deacon | Full admin access[1] |
| Superuser | Unrestricted access |
User Roles
Anonymous Users
Can view weekly duties at /on-duty/. All other features require login.
Authenticated Members
Access:
- Personal dashboard (
/dashboard/) - Weekly duties view (
/on-duty/) - Own profile editing
- Personal calendar feed (UUID-protected)
Cannot:
- Manage stewards or schedules
- Edit other users' data
Church Officers (Elders/Deacons)
Members of Elders or Deacons Django Groups.
Additional Access:
- Steward management (list, create, edit)
- Schedule management (list, create)
- Schedule editing (requires
SchedulePermission)
Special Access via Schedule Permissions
If a standard member is granted a SchedulePermission (e.g., to manage "Ushers"), they automatically gain:
- Access to the Schedules List (
/schedules/) - Access to edit schedules of that specific type (if
can_edit=True)
Group Assignment
Add users to groups via Django Admin → Users → [User] → Groups section.
Superusers
Bypass all permission checks. Created via manage.py createsuperuser.
Permission Layers
1. Church Officer Groups
Two Django Groups created by data migration:
# stewards/migrations/0002_data_migration_create_church_officer_groups.py
Group.objects.get_or_create(name="Elders")
Group.objects.get_or_create(name="Deacons")Both groups grant equivalent administrative access.
2. SchedulePermission Model
Fine-grained per-schedule-type permissions.
Fields:
user- User being granted permissionschedule_type- E.g., "Preaching", "Ushers"can_edit- Can create/edit this schedule typecan_approve_swaps- Can approve swap requests (future)
Example Use Case:
# Allow Deacon John to manage only Ushers schedule
SchedulePermission.objects.create(
user=john,
schedule_type=ScheduleType.objects.get(code="ushering"),
can_edit=True
)TIP
Superusers bypass SchedulePermission checks automatically.
Implementation
View Protection
Class-Based Views:
from braces.views import GroupRequiredMixin, LoginRequiredMixin
class StewardListView(GroupRequiredMixin, LoginRequiredMixin, ListView):
group_required = ["Elders", "Deacons"]Function-Based Views (HTMX):
from .permissions import user_can_edit_schedule
def update_assignment(request, pk):
assignment = get_object_or_404(Assignment, pk=pk)
schedule = assignment.schedule_date.schedule
if not user_can_edit_schedule(request.user, schedule):
return HttpResponse("Permission denied", status=403)Template Checks
Hide admin links:
{% if user.groups.all|length > 0 or user.is_superuser %}
<a href="{% url 'schedules:create' %}">Create Schedule</a>
{% endif %}Context variable:
# In view
context['user_can_edit'] = user_can_edit_schedule(request.user, schedule){% if user_can_edit %}
<button>Publish Schedule</button>
{% endif %}URL Access Matrix
| URL | Access | Notes |
|---|---|---|
/ | Public | |
/auth/login/ | Public | |
/dashboard/ | Login required | |
/on-duty/ | Public | Anyone can view |
/schedules/ | Officers/Delegated | Elders/Deacons or SchedulePermission |
/schedules/create/ | Officers + perm | Requires schedules.add_schedule |
/schedules/<id>/ | Login required | Read-only for non-officers |
/schedules/<id>/publish/ | SchedulePermission | |
/stewards/ | Officers | Elders/Deacons only |
/stewards/profile/edit/ | Own profile |
Testing Checklist
Anonymous User:
Member:
Officer:
Superuser:
Troubleshooting
User can't access steward management
Check group membership: Django Admin → Users → [User] → Groups
User can't edit specific schedule
Verify SchedulePermission exists:
SchedulePermission.objects.filter(
user=user,
schedule_type=schedule.schedule_type,
can_edit=True
).exists()HTMX requests return 403
- Check
user_can_edit_schedule()returnsTrue - Verify schedule is not published (most edits blocked)
- Check CSRF token in browser console
Published Schedules
Editing is blocked on published schedules regardless of permissions. Unpublish first.
Subject to SchedulePermission for schedule editing ↩︎