Skip to content

Feature/snapshot subscription graphql - #5058

Open
HarshitVerma109 wants to merge 3 commits into
OWASP:feature/community-snapshotsfrom
HarshitVerma109:feature/snapshot-subscription-graphql
Open

Feature/snapshot subscription graphql#5058
HarshitVerma109 wants to merge 3 commits into
OWASP:feature/community-snapshotsfrom
HarshitVerma109:feature/snapshot-subscription-graphql

Conversation

@HarshitVerma109

Copy link
Copy Markdown
Collaborator

Proposed change

Resolves #5056

Adds GraphQL mutations and query for managing snapshot digest subscriptions. Users can create, update, and cancel their subscription, and unsubscribe directly from email links using a token-based endpoint that requires no login.

Checklist

  • Required: I followed the contributing workflow
  • Required: I verified that my code works as intended and resolves the issue as described
  • Required: I ran all required checks and tests locally; all warnings addressed and failures resolved
  • I used AI for code, documentation, tests, or communication related to this PR

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Changes

Subscription models and persistence

Layer / File(s) Summary
Subscription models and persistence
backend/apps/owasp/models/*, backend/apps/owasp/migrations/..., backend/tests/unit/apps/owasp/models/*
Snapshot subscription content fields and persistence methods are refactored. Entity subscriptions and per-entity preferences, constraints, synchronization, migration, and model tests are added.

Entity subscription GraphQL surface

Layer / File(s) Summary
Entity subscription GraphQL surface
backend/apps/owasp/api/internal/{mutations,nodes,queries}/*, backend/tests/unit/apps/owasp/api/internal/{mutations,nodes,queries}/entity_subscription_test.py
GraphQL inputs, result types, queries, nodes, and authenticated/token-based entity subscription mutations are added with validation and tests.

Snapshot subscription GraphQL surface

Layer / File(s) Summary
Snapshot subscription GraphQL surface
backend/apps/owasp/api/internal/{mutations,nodes,queries}/*, backend/settings/graphql.py, backend/tests/unit/apps/owasp/api/internal/{mutations,nodes,queries}/snapshot_subscription_test.py
Snapshot subscription queries and mutations are exposed through the GraphQL schema, including create, update, cancel, and token unsubscribe operations.

Subscription administration

Layer / File(s) Summary
Subscription administration
backend/apps/owasp/admin/*, backend/tests/unit/apps/owasp/admin/*
Entity subscription inlines and admin configuration are added, while snapshot subscription fieldsets and registration tests are updated.

Chapter search query

Layer / File(s) Summary
Chapter search query
backend/apps/owasp/api/internal/{nodes,queries}/*, backend/tests/unit/apps/owasp/api/internal/queries/chapter_test.py
Chapter IDs and bounded active-chapter search are exposed through GraphQL with resolver coverage.

Snapshot automation target arrangement

Layer / File(s) Summary
Snapshot automation target arrangement
backend/apps/owasp/Makefile
The snapshot frequency variable and creation target are moved earlier, removing their duplicate definition.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • OWASP/Nest#4938: Both changes touch the OWASP snapshot Makefile frequency and creation target.
  • OWASP/Nest#5021: Both changes overlap in snapshot subscription model fields and admin configuration.

Suggested reviewers: kasya, arkid15r, rudransh-shrivastava

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning It also adds a separate EntitySubscription system and Chapter query changes that are not part of #5056. Move the EntitySubscription and Chapter-related work into a separate PR unless those changes are explicitly required for #5056.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Related to the main change, though the phrasing is broad and not very polished.
Description check ✅ Passed The description matches the snapshot subscription GraphQL query, mutations, unsubscribe flow, and tests.
Linked Issues check ✅ Passed The PR implements the required snapshot subscription query, mutations, unsubscribe flow, and tests.
Docstring Coverage ✅ Passed Docstring coverage is 90.51% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.67846% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.78%. Comparing base (38e18f2) to head (8e2855c).
⚠️ Report is 1 commits behind head on feature/community-snapshots.

Files with missing lines Patch % Lines
...sp/api/internal/mutations/snapshot_subscription.py 99.20% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                       Coverage Diff                       @@
##           feature/community-snapshots    #5058      +/-   ##
===============================================================
+ Coverage                        98.77%   98.78%   +0.01%     
===============================================================
  Files                              543      546       +3     
  Lines                            17443    17739     +296     
  Branches                          2539     2571      +32     
===============================================================
+ Hits                             17229    17524     +295     
- Misses                              88       89       +1     
  Partials                           126      126              
Flag Coverage Δ
backend 99.34% <99.67%> (+<0.01%) ⬆️
frontend 97.22% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...kend/src/apps/owasp/admin/snapshot_subscription.py 100.00% <100.00%> (ø)
...ckend/src/apps/owasp/api/internal/nodes/chapter.py 100.00% <ø> (ø)
.../owasp/api/internal/nodes/snapshot_subscription.py 100.00% <100.00%> (ø)
...end/src/apps/owasp/api/internal/queries/chapter.py 100.00% <100.00%> (ø)
...d/src/apps/owasp/api/internal/queries/committee.py 100.00% <100.00%> (ø)
...end/src/apps/owasp/api/internal/queries/project.py 100.00% <100.00%> (ø)
...wasp/api/internal/queries/snapshot_subscription.py 100.00% <100.00%> (ø)
...end/src/apps/owasp/models/snapshot_subscription.py 100.00% <100.00%> (ø)
...sp/api/internal/mutations/snapshot_subscription.py 99.20% <99.20%> (ø)

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 38e18f2...8e2855c. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/apps/owasp/api/internal/mutations/snapshot_subscription.py`:
- Around line 167-173: The unsubscribe-token lookup in SnapshotSubscription
mutation only handles SnapshotSubscription.DoesNotExist and ValueError, but
invalid UUID input raises Django’s ValidationError before the query completes.
Update the exception handling in the mutation that calls
SnapshotSubscription.objects.get(unsubscribe_token=token) to also catch
ValidationError, and make sure the needed import from django.core.exceptions is
added so malformed tokens return the existing invalid-token result instead of an
unhandled error.
- Around line 63-86: The subscription creation logic in SnapshotSubscription
mutation is checking only
SnapshotSubscription.objects.filter(user=user).exists(), which blocks
re-subscription after cancel and still allows a race before create(). Update the
check to distinguish active vs inactive subscriptions (for example, based on
is_active in the SnapshotSubscription model) so canceled users can subscribe
again, and make the create path resilient to concurrent requests by handling the
one-to-one constraint failure around the subscription creation in the mutation
that builds the SnapshotSubscriptionResult.

In `@backend/apps/owasp/models/snapshot_subscription.py`:
- Around line 34-45: The subscription creation flow is blocking re-subscribes
because it treats inactive records as existing subscriptions. Update the
existence check in create_snapshot_subscription to only consider active
SnapshotSubscription rows by filtering on user and is_active=True, while keeping
the cancellation/unsubscribe behavior in cancel_snapshot_subscription and
unsubscribe_by_token unchanged so users can recreate a subscription after
canceling it.

In `@backend/tests/unit/apps/owasp/admin/snapshot_subscription_test.py`:
- Around line 12-45: The test only checks SnapshotSubscriptionAdmin directly and
misses whether apps.owasp.admin actually registers the model with admin.site.
Update the test in snapshot_subscription_test to import the admin package/module
that performs registration and assert SnapshotSubscription is present in
admin.site._registry, or that the registry entry is an instance of
SnapshotSubscriptionAdmin, so a broken import or missing admin.site.register
call is caught.

In
`@backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py`:
- Around line 187-195: Update test_malformed_token in
snapshot_subscription_test.py to match Django ORM behavior by mocking
django.core.exceptions.ValidationError instead of ValueError for
SnapshotSubscription.objects.get and keep the same unsubscribe_by_token
assertion. Also add a new test_create_after_cancel around
create_snapshot_subscription to verify a user can create a new subscription
after a previously cancelled/inactive one, so the test covers the intended
recreate flow rather than blocking on any existing record.

In
`@backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py`:
- Around line 34-59: The snapshot subscription tests are calling the Strawberry
Django field descriptor directly instead of the underlying resolver, so they
never execute the real my_subscription logic. Update the tests in
SnapshotSubscriptionQuery to fetch the my_subscription field from the class and
invoke its base_resolver.func with self.query and info, so the resolver
implementation is actually exercised for the authenticated, not found, and found
cases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1a833131-728a-4590-803c-f98c71da2af2

📥 Commits

Reviewing files that changed from the base of the PR and between 5a15194 and 22b8e4b.

⛔ Files ignored due to path filters (1)
  • frontend/src/types/__generated__/graphql.ts is excluded by !**/__generated__/**
📒 Files selected for processing (18)
  • backend/apps/owasp/admin/__init__.py
  • backend/apps/owasp/admin/snapshot_subscription.py
  • backend/apps/owasp/api/internal/mutations/__init__.py
  • backend/apps/owasp/api/internal/mutations/snapshot_subscription.py
  • backend/apps/owasp/api/internal/nodes/snapshot_subscription.py
  • backend/apps/owasp/api/internal/queries/__init__.py
  • backend/apps/owasp/api/internal/queries/snapshot_subscription.py
  • backend/apps/owasp/migrations/0075_snapshotsubscription.py
  • backend/apps/owasp/models/__init__.py
  • backend/apps/owasp/models/snapshot_subscription.py
  • backend/data/nest.dump
  • backend/settings/graphql.py
  • backend/tests/unit/apps/owasp/admin/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/mutations/__init__.py
  • backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/nodes/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/models/snapshot_subscription_test.py

Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/models/snapshot_subscription.py Outdated
Comment thread backend/tests/unit/apps/owasp/admin/snapshot_subscription_test.py
Comment thread backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 19 files

Confidence score: 2/5

  • In backend/apps/owasp/api/internal/mutations/snapshot_subscription.py, the create subscription path appears to block previously canceled users by only checking record existence, so users can get stuck permanently inactive via GraphQL after canceling — update the logic to allow reactivation (or check active state) before merging.
  • In backend/apps/owasp/api/internal/mutations/snapshot_subscription.py, unsubscribe_by_token does not catch ValidationError for malformed UUID tokens, which can bubble up as an unhandled GraphQL error instead of a controlled response — add UUID validation/error handling and return a safe client-facing error before merging.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
@HarshitVerma109
HarshitVerma109 marked this pull request as draft June 26, 2026 17:43
@HarshitVerma109 HarshitVerma109 added the gsoc2026:harshitverma109 harshitverma109 GSoC 2026 related work label Jun 27, 2026
@HarshitVerma109
HarshitVerma109 force-pushed the feature/snapshot-subscription-graphql branch from 22b8e4b to 5a1831b Compare July 4, 2026 04:25
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

Contribution validation failed:

  • commit_sign_off: One or more commits are missing or have an invalid Signed-off-by trailer.

@HarshitVerma109
HarshitVerma109 force-pushed the feature/snapshot-subscription-graphql branch from 5a1831b to 0f4f87b Compare July 4, 2026 04:31

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py (1)

34-37: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Resolver invocation still bypasses the actual resolver function.

field = SnapshotSubscriptionQuery.__dict__["my_subscription"] returns the StrawberryDjangoField descriptor (post-decoration), not the plain my_subscription function. Calling it directly as field(self.query, info=info) doesn't match how the field wraps/exposes its resolver, so this likely doesn't exercise the real my_subscription body (unauthenticated check, SnapshotSubscription.objects.get, DoesNotExist handling).

This is the same pattern flagged in a previous review of this exact resolver: access the underlying function via base_resolver instead.

🐛 Suggested fix
     def _resolve_my_subscription(self, info):
         """Invoke the underlying resolver for my_subscription."""
         field = SnapshotSubscriptionQuery.__dict__["my_subscription"]
-        return field(self.query, info=info)
+        return field.base_resolver.func(self.query, info=info)

Since the current call may silently pass/fail without ever running the real my_subscription logic, please confirm these tests actually fail/pass for the right reasons (e.g. temporarily break the resolver logic and re-run).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py`
around lines 34 - 37, The test helper for
SnapshotSubscriptionQuery.my_subscription is invoking the StrawberryDjangoField
descriptor directly instead of the underlying resolver, so it may not exercise
the real resolver logic. Update _resolve_my_subscription to call the actual
resolver via the field’s base_resolver on
SnapshotSubscriptionQuery.my_subscription, and make sure the tests validate the
unauthenticated path, SnapshotSubscription.objects.get lookup, and DoesNotExist
handling by exercising the real my_subscription body.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/apps/owasp/api/internal/mutations/snapshot_subscription.py`:
- Around line 59-81: Wrap the project preference replacement logic in
_sync_project_preferences with a transaction so the delete-and-recreate sequence
is atomic, and make sure
create_snapshot_subscription/update_snapshot_subscription paths that call it are
protected as well. Handle IntegrityError at the mutation boundary so
reactivation or updates cannot leave SnapshotSubscription.project_preferences in
a partially applied state if a ProjectSubscriptionPreference.objects.create call
fails.

In `@backend/apps/owasp/api/internal/nodes/project_subscription_preference.py`:
- Around line 21-24: The `ProjectSubscriptionPreference.project` resolver is
using `prefetch_related` for a single ForeignKey, which is less appropriate than
a join-based fetch. Update the `@strawberry_django.field` configuration on
`project` to use `select_related` for the `project` relation instead, keeping
the resolver and `ProjectSubscriptionPreference`/`ProjectNode` signatures
unchanged.

In `@backend/apps/owasp/models/snapshot_subscription.py`:
- Around line 64-65: Remove the stale “Per-project preferences” comment from
snapshot_subscription.py so the section no longer suggests a missing field.
Update the SnapshotSubscription model definition by deleting that header comment
and keeping the surrounding class members aligned with the current schema, since
per-project preferences now belong in ProjectSubscriptionPreference.

In `@backend/tests/unit/apps/owasp/api/internal/queries/chapter_test.py`:
- Around line 136-151: The search_chapters test currently stubs __getitem__
without verifying the slice, so it can pass even if the limit is removed. Update
test_search_chapters_valid_query in ChapterQuery to assert that the ordered
queryset is sliced with SEARCH_CHAPTERS_LIMIT by checking the __getitem__ call
on mock_ordered_qs, while keeping the existing filter and order_by expectations.

---

Duplicate comments:
In
`@backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py`:
- Around line 34-37: The test helper for
SnapshotSubscriptionQuery.my_subscription is invoking the StrawberryDjangoField
descriptor directly instead of the underlying resolver, so it may not exercise
the real resolver logic. Update _resolve_my_subscription to call the actual
resolver via the field’s base_resolver on
SnapshotSubscriptionQuery.my_subscription, and make sure the tests validate the
unauthenticated path, SnapshotSubscription.objects.get lookup, and DoesNotExist
handling by exercising the real my_subscription body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 77b3504b-b851-4fc3-94c1-8db02ec93813

📥 Commits

Reviewing files that changed from the base of the PR and between 22b8e4b and 5a1831b.

⛔ Files ignored due to path filters (1)
  • frontend/src/types/__generated__/graphql.ts is excluded by !**/__generated__/**
📒 Files selected for processing (25)
  • backend/apps/owasp/Makefile
  • backend/apps/owasp/admin/snapshot_subscription.py
  • backend/apps/owasp/api/internal/mutations/__init__.py
  • backend/apps/owasp/api/internal/mutations/snapshot_subscription.py
  • backend/apps/owasp/api/internal/nodes/chapter.py
  • backend/apps/owasp/api/internal/nodes/project_subscription_preference.py
  • backend/apps/owasp/api/internal/nodes/snapshot_subscription.py
  • backend/apps/owasp/api/internal/queries/__init__.py
  • backend/apps/owasp/api/internal/queries/chapter.py
  • backend/apps/owasp/api/internal/queries/snapshot_subscription.py
  • backend/apps/owasp/migrations/0076_add_project_subscription_preference.py
  • backend/apps/owasp/models/__init__.py
  • backend/apps/owasp/models/project_subscription_preference.py
  • backend/apps/owasp/models/snapshot_subscription.py
  • backend/data/nest.dump
  • backend/settings/graphql.py
  • backend/tests/unit/apps/owasp/admin/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/mutations/__init__.py
  • backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/nodes/project_subscription_preference_test.py
  • backend/tests/unit/apps/owasp/api/internal/nodes/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/chapter_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/models/project_subscription_preference_test.py
  • backend/tests/unit/apps/owasp/models/snapshot_subscription_test.py

Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/nodes/project_subscription_preference.py Outdated
Comment thread backend/apps/owasp/models/snapshot_subscription.py Outdated
Comment thread backend/tests/unit/apps/owasp/api/internal/queries/chapter_test.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
backend/apps/owasp/models/snapshot_subscription.py (1)

64-65: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale "Per-project preferences" comment still present.

This section header comment has no corresponding field anymore — per-project preferences now live in ProjectSubscriptionPreference. This was flagged in a previous review round and appears unresolved.

🧹 Proposed cleanup
-    # Per-project preferences
-
     created_at = models.DateTimeField(auto_now_add=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/apps/owasp/models/snapshot_subscription.py` around lines 64 - 65,
Remove the stale “Per-project preferences” section header from
snapshot_subscription.py, since the related data now lives in
ProjectSubscriptionPreference. Update the surrounding class or model definitions
in SnapshotSubscription so the comments only describe fields that still exist,
and keep any remaining section headers aligned with the actual attributes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py`:
- Around line 134-148: Add test coverage for the new project preferences sync
path in both TestCreateSnapshotSubscription and TestUpdateSnapshotSubscription,
since current tests only cover subscribed_chapter_ids and never exercise
input_data.project_preferences. Update the relevant mutation tests to pass
project_preferences and assert that _sync_project_preferences is triggered,
including the delete-and-create flow via
ProjectSubscriptionPreference.objects.create with the expected values. Use the
create_snapshot_subscription and update_snapshot_subscription mutation entry
points to locate the behavior.

---

Duplicate comments:
In `@backend/apps/owasp/models/snapshot_subscription.py`:
- Around line 64-65: Remove the stale “Per-project preferences” section header
from snapshot_subscription.py, since the related data now lives in
ProjectSubscriptionPreference. Update the surrounding class or model definitions
in SnapshotSubscription so the comments only describe fields that still exist,
and keep any remaining section headers aligned with the actual attributes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 44fa69f1-2f8c-4d00-9630-76901f8b255c

📥 Commits

Reviewing files that changed from the base of the PR and between 5a1831b and 0f4f87b.

📒 Files selected for processing (20)
  • backend/apps/owasp/Makefile
  • backend/apps/owasp/admin/snapshot_subscription.py
  • backend/apps/owasp/api/internal/mutations/snapshot_subscription.py
  • backend/apps/owasp/api/internal/nodes/chapter.py
  • backend/apps/owasp/api/internal/nodes/project_subscription_preference.py
  • backend/apps/owasp/api/internal/nodes/snapshot_subscription.py
  • backend/apps/owasp/api/internal/queries/chapter.py
  • backend/apps/owasp/migrations/0076_add_project_subscription_preference.py
  • backend/apps/owasp/models/__init__.py
  • backend/apps/owasp/models/project_subscription_preference.py
  • backend/apps/owasp/models/snapshot_subscription.py
  • backend/data/nest.dump
  • backend/tests/unit/apps/owasp/admin/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/nodes/project_subscription_preference_test.py
  • backend/tests/unit/apps/owasp/api/internal/nodes/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/chapter_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/models/project_subscription_preference_test.py
  • backend/tests/unit/apps/owasp/models/snapshot_subscription_test.py

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 4, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 26 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/src/apps/owasp/api/internal/queries/chapter.py
Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
backend/apps/owasp/api/internal/mutations/snapshot_subscription.py (2)

59-95: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Add a size cap on project_preferences to bound the per-item create loop.

_sync_project_preferences iterates preferences and issues one ProjectSubscriptionPreference.objects.create() per item with no upper bound on list length. Since this is reachable from an authenticated mutation input (CreateSnapshotSubscriptionInput/UpdateSnapshotSubscriptionInput.project_preferences), a client could submit an arbitrarily large list, causing a large burst of synchronous DB writes within a single request/transaction. Consider capping the list length (mirroring the MAX_LIMIT-style constants used elsewhere, e.g. backend/apps/owasp/api/internal/queries/chapter.py) and/or using bulk_create instead of a per-item loop.

♻️ Suggested change
+MAX_PROJECT_PREFERENCES = 100
+
 def _sync_project_preferences(
     subscription: SnapshotSubscription,
     preferences: list[ProjectPreferenceInput],
 ) -> None:
     ...
     project_ids = [pref.project_id for pref in preferences]
+    if len(project_ids) > MAX_PROJECT_PREFERENCES:
+        msg = f"Too many project preferences (max {MAX_PROJECT_PREFERENCES})."
+        raise ValueError(msg)
     if len(project_ids) != len(set(project_ids)):
         msg = "Duplicate project IDs in preferences."
         raise ValueError(msg)

     try:
         with transaction.atomic():
             subscription.project_preferences.all().delete()
-
-            for pref in preferences:
-                ProjectSubscriptionPreference.objects.create(
-                    subscription=subscription,
-                    project_id=pref.project_id,
-                    include_issues=pref.include_issues,
-                    include_pull_requests=pref.include_pull_requests,
-                    include_releases=pref.include_releases,
-                )
+            ProjectSubscriptionPreference.objects.bulk_create(
+                ProjectSubscriptionPreference(
+                    subscription=subscription,
+                    project_id=pref.project_id,
+                    include_issues=pref.include_issues,
+                    include_pull_requests=pref.include_pull_requests,
+                    include_releases=pref.include_releases,
+                )
+                for pref in preferences
+            )
     except IntegrityError:
         msg = "Invalid project ID in preferences."
         raise ValueError(msg) from None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/apps/owasp/api/internal/mutations/snapshot_subscription.py` around
lines 59 - 95, The _sync_project_preferences helper accepts an unbounded
preferences list and creates one ProjectSubscriptionPreference row per item, so
add a hard maximum for project_preferences before the transaction starts. Use
the existing style of MAX_LIMIT-style constants used elsewhere and enforce it in
_sync_project_preferences (or in the SnapshotSubscription mutation input path)
so CreateSnapshotSubscriptionInput and UpdateSnapshotSubscriptionInput reject
oversized lists. If appropriate, replace the per-item
ProjectSubscriptionPreference.objects.create loop with bulk_create to reduce
write overhead while keeping the duplicate-ID and IntegrityError handling
intact.

275-299: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Avoid returning subscription from the token-based unsubscribe mutation. SnapshotSubscriptionNode can reach ProjectNode.recent_issues.author/assignees, and UserNode exposes email, so an unauthenticated caller can request PII. Return only ok/message here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/apps/owasp/api/internal/mutations/snapshot_subscription.py` around
lines 275 - 299, The unsubscribe_by_token mutation is returning a
SnapshotSubscription object that can expose sensitive fields through
SnapshotSubscriptionNode and related resolvers. Update unsubscribe_by_token in
SnapshotSubscriptionResult handling so it returns only ok and message for both
success and failure cases, and remove the subscription payload from the
successful response; keep the token lookup, is_active check, and save logic
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py`:
- Around line 151-186: Add tests for the new validation branches in
`_sync_project_preferences` for both `create_snapshot_subscription` and the
update mutation path. Cover duplicate `project_id` inputs so the duplicate-check
`ValueError` is exercised and assert the mutation returns a failed result with
the validation message. Also add a test that patches
`ProjectSubscriptionPreference.objects.create` to raise `IntegrityError` and
verify it is mapped to `result.ok is False` with the "Invalid project ID in
preferences." message. Use the existing `mutations`,
`CreateSnapshotSubscriptionInput`, and update mutation test setup to locate the
relevant paths.

---

Outside diff comments:
In `@backend/apps/owasp/api/internal/mutations/snapshot_subscription.py`:
- Around line 59-95: The _sync_project_preferences helper accepts an unbounded
preferences list and creates one ProjectSubscriptionPreference row per item, so
add a hard maximum for project_preferences before the transaction starts. Use
the existing style of MAX_LIMIT-style constants used elsewhere and enforce it in
_sync_project_preferences (or in the SnapshotSubscription mutation input path)
so CreateSnapshotSubscriptionInput and UpdateSnapshotSubscriptionInput reject
oversized lists. If appropriate, replace the per-item
ProjectSubscriptionPreference.objects.create loop with bulk_create to reduce
write overhead while keeping the duplicate-ID and IntegrityError handling
intact.
- Around line 275-299: The unsubscribe_by_token mutation is returning a
SnapshotSubscription object that can expose sensitive fields through
SnapshotSubscriptionNode and related resolvers. Update unsubscribe_by_token in
SnapshotSubscriptionResult handling so it returns only ok and message for both
success and failure cases, and remove the subscription payload from the
successful response; keep the token lookup, is_active check, and save logic
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a44d03fd-97c5-458a-9e5c-31af054d9c72

📥 Commits

Reviewing files that changed from the base of the PR and between 0f4f87b and f774a5f.

📒 Files selected for processing (5)
  • backend/apps/owasp/api/internal/mutations/snapshot_subscription.py
  • backend/apps/owasp/api/internal/nodes/project_subscription_preference.py
  • backend/apps/owasp/models/snapshot_subscription.py
  • backend/tests/unit/apps/owasp/api/internal/mutations/snapshot_subscription_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/chapter_test.py
💤 Files with no reviewable changes (1)
  • backend/apps/owasp/models/snapshot_subscription.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jul 4, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

Re-trigger cubic

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 4, 2026
@HarshitVerma109
HarshitVerma109 marked this pull request as ready for review July 4, 2026 06:08
@HarshitVerma109

Copy link
Copy Markdown
Collaborator Author

Hi @arkid15r, please review it and let me know if any changes are required.

@arkid15r arkid15r left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This needs more work:

Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/api/internal/queries/snapshot_subscription.py Outdated
Comment thread backend/apps/owasp/models/project_subscription_preference.py Outdated
@github-actions github-actions Bot added frontend-tests makefile nestbot-tests ci infrastructure docs Improvements or additions to documentation docker Pull requests that update Docker code nestbot labels Aug 17, 2026
@github-actions

Copy link
Copy Markdown

Contribution validation failed:

1 similar comment
@github-actions

Copy link
Copy Markdown

Contribution validation failed:

Signed-off-by: Harsh <harshit1092004@gmail.com>
@HarshitVerma109
HarshitVerma109 force-pushed the feature/snapshot-subscription-graphql branch from 6c8ae84 to 2bf8b4d Compare August 17, 2026 22:12
@github-actions github-actions Bot removed docs Improvements or additions to documentation docker Pull requests that update Docker code nestbot frontend-tests makefile nestbot-tests labels Aug 17, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review completed against the latest diff

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Comment thread backend/src/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/src/apps/owasp/models/snapshot_subscription.py
Comment thread backend/src/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/tests/unit/apps/owasp/api/internal/queries/snapshot_subscription_test.py Outdated
Comment thread backend/src/apps/owasp/api/internal/queries/committee.py Outdated
Comment thread backend/src/apps/owasp/api/internal/mutations/snapshot_subscription.py Outdated
Comment thread backend/tests/unit/apps/owasp/models/snapshot_subscription_test.py
Comment thread backend/src/apps/owasp/api/internal/queries/committee.py
Signed-off-by: Harsh <harshit1092004@gmail.com>
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Aug 17, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 24 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Signed-off-by: Harsh <harshit1092004@gmail.com>
@sonarqubecloud

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

0 issues found across 8 files (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@HarshitVerma109

Copy link
Copy Markdown
Collaborator Author

Hi @arkid15r, please review it and let me know if changes are required.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants