Skip to content

Commit

Permalink
backend
Browse files Browse the repository at this point in the history
  • Loading branch information
rm03 committed Nov 10, 2024
1 parent 109c44c commit e659619
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 0 deletions.
27 changes: 27 additions & 0 deletions backend/clubs/middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.contrib.auth.models import User
from django.urls import resolve
from django.utils.functional import SimpleLazyObject


class LimitedPermissionsMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
current_url = getattr(resolve(request.path_info), "url_name", None)

if (
request.user.is_authenticated
and request.user.is_superuser
and request.session.get("limited_permissions", False)
and "limited-permissions" not in current_url
):
limited_user = SimpleLazyObject(
lambda: User.objects.get(pk=request.user.pk)
)
limited_user.is_superuser = False
limited_user.is_staff = False
request.user = limited_user

response = self.get_response(request)
return response
4 changes: 4 additions & 0 deletions backend/clubs/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
FavoriteCalendarAPIView,
FavoriteEventsAPIView,
FavoriteViewSet,
LimitedPermissionsViewSet,
MajorViewSet,
MassInviteAPIView,
MeetingZoomAPIView,
Expand Down Expand Up @@ -134,6 +135,9 @@
)

router.register(r"booths", ClubBoothsViewSet, basename="club-booth")
router.register(
r"limitedpermissions", LimitedPermissionsViewSet, basename="limited-permissions"
)

urlpatterns = [
path(r"settings/", UserUpdateAPIView.as_view(), name="settings-detail"),
Expand Down
49 changes: 49 additions & 0 deletions backend/clubs/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7426,6 +7426,55 @@ def get_queryset(self):
return ClubApprovalResponseTemplate.objects.all().order_by("-created_at")


class LimitedPermissionsViewSet(viewsets.ViewSet):
"""
Allows superusers to view the site from a student perspective.
"""

permission_classes = [IsSuperuser]

def list(self, request):
"""
Check whether limited permissions are enabled for the user's session.
---
summary: Check Limited Permissions
responses:
"200":
content:
application/json:
schema:
type: object
properties:
limited_permissions:
type: boolean
---
"""
return Response(
{"limited_permissions": request.session.get("limited_permissions", False)}
)

@action(detail=False, methods=["post"])
def toggle(self, request, *args, **kwargs):
"""
Toggle limited permissions for the user's session.
---
summary: Toggle Limited Permissions
responses:
"200":
content:
application/json:
schema:
type: object
properties:
limited_permissions:
type: boolean
---
"""
new_state = not request.session.get("limited_permissions", False)
request.session["limited_permissions"] = new_state
return Response({"limited_permissions": new_state}, status=status.HTTP_200_OK)


class ScriptExecutionView(APIView):
"""
View and execute Django management scripts using these endpoints.
Expand Down
1 change: 1 addition & 0 deletions backend/pennclubs/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"simple_history.middleware.HistoryRequestMiddleware",
"clubs.middleware.LimitedPermissionsMiddleware",
]

ROOT_URLCONF = "pennclubs.urls"
Expand Down
27 changes: 27 additions & 0 deletions backend/tests/clubs/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2923,3 +2923,30 @@ def test_club_approval_response_templates(self):
content_type="application/json",
)
self.assertEqual(resp.status_code, 403)

def test_limited_permissions(self):
"""
Test limited permissions (i.e. authenticated student view) for superusers
"""

# Log in as superuser
self.client.force_login(self.user5)

resp = self.client.get(reverse("limited-permissions-list"))

self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json()["limited_permissions"], False)

# Toggle limited permissions
resp = self.client.post(reverse("limited-permissions-toggle"))
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json()["limited_permissions"], True)

# Accessing a superuser-only route should now fail
resp = self.client.get(reverse("templates-list"))
self.assertEqual(resp.status_code, 403)

# After toggling limited permissions, it should work again
self.client.post(reverse("limited-permissions-toggle"))
resp = self.client.get(reverse("templates-list"))
self.assertEqual(resp.status_code, 200)

0 comments on commit e659619

Please sign in to comment.