Skip to content

Private Consortia #112

@rssk

Description

@rssk

Implement Private Consortia Feature

Overview

Add support for private consortia that are only visible to the owner (leader), members, and admins. Private consortia should be hidden from users who are not part of the consortium. Only the leader can modify the privacy setting of a consortium.

Requirements

1. Database Schema Changes

  • Add isPrivate: Boolean field to the Consortium model schema
    • Default value: false (existing consortia remain public)
    • Location: centralApi/src/database/models/Consortium.ts
    • Update Consortium interface to include isPrivate: boolean

2. GraphQL Schema Updates

  • Add isPrivate: Boolean! field to ConsortiumListItem type
    • Location: centralApi/src/graphql/typeDefs.graphql
  • Add isPrivate: Boolean! field to ConsortiumDetails type
    • Location: centralApi/src/graphql/typeDefs.graphql
  • Update consortiumCreate mutation to accept optional isPrivate: Boolean parameter
    • Default to false if not provided
  • Update consortiumEdit mutation to accept optional isPrivate: Boolean parameter

3. Backend Resolver Changes

getConsortiumList Query

  • Filter consortia based on privacy and user access:
    • If isPrivate === false: Include in results (public consortia visible to all)
    • If isPrivate === true: Only include if:
      • Current user is the leader (consortium.leader.toString() === context.userId), OR
      • Current user is in the members array (consortium.members.includes(context.userId)), OR
      • Current user has admin role (context.roles?.includes('admin'))
  • Include isPrivate field in the returned ConsortiumListItem objects
  • Location: centralApi/src/graphql/resolvers.ts (line ~40)

getConsortiumDetails Query

  • Add access control check:
    • If isPrivate === false: Allow access (public consortium)
    • If isPrivate === true: Only allow if:
      • Current user is the leader, OR
      • Current user is in the members array, OR
      • Current user has admin role (context.roles?.includes('admin'))
    • If access denied, throw error: "Access denied: This consortium is private"
  • Include isPrivate field in the returned ConsortiumDetails object
  • Location: centralApi/src/graphql/resolvers.ts (line ~68)

consortiumCreate Mutation

  • Accept optional isPrivate: Boolean parameter
  • Set isPrivate field when creating new consortium
  • Default to false if not provided
  • Location: centralApi/src/graphql/resolvers.ts (line ~750)

consortiumEdit Mutation

  • Accept optional isPrivate: Boolean parameter
  • Update isPrivate field if provided
  • Only allow leader to modify privacy setting - verify consortium.leader.toString() === context.userId before allowing isPrivate field changes
  • When a consortium is made private, existing members retain access (no action needed)
  • Location: centralApi/src/graphql/resolvers.ts (line ~899)

4. Frontend Updates

GraphQL Query Updates

  • Update GET_CONSORTIUM_LIST_QUERY to include isPrivate field
    • Location: desktopApp/reactApp/src/apis/centralApi/getConsortiumList.tsx
  • Update GET_CONSORTIUM_DETAILS query to include isPrivate field
    • Location: desktopApp/reactApp/src/apis/centralApi/getConsortiumDetails.tsx

UI Components

  • Update consortium creation form to include privacy toggle/checkbox
  • Update consortium edit form to include privacy toggle/checkbox (only visible/editable by leader)
  • Note: No UI indicators (e.g., lock icons) needed in list view per requirements

5. Type Generation

  • Regenerate GraphQL types after schema changes
    • Run codegen to update generated types in:
      • centralApi/src/graphql/generated/graphql.ts
      • desktopApp/reactApp/src/apis/centralApi/generated/graphql.ts

6. Testing Considerations

  • Test that public consortia (isPrivate: false) are visible to all users
  • Test that private consortia (isPrivate: true) are only visible to leader, members, and admins
  • Test that non-members cannot access private consortium details
  • Test consortium creation with isPrivate: true and isPrivate: false
  • Test consortium edit to toggle privacy setting
  • Test that existing consortia (without isPrivate field) default to public behavior
  • Test edge cases:
    • User leaves private consortium (should no longer see it)
    • User is removed from private consortium (should no longer see it)
    • Leader changes privacy setting (only leader can modify)
    • Admin can access private consortia even if not a member
    • When consortium is made private, existing members retain access

Implementation Notes

Access Control Logic

The access check should verify:

const hasAccess = 
  !consortium.isPrivate || 
  consortium.leader.toString() === context.userId || 
  consortium.members.some(member => member.toString() === context.userId) ||
  context.roles?.includes('admin')

Privacy Setting Modification:

  • Only the leader can change the isPrivate field
  • When a consortium is made private, existing members automatically retain access

Migration Considerations

  • Existing consortia without isPrivate field should default to false (public)
  • Consider adding a migration script if needed, or rely on Mongoose defaults

Security

  • Ensure context.userId is always available and validated
  • Return appropriate error messages for unauthorized access attempts
  • Consider logging access attempts to private consortia for security auditing

Acceptance Criteria

  • Private consortia are only visible to owner, members, and admins
  • Public consortia remain visible to all users
  • Backend properly filters consortia based on privacy flag and user access
  • Only leader can modify privacy setting
  • When a consortium is made private, existing members retain access
  • Users can create consortia with privacy settings
  • Leader can edit privacy setting in consortium edit form
  • All existing functionality continues to work for public consortia
  • No breaking changes to existing API contracts (backward compatible)

Related Files

  • centralApi/src/database/models/Consortium.ts
  • centralApi/src/graphql/typeDefs.graphql
  • centralApi/src/graphql/resolvers.ts
  • centralApi/src/graphql/generated/graphql.ts
  • desktopApp/reactApp/src/apis/centralApi/getConsortiumList.tsx
  • desktopApp/reactApp/src/apis/centralApi/getConsortiumDetails.tsx
  • desktopApp/reactApp/src/apis/centralApi/generated/graphql.ts

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions