Implement: Group Creation and Management (US #28) #34

Closed
marko wants to merge 1 commits from feature/group-creation-management into main
Owner

Implemented backend API and frontend components for group creation and management.

Backend

  • Models: Group, GroupMember, GroupInvite, JoinRequest
  • API: Full CRUD for groups, member management (add/remove/role transfer), invite link generation, invite-based joining, join request flow
  • Permissions: GroupAdmin and GroupMember permission classes

Frontend

  • GroupsListPage - list all users groups
  • GroupDetailPage - view group details, manage members, create/revoke invites, transfer admin
  • CreateGroupPage - create a new group
  • JoinGroupPage - join via invite code
  • Navigation links added to Library header

Ref

#28

Implemented backend API and frontend components for group creation and management. ## Backend - **Models**: Group, GroupMember, GroupInvite, JoinRequest - **API**: Full CRUD for groups, member management (add/remove/role transfer), invite link generation, invite-based joining, join request flow - **Permissions**: GroupAdmin and GroupMember permission classes ## Frontend - GroupsListPage - list all users groups - GroupDetailPage - view group details, manage members, create/revoke invites, transfer admin - CreateGroupPage - create a new group - JoinGroupPage - join via invite code - Navigation links added to Library header ## Ref https://gitea-dev.codescripters.org/HermesFactory/cloud-reader/issues/28
marko added 1 commit 2026-06-20 19:27:57 +00:00
Backend:
- Add groups Django app with models: Group, GroupMember, GroupInvite, JoinRequest
- Create serializers with business rule validation
- Implement GroupViewSet with full CRUD + custom actions (members, invites, roles, leave, join requests)
- Add JoinGroupViewSet for invite-based joining flow
- Register app in Django config and URL routing

Frontend:
- Add shared types for groups to @cloud-reader/shared
- Create groups API client (groupsApi)
- Build GroupsListPage, GroupDetailPage (member mgmt, invites, role transfer)
- Build CreateGroupPage and JoinGroupPage
- Add lazy-loaded routes to App.tsx with ProtectedRoute
- Add navigation links to Library header

Ref: #28
Owner

Reid's Review — PR #34

Verdict: 🔴 Changes Required


🔴 Blocking Issues

These MUST be resolved before this PR can be merged.

  • [File: backend/apps/groups/views.py | Lines 860-872] race condition / missing transaction atomicity
    The join action has a race condition. Between checking use_count >= max_uses and incrementing use_count, multiple concurrent requests could join with an exhausted invite. Use F() expressions or select_for_update() to prevent this. Also wrap the member creation in a transaction.atomic() block.

  • [File: frontend/src/pages/GroupDetailPage.tsx | Line 1451] broken member self-check logic
    The condition member.user_id !== Number(user?.email ? undefined : undefined) is nonsensical and evaluates to incorrect behavior. The intent was to hide admin controls when viewing your own entry. Fix to: member.user_id !== user?.id.

  • [File: frontend/src/api/groups.ts | Lines 948-950] any type on API response
    The listGroups return type infers any due to improper type handling. The paginated response structure {count, results} differs from what the type claims. Add proper type guards or normalize the API response.

  • [Files: GroupDetailPage.tsx, GroupsListPage.tsx, JoinGroupPage.tsx, CreateGroupPage.tsx] inline styles violation
    All components use inline styles instead of CSS modules, styled-components, or a consistent styling solution. This violates project standards. Refactor to use external CSS or a styling system.


🟡 Suggestions (Non-Blocking)

These are recommendations for improvement.

  • [File: backend/apps/groups/views.py | Lines 813-826] Consider reusing JoinViaInviteSerializer for validate_invite action.

  • [File: backend/apps/groups/views.py | Lines 660-674] Wrap role transfer in transaction.atomic().

  • [File: backend/apps/groups/models.py] Consider db_index on GroupMember.role.


📋 AC Coverage

Based on linked issue #28

  • Group creation with admin role assignment
  • Group list/detail views with member counts
  • Invite link generation
  • Join via invite confirmation
  • Admin remove members
  • Admin transfer role
  • Member leave group (dissolution if last admin)
  • Admin approval flow for join requests - NOT IMPLEMENTED
## Reid's Review — PR #34 **Verdict:** 🔴 Changes Required --- ### 🔴 Blocking Issues > These MUST be resolved before this PR can be merged. - **[File: backend/apps/groups/views.py | Lines 860-872]** `race condition / missing transaction atomicity` The join action has a race condition. Between checking `use_count >= max_uses` and incrementing `use_count`, multiple concurrent requests could join with an exhausted invite. Use F() expressions or select_for_update() to prevent this. Also wrap the member creation in a transaction.atomic() block. - **[File: frontend/src/pages/GroupDetailPage.tsx | Line 1451]** `broken member self-check logic` The condition `member.user_id !== Number(user?.email ? undefined : undefined)` is nonsensical and evaluates to incorrect behavior. The intent was to hide admin controls when viewing your own entry. Fix to: `member.user_id !== user?.id`. - **[File: frontend/src/api/groups.ts | Lines 948-950]** `any type on API response` The listGroups return type infers `any` due to improper type handling. The paginated response structure `{count, results}` differs from what the type claims. Add proper type guards or normalize the API response. - **[Files: GroupDetailPage.tsx, GroupsListPage.tsx, JoinGroupPage.tsx, CreateGroupPage.tsx]** `inline styles violation` All components use inline styles instead of CSS modules, styled-components, or a consistent styling solution. This violates project standards. Refactor to use external CSS or a styling system. --- ### 🟡 Suggestions (Non-Blocking) > These are recommendations for improvement. - **[File: backend/apps/groups/views.py | Lines 813-826]** Consider reusing JoinViaInviteSerializer for validate_invite action. - **[File: backend/apps/groups/views.py | Lines 660-674]** Wrap role transfer in transaction.atomic(). - **[File: backend/apps/groups/models.py]** Consider db_index on GroupMember.role. --- ### 📋 AC Coverage > Based on linked issue #28 - [x] Group creation with admin role assignment - [x] Group list/detail views with member counts - [x] Invite link generation - [x] Join via invite confirmation - [x] Admin remove members - [x] Admin transfer role - [x] Member leave group (dissolution if last admin) - [ ] Admin approval flow for join requests - NOT IMPLEMENTED
max closed this pull request 2026-07-21 22:15:54 +00:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No labels
2 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: HermesFactory/cloud-reader#34