Skip to content

Conversation

@ishanBahuguna
Copy link
Contributor

Proposed change

Resolves #2624

Backend:

  1. Updated the Project model to support Slack channel URLs using EntityChannel.
  2. Implemented a new resolver to fetch Slack channel links from the backend.
  3. Added test cases for the updated model and resolver functionality.

Frontend:

  1. Updated the GraphQL query to fetch Slack channel data for Project pages.
  2. Displayed proper badges on specific projects
  3. Added test cases to validate the correct retrieval and rendering of Slack channel.

While working on the issue I found that the Chapter page is already displaying the slack channels on frontend

Checklist

  • I read and followed the contributing guidelines
  • I ran make check-test locally and all tests passed
  • I used AI for code, documentation, or tests in this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Summary by CodeRabbit

  • New Features
    • Projects now display social links on their detail pages, including platform-specific URLs for connected social channels.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

This PR introduces support for displaying related Slack channels on Chapter and Project pages. Backend changes add GenericRelation fields to Project and Chapter models, expose these relationships via a new social_urls GraphQL field on ProjectNode, and include corresponding tests. Frontend updates the DetailsCard component to render social links for projects, fetches the data via an updated GraphQL query, extends type definitions, and adds test coverage.

Changes

Cohort / File(s) Summary
Backend Models
backend/apps/owasp/models/project.py, backend/apps/owasp/models/chapter.py
Added social_channels and channels GenericRelation fields to Project and Chapter models respectively, enabling reverse lookups to EntityChannel records. Imported EntityChannel to support the relations.
Backend GraphQL/API
backend/apps/owasp/api/internal/nodes/project.py
Added social_urls() method to ProjectNode that iterates over active social_channels and returns a list of Slack app redirect URLs for channels with valid slack_channel_id.
Backend Tests
backend/tests/apps/owasp/models/project_test.py, backend/tests/apps/owasp/api/internal/nodes/project_test.py
Added tests validating the new social_channels GenericRelation field and social_urls GraphQL field presence, type, and expected field metadata.
Frontend Type Definitions
frontend/src/types/project.ts
Added optional socialUrls?: string[] property to the Project type interface.
Frontend GraphQL Queries
frontend/src/server/queries/projectQueries.ts
Updated GET_PROJECT_DATA query to include socialUrls field in the project selection set.
Frontend Components
frontend/src/components/CardDetailsPage.tsx, frontend/src/app/projects/[projectKey]/page.tsx
Extended SocialLinks rendering condition to include type 'project'; added socialLinks prop to DetailsCard in ProjectDetailsPage populated with project.socialUrls.
Frontend Tests
frontend/__tests__/unit/components/CardDetailsPage.test.tsx
Added test cases validating SocialLinks rendering for project type with non-empty socialLinks arrays.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review GenericRelation configuration and reverse lookup semantics in models
  • Verify social_urls resolver correctly filters and transforms slack channel data
  • Confirm GraphQL query shape alignment with frontend type definitions
  • Validate test coverage completeness for new model and resolver fields

Possibly related PRs

Suggested labels

backend, frontend, backend-tests, frontend-tests

Suggested reviewers

  • arkid15r
  • kasya

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main feature added: related Slack channels for chapters and projects, which aligns with the core changeset.
Description check ✅ Passed The description comprehensively covers backend and frontend changes, testing, and provides context about the Chapter page already supporting Slack channels.
Linked Issues check ✅ Passed The PR addresses issue #2624 requirements: added GenericRelation fields to Chapter and Project models [project.py, chapter.py], implemented GraphQL resolver for social_urls [project.py], updated GraphQL query [projectQueries.ts], and added comprehensive tests for both backend and frontend.
Out of Scope Changes check ✅ Passed All changes are within scope of issue #2624: model relations, GraphQL resolvers, frontend queries, UI rendering, and corresponding tests. No unrelated modifications detected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

✨ Issue Enrichment is now available for GitHub issues!

CodeRabbit can now help you manage issues more effectively:

  • Duplicate Detection — Identify similar or duplicate issues
  • Related Issues & PRs — Find relevant issues and PR's from your repository
  • Suggested Assignees — Find the best person to work on the issue
  • Implementation Planning — Generate detailed coding plans for engineers and agents
