This repository has been archived on 2026-07-21. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cloud-reader/backend/apps/groups/permissions.py
Marko 8a86cf8388 feat: implement per-member reading progress tracking for shared books (#30)
Backend (apps/groups):
- ReadingGroup model: named groups linked to EBooks with creator tracking
- GroupMembership model: user-group association with member/admin roles
- MemberProgress model: per-member progress with section tracking,
  percentage, time_spent, privacy toggles, and device-position preservation
- ReadingGroupViewSet: CRUD, join/leave, members list, progress endpoints
- GET /api/groups/{id}/members/progress/ — all members' progress
  (public: section label only; own: full detail; private: stubbed)
- PATCH /api/groups/{id}/progress/ — update own progress with auto-
  percentage calculation from section boundaries
- GET /api/groups/{id}/progress/summary/ — admin dashboard with
  averages, started/finished counts, and per-member details
- Permissions: IsGroupMember, IsGroupAdmin

Frontend:
- Groups list page (/groups) with create modal and book selector
- Group detail page (/groups/:id) with progress and admin summary tabs
- Progress bar visualization per member with privacy-aware display
- Admin stat cards (total members, started, finished, avg progress, avg time)
- Navigation link from Library header

Shared:
- ReadingGroupSummary and MemberProgressPublic types
- API endpoint constants for groups routes

Closes #30
2026-06-20 19:31:21 +00:00

28 lines
977 B
Python

from rest_framework import permissions
from rest_framework.request import Request
from apps.groups.models import GroupMembership
class IsGroupMember(permissions.BasePermission):
"""Allow access only to members of the group."""
def has_permission(self, request: Request, view: object) -> bool:
group_id = view.kwargs.get("group_pk") or view.kwargs.get("pk")
if not group_id:
return False
return GroupMembership.objects.filter(
group_id=group_id, user=request.user
).exists()
class IsGroupAdmin(permissions.BasePermission):
"""Allow access only to group admins."""
def has_permission(self, request: Request, view: object) -> bool:
group_id = view.kwargs.get("group_pk") or view.kwargs.get("pk")
if not group_id:
return False
return GroupMembership.objects.filter(
group_id=group_id, user=request.user, role=GroupMembership.Role.ADMIN
).exists()