Disable automatic issue enrichment

To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

issue_enrichment:
  auto_enrich:
    enabled: false

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
frontend/src/components/CardDetailsPage.tsx (1)

120-148: Extending SocialLinks to project type is aligned and guarded

The condition now including type === 'project' reuses the existing SocialLinks rendering path for chapters/committees and is still safely guarded by socialLinks truthiness, with SocialLinks itself no-op’ing on an empty array. This is a straightforward and correct extension of the existing behavior.

If you touch this area again, consider replacing the repeated type === ... checks with an ['chapter', 'committee', 'project'].includes(type) style predicate for slightly clearer intent.

backend/tests/apps/owasp/models/project_test.py (1)

4-9: Good coverage of social_channels GenericRelation

The new test_social_channels_ accurately verifies the presence and configuration of the social_channels GenericRelation on Project, including model type and content-type/object-id field names, which should catch regressions in the relation wiring.

You might rename the test to something like test_social_channels_field_configuration (dropping the trailing underscore) to better reflect its purpose and match existing naming style.

Also applies to: 136-143

frontend/__tests__/unit/components/CardDetailsPage.test.tsx (1)

675-695: New test for project social links covers the added behavior

The renders social links for project type when socialLinks are provided test accurately asserts that the Social Links heading appears and that three links are rendered for a project with three URLs, mirroring the existing chapter/committee tests and giving good regression coverage.

Because you assert on getAllByRole('link'), this test may become brittle if additional unrelated links are added to the card; using a more specific container or test id around the Social Links section could make it more resilient.

backend/apps/owasp/api/internal/nodes/project.py (1)

114-127: social_urls resolver is functionally correct for Slack channels

The resolver walks active social_channels, filters for Slack entries with a non-empty slack_channel_id, and returns well-formed app_redirect URLs, which matches the requirement to expose related Slack channels; given it’s used for a single-project query, the simple loop is acceptable from a performance standpoint.

If there’s a chance of duplicate EntityChannel records pointing to the same Slack channel, you may want to de-duplicate urls (e.g., via a set) or enforce uniqueness at the DB layer to avoid repeated badges in the UI.

backend/apps/owasp/models/chapter.py (1)

71-77: Consider aligning field naming with Project model for consistency.

The implementation is correct, but there's a naming inconsistency: Project uses social_channels while Chapter uses channels. Since both serve the same purpose (linking to EntityChannel for social/Slack channels), consistent naming would improve code maintainability and reduce cognitive load when working across both models.

If you agree, consider renaming to match:

-    # related channels from EntityChannel
-    channels = GenericRelation(
+    # related channels from EntityChannel
+    social_channels = GenericRelation(
         EntityChannel,
         content_type_field="entity_type",
         object_id_field="entity_id",
-        related_query_name="chapter",
+        related_query_name="chapter",
     )

Note: If you choose to rename, ensure any existing usages of chapter.channels (e.g., in API resolvers or templates) are updated accordingly.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfef4da and c430247.

⛔ Files ignored due to path filters (2)
  • frontend/src/types/__generated__/graphql.ts is excluded by !**/__generated__/**
  • frontend/src/types/__generated__/projectQueries.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (10)
  • backend/apps/owasp/api/internal/nodes/project.py (1 hunks)
  • backend/apps/owasp/models/chapter.py (2 hunks)
  • backend/apps/owasp/models/project.py (2 hunks)
  • backend/tests/apps/owasp/api/internal/nodes/project_test.py (2 hunks)
  • backend/tests/apps/owasp/models/project_test.py (2 hunks)
  • frontend/__tests__/unit/components/CardDetailsPage.test.tsx (1 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (1 hunks)
  • frontend/src/server/queries/projectQueries.ts (1 hunks)
  • frontend/src/types/project.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-07-12T17:36:57.255Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/__tests__/unit/pages/createProgram.test.tsx:70-86
Timestamp: 2025-07-12T17:36:57.255Z
Learning: When testing React page components that use mocked form components, validation logic should be tested at the form component level, not the page level. Page-level tests should focus on authentication, role checking, submission handling, and navigation logic.

Applied to files:

  • frontend/__tests__/unit/components/CardDetailsPage.test.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a length check before rendering HealthMetrics: `healthMetricsData.length > 0`. This ensures that when HealthMetrics is rendered, the data array has at least one element, making accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/CardDetailsPage.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a safety check that ensures HealthMetrics component is only rendered when healthMetricsData exists and has at least one element: `healthMetricsData && healthMetricsData.length > 0`. This makes accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/CardDetailsPage.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS is actively used in frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx for program editing functionality and cannot be removed. It serves a different purpose than GET_PROGRAM_ADMIN_DETAILS, providing comprehensive program information needed for editing.

Applied to files:

  • frontend/src/server/queries/projectQueries.ts
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details. These queries cannot be removed or merged as they serve different use cases in the application.

Applied to files:

  • frontend/src/server/queries/projectQueries.ts
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details.

Applied to files:

  • frontend/src/server/queries/projectQueries.ts
📚 Learning: 2025-09-10T03:14:06.506Z
Learnt from: arkid15r
Repo: OWASP/Nest PR: 1995
File: backend/apps/github/models/issue.py:61-65
Timestamp: 2025-09-10T03:14:06.506Z
Learning: When refactoring from ManyToManyField to GenericForeignKey + GenericRelation in Django, all standard relationship operations (.all(), .add(), .select_related(), .order_by()) continue to work unchanged. GenericRelation automatically handles setting content_type and object_id when using .add().

Applied to files:

  • backend/apps/owasp/models/project.py
🧬 Code graph analysis (4)
backend/apps/owasp/models/chapter.py (1)
backend/apps/owasp/models/entity_channel.py (1)
  • EntityChannel (8-66)
frontend/src/app/projects/[projectKey]/page.tsx (1)
backend/apps/github/models/repository.py (1)
  • project (162-164)
backend/tests/apps/owasp/models/project_test.py (1)
backend/apps/owasp/models/entity_channel.py (1)
  • EntityChannel (8-66)
backend/apps/owasp/models/project.py (1)
backend/apps/owasp/models/entity_channel.py (1)
  • EntityChannel (8-66)
🔇 Additional comments (7)
frontend/src/app/projects/[projectKey]/page.tsx (1)

91-111: Propagating socialUrls into DetailsCard looks correct

Passing socialLinks={project.socialUrls} cleanly wires the new GraphQL field into the shared details component, and the downstream component already guards rendering on presence/length of the array, so this should be safe even when the field is null/undefined or empty.

frontend/src/types/project.ts (1)

18-48: socialUrls type addition is consistent with usage

Adding socialUrls?: string[] to Project matches the GraphQL selection and DetailsCard props, and keeping it optional preserves backward compatibility with callers that don’t request this field.

frontend/src/server/queries/projectQueries.ts (1)

3-128: GraphQL query now correctly fetches socialUrls

Including socialUrls in GET_PROJECT_DATA keeps the client query in sync with the new ProjectNode field and the Project type, enabling the project page to render social links without affecting other queries like GET_PROJECT_METADATA.

backend/tests/apps/owasp/api/internal/nodes/project_test.py (1)

16-41: ProjectNode test suite correctly extended for social_urls

Adding "social_urls" to expected_field_names and the dedicated test_resolve_social_urls that checks the type as list[str] keeps the public API contract of ProjectNode well-specified and ensures the new field can’t silently change or disappear.

Also applies to: 108-111

backend/apps/owasp/models/project.py (2)

22-22: LGTM!

The import is correctly placed alongside other model imports.


130-136: LGTM!

The GenericRelation setup is correct and follows Django conventions. The field configuration properly maps to EntityChannel's entity_type and entity_id fields, and the related_query_name="project" enables efficient reverse lookups. Based on learnings, this pattern supports all standard relationship operations.

backend/apps/owasp/models/chapter.py (1)

17-17: LGTM!

The import is correctly placed with other model imports.

@ahmedxgouda ahmedxgouda self-assigned this Dec 11, 2025
@ishanBahuguna
Copy link
Contributor Author

@ahmedxgouda should I keep working on this ? As you have assigned this to yourself

@arkid15r
Copy link
Collaborator

@ahmedxgouda should I keep working on this ? As you have assigned this to yourself

@ishanBahuguna yes. Ahmed is an assignee for the code review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add related Slack channels to Chapter and Project pages

3 participants