Skip to content

feat: Add Zendesk connector integration #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

KafilatAdeleke
Copy link

@KafilatAdeleke KafilatAdeleke commented Aug 1, 2025

This commit introduces the Zendesk connector, allowing users to integrate and search their Zendesk tickets.

Key changes include:

  • Backend:
    • Added ZendeskConnector class for API interaction.
    • Updated DocumentType and SearchSourceConnectorType enums.
    • Integrated Zendesk indexing into search_source_connectors_routes.py and connectors_indexing_tasks.py.
    • Added httpx dependency to pyproject.toml.
  • Frontend:
    • Added Zendesk connector to the "Add Connector" page.
    • Implemented Zendesk connector configuration fields in the "Edit Connector" page.
    • Updated biome.json schema version.
    • Updated ModernHeroWithGradients.tsx to include Zendesk in the list of external sources.

closes #220

Description

Motivation and Context

FIX #

Changes Overview

Screenshots

API Changes

  • This PR includes API changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance improvement (non-breaking change which enhances performance)
  • Documentation update
  • Breaking change (fix or feature that would cause existing functionality to change)

Testing

  • I have tested these changes locally
  • I have added/updated unit tests
  • I have added/updated integration tests

Checklist:

  • My code follows the code style of this project
  • My change requires documentation updates
  • I have updated the documentation accordingly
  • My change requires dependency updates
  • I have updated the dependencies accordingly
  • My code builds clean without any errors or warnings
  • All new and existing tests passed

Summary by CodeRabbit

  • New Features

    • Introduced Zendesk connector integration, allowing users to add and configure Zendesk as a data source for ticket and support data.
    • Added dedicated setup and edit pages for Zendesk connectors with form validation and user guidance.
    • Included Zendesk in the connector selection interface under a new "Customer Support" category.
  • Improvements

    • Enhanced connector editing to support Zendesk-specific fields and validation.
    • Updated connector schemas and validation logic to accommodate Zendesk credentials.
  • Dependency Updates

    • Added the httpx package for backend HTTP requests.
  • Other

    • Minor configuration and documentation updates with no user-facing impact.

This commit introduces the Zendesk connector, allowing users to integrate and search their Zendesk tickets.

Key changes include:
- Backend:
  - Added `ZendeskConnector` class for API interaction.
  - Updated `DocumentType` and `SearchSourceConnectorType` enums.
  - Integrated Zendesk indexing into `search_source_connectors_routes.py` and `connectors_indexing_tasks.py`.
  - Added `httpx` dependency to `pyproject.toml`.
- Frontend:
  - Added Zendesk connector to the "Add Connector" page.
  - Implemented Zendesk connector configuration fields in the "Edit Connector" page.
  - Updated `biome.json` schema version.
  - Updated `ModernHeroWithGradients.tsx` to include Zendesk in the list of external sources.
Copy link

vercel bot commented Aug 1, 2025

@KafilatAdeleke is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

coderabbitai bot commented Aug 1, 2025

Walkthrough

This change introduces a Zendesk connector across the backend and frontend. It adds enum values, validation, and migration logic for the new connector type in the backend, implements the connector class for Zendesk API integration, and scaffolds (commented) indexing code. The frontend is updated to support creation, editing, and categorization of Zendesk connectors with appropriate forms, validation, and documentation UI.

Changes

Cohort / File(s) Change Summary
Backend: Zendesk connector implementation
surfsense_backend/app/connectors/zendesk_connector.py
Adds a new ZendeskConnector class for authenticating with and fetching tickets from the Zendesk API, including error handling and pagination.
Backend: Enum and schema updates
surfsense_backend/app/db.py, surfsense_backend/alembic/versions/15_add_zendesk_connector_enums.py
Adds ZENDESK_CONNECTOR to DocumentType and SearchSourceConnectorType enums and provides an Alembic migration to update the database enums accordingly.
Backend: Connector validation
surfsense_backend/app/schemas/search_source_connector.py
Extends validate_config_for_connector_type to require Zendesk-specific configuration fields and validate their presence and non-emptiness for the new connector type.
Backend: Indexing scaffolding
surfsense_backend/app/routes/search_source_connectors_routes.py
Adds (commented out) async functions and endpoint logic for Zendesk connector indexing, following the established pattern for other connectors.
Backend: Dependency and config updates
surfsense_backend/pyproject.toml, docker-compose.override.yml
Adds httpx dependency for async HTTP requests; removes NVIDIA GPU resource reservation from Docker Compose override.
Frontend: Add Zendesk connector UI
surfsense_web/app/dashboard/[search_space_id]/connectors/add/zendesk-connector/page.tsx
Adds a new page for setting up a Zendesk connector, including a validated form, documentation, and UI feedback.
Frontend: Connector category and listing
surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx
Adds a new "Customer Support" category and lists the Zendesk connector in the add connector page.
Frontend: Edit connector UI and validation
surfsense_web/app/dashboard/[search_space_id]/connectors/[connector_id]/edit/page.tsx, surfsense_web/components/editConnector/types.ts, surfsense_web/hooks/useConnectorEditPage.ts
Adds Zendesk-specific fields to the edit connector form, schema, and edit logic, including validation and form state management.
Frontend: Miscellaneous config and content
surfsense_web/components/ModernHeroWithGradients.tsx, surfsense_web/biome.json, surfsense_browser_extension/biome.json, biome.json
Minor content formatting change; updates biome config files to schema 2.1.3 and sets root property.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend
    participant Backend
    participant Zendesk API

    User->>Frontend: Fill Zendesk connector form and submit
    Frontend->>Backend: POST /connectors (Zendesk config)
    Backend->>Backend: Validate config for ZENDESK_CONNECTOR
    Backend->>Backend: Store connector in DB
    Backend-->>Frontend: Success/Failure response
    Frontend-->>User: Show confirmation or error

    User->>Frontend: Initiate ticket indexing (future)
    Frontend->>Backend: Request to index Zendesk tickets
    Backend->>Zendesk API: Fetch tickets (paginated)
    Zendesk API-->>Backend: Return ticket data
    Backend->>Backend: Store tickets, update last indexed
    Backend-->>Frontend: Indexing status
    Frontend-->>User: Show indexing progress/result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Assessment against linked issues

Objective Addressed Explanation
Add a Zendesk Connector (backend: enums, migration, validation, connector class) (#220)
Add a Zendesk Connector (frontend: creation, editing, validation, UI, docs) (#220)
Add Zendesk to connector categories and listing (frontend) (#220)
Add (scaffold) indexing logic for Zendesk connector (backend) (#220)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Remove NVIDIA GPU resource reservation (docker-compose.override.yml) This change is unrelated to the Zendesk connector objectives; it modifies Docker deployment settings.

Possibly related PRs

Poem

A rabbit hopped to Zendesk’s door,
With tickets and tokens, it asked for more.
A connector now links support with ease,
Through forms and fields, it aims to please.
Backend and frontend, both aligned,
In code and docs, Zendesk you’ll find!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23f7278 and 662c982.

📒 Files selected for processing (2)
  • surfsense_backend/app/connectors/zendesk_connector.py (1 hunks)
  • surfsense_backend/app/routes/search_source_connectors_routes.py (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • surfsense_backend/app/routes/search_source_connectors_routes.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • surfsense_backend/app/connectors/zendesk_connector.py
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

recurseml bot commented Aug 1, 2025

✨ No issues found! Your code is sparkling clean! ✨

Need help? Join our Discord for support!
https://discord.gg/qEjHQk64Z9

Copy link

@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: 6

🧹 Nitpick comments (6)
surfsense_web/components/ModernHeroWithGradients.tsx (1)

52-55: Add “Zendesk” to the marketing copy to advertise the new connector

The PR’s main feature is Zendesk integration, but the hero text still omits Zendesk in the external-sources list. Updating this copy keeps the UI consistent with the newly delivered capability.

- external sources such as Search Engines, Slack, Linear, Jira, Confluence, Notion,
- YouTube, GitHub, Discord and more.
+ external sources such as Search Engines, Slack, Linear, Jira, Confluence, Notion,
+ Zendesk, YouTube, GitHub, Discord and more.
docker-compose.override.yml (2)

35-35: Trim trailing whitespace.

Line 35 contains trailing spaces, triggering the YAML-lint warning.
This is purely cosmetic but easy to fix.

-      
+

31-33: Confirm need for GPU-related env vars now that the GPU deploy block is gone.

With the entire deploy.resources.reservations.devices section removed, the backend container is no longer scheduled with GPU-specific constraints. Keeping

- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=compute,utility

may confuse future readers and can cause Docker to complain on hosts without the NVIDIA runtime. Consider deleting these lines unless the container still performs CUDA work.

-      - NVIDIA_VISIBLE_DEVICES=all
-      - NVIDIA_DRIVER_CAPABILITIES=compute,utility
surfsense_web/components/editConnector/types.ts (1)

42-44: Consider adding validation for Zendesk configuration fields.

The Zendesk configuration fields follow the correct naming pattern. Consider adding validation rules for better user experience:

	ZENDESK_SUBDOMAIN: z.string().optional(),
-	ZENDESK_EMAIL: z.string().optional(),
-	ZENDESK_API_TOKEN: z.string().optional(),
+	ZENDESK_EMAIL: z.string().email("Please enter a valid email address").optional(),
+	ZENDESK_API_TOKEN: z.string().min(1, "API token cannot be empty").optional(),
surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx (1)

139-151: Consider using a different icon to distinguish from Jira.

The Zendesk connector implementation looks good and follows the established pattern. However, both Zendesk and Jira use the same IconTicket component, which might cause visual confusion for users.

Consider using a different icon for Zendesk to improve visual distinction:

-				icon: <IconTicket className="h-6 w-6" />,
+				icon: <IconHeadset className="h-6 w-6" />,

Don't forget to add the import:

import {
	IconBook,
	IconBrandDiscord,
	IconBrandGithub,
	IconBrandNotion,
	IconBrandSlack,
	IconBrandWindows,
	IconBrandZoom,
	IconChevronDown,
	IconChevronRight,
+	IconHeadset,
	IconLayoutKanban,
	IconLinkPlus,
	IconMail,
	IconTicket,
	IconWorldWww,
} from "@tabler/icons-react";
surfsense_backend/alembic/versions/15_add_zendesk_connector_enums.py (1)

56-61: Consider enhancing downgrade documentation.

While PostgreSQL doesn't support enum value removal, the downgrade function could provide more detailed guidance for manual cleanup if needed.

 def downgrade() -> None:
     """
-    Downgrade logic not implemented since PostgreSQL
-    does not support removing enum values.
+    Downgrade logic not implemented since PostgreSQL does not support removing enum values.
+    
+    If manual cleanup is required:
+    1. Ensure no database records reference 'ZENDESK_CONNECTOR' enum values
+    2. Manually recreate enum types without the ZENDESK_CONNECTOR value
+    3. Update all dependent tables to use the new enum types
     """
     pass
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f105dd3 and 2532bbf.

📒 Files selected for processing (17)
  • biome.json (1 hunks)
  • docker-compose.override.yml (1 hunks)
  • surfsense_backend/alembic/versions/15_add_zendesk_connector_enums.py (1 hunks)
  • surfsense_backend/app/connectors/zendesk_connector.py (1 hunks)
  • surfsense_backend/app/db.py (2 hunks)
  • surfsense_backend/app/routes/search_source_connectors_routes.py (3 hunks)
  • surfsense_backend/app/schemas/search_source_connector.py (1 hunks)
  • surfsense_backend/app/tasks/connectors_indexing_tasks.py (2 hunks)
  • surfsense_backend/pyproject.toml (1 hunks)
  • surfsense_browser_extension/biome.json (1 hunks)
  • surfsense_web/app/dashboard/[search_space_id]/connectors/[connector_id]/edit/page.tsx (1 hunks)
  • surfsense_web/app/dashboard/[search_space_id]/connectors/add/page.tsx (1 hunks)
  • surfsense_web/app/dashboard/[search_space_id]/connectors/add/zendesk-connector/page.tsx (1 hunks)
  • surfsense_web/biome.json (1 hunks)
  • surfsense_web/components/ModernHeroWithGradients.tsx (1 hunks)
  • surfsense_web/components/editConnector/types.ts (1 hunks)
  • surfsense_web/hooks/useConnectorEditPage.ts (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
surfsense_backend/app/connectors/zendesk_connector.py (1)
surfsense_web/lib/api.ts (1)
  • get (82-94)
surfsense_backend/app/schemas/search_source_connector.py (1)
surfsense_backend/app/db.py (1)
  • SearchSourceConnectorType (50-61)
surfsense_web/app/dashboard/[search_space_id]/connectors/[connector_id]/edit/page.tsx (1)
surfsense_web/components/editConnector/EditSimpleTokenForm.tsx (1)
  • EditSimpleTokenForm (24-49)
🪛 YAMLlint (1.37.1)
docker-compose.override.yml

[error] 35-35: trailing spaces

(trailing-spaces)

🔇 Additional comments (21)
biome.json (1)

2-2: Schema version bump looks good

Updating to 2.1.3 keeps the config current with Biome’s latest tooling. No other config changes are introduced, so no action needed.

surfsense_web/biome.json (1)

2-3: root: false + schema bump are sensible

Setting root to false allows the project-level configuration to take precedence, and the schema bump keeps the file in sync with the root config. Looks consistent with the other directories.

surfsense_browser_extension/biome.json (1)

2-3: Consistent Biome update

Matches the pattern in surfsense_web; no issues spotted.

surfsense_backend/pyproject.toml (1)

38-38: httpx dependency addition verified

  • PyPI releases confirm 0.27.0 exists (with patches up to 0.27.2); the latest httpx is 0.28.1, so >=0.27.0 will pull in current stable releases.
  • GitHub security advisories report a single critical issue affecting only <0.23.0, which is patched in 0.23.0—versions >=0.27.0 are not impacted.

✅ No known vulnerabilities for httpx >= 0.27.0; this dependency addition can be approved.

surfsense_backend/app/db.py (3)

47-47: LGTM! Enum addition follows existing pattern.

The ZENDESK_CONNECTOR addition to DocumentType enum is consistent with other connector types.


51-51: Good cleanup of the comment typo.

Fixed the capitalization in "RETURNed" - nice attention to detail.


61-61: LGTM! SearchSourceConnectorType enum properly extended.

The ZENDESK_CONNECTOR addition maintains consistency with existing connector types and aligns with the database migration requirements.

surfsense_backend/app/schemas/search_source_connector.py (1)

170-189: LGTM! Zendesk validation follows established patterns.

The validation logic for the Zendesk connector is well-implemented:

  • Properly validates all three required configuration fields
  • Follows the same pattern as other multi-field connectors (Jira, Confluence)
  • Includes appropriate empty value checks for security
  • Error messages are descriptive and consistent

The implementation correctly ensures that sensitive credentials cannot be empty and that only expected configuration keys are present.

surfsense_web/app/dashboard/[search_space_id]/connectors/[connector_id]/edit/page.tsx (1)

253-278: LGTM! Consistent implementation following established patterns.

The Zendesk connector configuration form follows the same pattern as other multi-field connectors (Jira, Confluence) with appropriate field names, descriptions, and validation. The implementation is clean and consistent with the existing codebase.

surfsense_backend/alembic/versions/15_add_zendesk_connector_enums.py (1)

18-53: LGTM! Safe migration implementation with proper conditional logic.

The migration properly uses conditional PL/pgSQL blocks to safely add enum values without causing errors if they already exist. The approach handles both required enum types correctly.

surfsense_web/hooks/useConnectorEditPage.ts (4)

55-57: LGTM! Consistent form field initialization.

The Zendesk form fields are properly initialized in the default values, following the same pattern as other connectors.


84-86: LGTM! Proper form reset logic.

The form reset logic correctly populates Zendesk fields from the connector configuration, maintaining consistency with the existing pattern.


312-333: LGTM! Consistent validation and save logic.

The Zendesk connector case follows the exact same pattern as Jira and Confluence connectors with proper validation, error handling, and configuration object creation.


396-399: LGTM! Proper form state reset after successful save.

The form values are correctly reset to the saved configuration values after a successful update, maintaining consistency with other connector types.

surfsense_web/app/dashboard/[search_space_id]/connectors/add/zendesk-connector/page.tsx (3)

53-95: LGTM! Well-structured component with proper form handling.

The component follows React best practices with proper form validation, error handling, loading states, and user feedback. The integration with the createConnector hook is implemented correctly.


113-235: LGTM! Excellent user experience with clear form layout.

The tabbed interface provides a clean separation between the connection form and documentation. Form fields have appropriate labels, descriptions, and placeholders. The alert about API token requirements is helpful for users.


238-281: LGTM! Helpful documentation with clear setup instructions.

The documentation tab provides clear, step-by-step instructions for generating a Zendesk API token. The accordion layout keeps the information organized and accessible.

surfsense_backend/app/routes/search_source_connectors_routes.py (3)

46-46: LGTM!

The import is correctly placed and follows the established pattern with other connector indexing functions.


492-505: LGTM!

The Zendesk connector handling follows the established pattern perfectly, with proper logging, background task scheduling, and consistent parameter passing.


981-1035: Approved: Zendesk indexing helpers and signature verified

The index_zendesk_tickets function is present in surfsense_backend/app/tasks/connectors_indexing_tasks.py with the following signature, which matches its invocation in your new helpers:

  • session: AsyncSession
  • connector_id: int
  • search_space_id: int
  • user_id: str
  • start_date: str | None = None
  • end_date: str | None = None
  • update_last_indexed: bool = True

No further changes are required—your wrapper and main indexing functions follow the established pattern, with proper session handling, logging, error management, and timestamp updates.

surfsense_backend/app/tasks/connectors_indexing_tasks.py (1)

18-18: LGTM!

The import is correctly placed with other connector imports in alphabetical order.

Comment on lines 4 to 8
class ZendeskConnector:
def __init__(self, subdomain: str, email: str, api_token: str):
self.base_url = f"https://{subdomain}.zendesk.com/api/v2"
self.auth = (f"{email}/token", api_token)

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add parameter validation for constructor arguments.

The constructor should validate that the required parameters are not empty and that the subdomain follows expected format patterns to prevent runtime errors.

 class ZendeskConnector:
     def __init__(self, subdomain: str, email: str, api_token: str):
+        if not subdomain or not subdomain.strip():
+            raise ValueError("Subdomain cannot be empty")
+        if not email or not email.strip():
+            raise ValueError("Email cannot be empty") 
+        if not api_token or not api_token.strip():
+            raise ValueError("API token cannot be empty")
+        
         self.base_url = f"https://{subdomain}.zendesk.com/api/v2"
         self.auth = (f"{email}/token", api_token)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class ZendeskConnector:
def __init__(self, subdomain: str, email: str, api_token: str):
self.base_url = f"https://{subdomain}.zendesk.com/api/v2"
self.auth = (f"{email}/token", api_token)
class ZendeskConnector:
def __init__(self, subdomain: str, email: str, api_token: str):
if not subdomain or not subdomain.strip():
raise ValueError("Subdomain cannot be empty")
if not email or not email.strip():
raise ValueError("Email cannot be empty")
if not api_token or not api_token.strip():
raise ValueError("API token cannot be empty")
self.base_url = f"https://{subdomain}.zendesk.com/api/v2"
self.auth = (f"{email}/token", api_token)
🤖 Prompt for AI Agents
In surfsense_backend/app/connectors/zendesk_connector.py around lines 4 to 8,
the constructor lacks validation for its parameters. Add checks to ensure
subdomain, email, and api_token are not empty or None. Additionally, validate
that the subdomain matches expected format patterns (e.g., allowed characters
and length). Raise appropriate exceptions if validations fail to prevent runtime
errors later.

Comment on lines 2704 to 2712
async def index_zendesk_tickets(
session: AsyncSession,
connector_id: int,
search_space_id: int,
user_id: str,
start_date: str | None = None,
end_date: str | None = None,
update_last_indexed: bool = True,
) -> tuple[int, str | None]:
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using date parameters for filtering tickets.

The start_date and end_date parameters are accepted but never used in the function implementation. Unlike other indexing functions in this file, the Zendesk implementation doesn't filter tickets by date range. This could lead to performance issues with large ticket volumes and inconsistent behavior compared to other connectors.

Consider implementing date filtering for Zendesk tickets:

async def index_zendesk_tickets(
    session: AsyncSession,
    connector_id: int,
    search_space_id: int,
    user_id: str,
    start_date: str | None = None,
    end_date: str | None = None,
    update_last_indexed: bool = True,
) -> tuple[int, str | None]:
    """
    Index Zendesk tickets.

    Args:
        session: Database session
        connector_id: ID of the Zendesk connector
        search_space_id: ID of the search space to store documents in
+       user_id: User ID
+       start_date: Start date for indexing (YYYY-MM-DD format)
+       end_date: End date for indexing (YYYY-MM-DD format)
        update_last_indexed: Whether to update the last_indexed_at timestamp (default: True)

    Returns:
        Tuple containing (number of documents indexed, error message or None)
    """

Additionally, implement date range calculation and pass it to the get_tickets() method similar to other connectors.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In surfsense_backend/app/tasks/connectors_indexing_tasks.py around lines 2704 to
2712, the start_date and end_date parameters are defined but not used to filter
Zendesk tickets, which can cause performance issues and inconsistency. Modify
the function to calculate the date range based on these parameters and pass this
date range to the get_tickets() method to filter tickets accordingly, following
the pattern used in other connector indexing functions.

Comment on lines 2827 to 2829
if not all([ticket_id, ticket_subject, ticket_description]):
documents_skipped += 1
continue
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add logging for skipped tickets.

When tickets are skipped due to missing required fields, there's no logging to track which tickets were skipped or why. This makes debugging and auditing difficult.

if not all([ticket_id, ticket_subject, ticket_description]):
+    logger.warning(
+        f"Skipping ticket with missing data - ID: {ticket_id or 'None'}, "
+        f"Subject: {ticket_subject or 'None'}, "
+        f"Description: {'Present' if ticket_description else 'None'}"
+    )
    documents_skipped += 1
    continue
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if not all([ticket_id, ticket_subject, ticket_description]):
documents_skipped += 1
continue
if not all([ticket_id, ticket_subject, ticket_description]):
logger.warning(
f"Skipping ticket with missing data - ID: {ticket_id or 'None'}, "
f"Subject: {ticket_subject or 'None'}, "
f"Description: {'Present' if ticket_description else 'None'}"
)
documents_skipped += 1
continue
🤖 Prompt for AI Agents
In surfsense_backend/app/tasks/connectors_indexing_tasks.py around lines 2827 to
2829, add logging to record when tickets are skipped due to missing required
fields. Modify the code inside the if condition to log which ticket is being
skipped and specify which required fields are missing before incrementing
documents_skipped and continuing. Use an appropriate logger to output this
information for better debugging and auditing.

Comment on lines 2846 to 2849
user_llm = await get_user_long_context_llm(session, user_id)
if not user_llm:
documents_skipped += 1
continue
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add logging when LLM is not configured.

Similar to the missing fields issue, when tickets are skipped due to missing LLM configuration, there's no logging to indicate this problem.

user_llm = await get_user_long_context_llm(session, user_id)
if not user_llm:
+    logger.error(f"No long context LLM configured for user {user_id}")
    documents_skipped += 1
    continue
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
user_llm = await get_user_long_context_llm(session, user_id)
if not user_llm:
documents_skipped += 1
continue
user_llm = await get_user_long_context_llm(session, user_id)
if not user_llm:
logger.error(f"No long context LLM configured for user {user_id}")
documents_skipped += 1
continue
🤖 Prompt for AI Agents
In surfsense_backend/app/tasks/connectors_indexing_tasks.py around lines 2846 to
2849, add a logging statement when user_llm is not configured and tickets are
skipped. This log should clearly indicate that the skip is due to missing LLM
configuration, helping to track and debug such cases. Use the existing logger to
output a warning or info message before continuing the loop.

Comment on lines +41 to +48
const zendeskConnectorFormSchema = z.object({
name: z.string().min(3, {
message: "Connector name must be at least 3 characters.",
}),
subdomain: z.string().min(3, { message: "Subdomain must be at least 3 characters." }),
email: z.string().email({ message: "Invalid email address." }),
api_token: z.string().min(20, { message: "API token appears to be too short." }),
});
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify API token length validation.

The schema requires API tokens to be at least 20 characters, but Zendesk API tokens may have different length requirements. Consider verifying the actual token format and length requirements.


🌐 Web query:

What is the typical length and format of Zendesk API tokens?

💡 Result:

A typical Zendesk API token is a randomly generated string used for authenticating API requests, with the following format and length: it consists of 40 alphanumeric characters (letters and numbers) without special characters or separators[4][6][7][9]. For example:

6wiIBWbGkBMo1mRDMuVwkw1EPsNkeUj95PIz2akv

This token is used in basic authentication, concatenated with an email address and the literal word “token” as shown:

{email_address}/token:{api_token}

When encoding credentials for the Authorization header, the string [email protected]/token:6wiIBWbGkBMo1mRDMuVwkw1EPsNkeUj95PIz2akv (where the part after the colon is the API token) is base64 encoded[4][7].

Key points:

  • Length: Always exactly 40 characters.
  • Format: Alphanumeric, case-sensitive.
  • No separators or special formatting within the token itself.

Note: Zendesk also supports other token types (OAuth, JWT), but the classic API token for basic authentication described above always follows this 40-character format[4][9].

Citations:


Enforce exact 40-character alphanumeric API token

The official Zendesk API token is always exactly 40 alphanumeric characters (case-sensitive, no separators). Update the Zod schema accordingly:

• File: surfsense_web/app/dashboard/[search_space_id]/connectors/add/zendesk-connector/page.tsx
• Around lines 41–48 (the api_token field)

Suggested diff:

- api_token: z.string().min(20, { message: "API token appears to be too short." }),
+ api_token: z
+   .string()
+   .length(40, { message: "API token must be exactly 40 characters." })
+   .regex(/^[A-Za-z0-9]+$/, { message: "API token must be alphanumeric." }),

This ensures strict validation against the 40-character, alphanumeric format mandated by Zendesk.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const zendeskConnectorFormSchema = z.object({
name: z.string().min(3, {
message: "Connector name must be at least 3 characters.",
}),
subdomain: z.string().min(3, { message: "Subdomain must be at least 3 characters." }),
email: z.string().email({ message: "Invalid email address." }),
api_token: z.string().min(20, { message: "API token appears to be too short." }),
});
const zendeskConnectorFormSchema = z.object({
name: z.string().min(3, {
message: "Connector name must be at least 3 characters.",
}),
subdomain: z.string().min(3, { message: "Subdomain must be at least 3 characters." }),
email: z.string().email({ message: "Invalid email address." }),
api_token: z
.string()
.length(40, { message: "API token must be exactly 40 characters." })
.regex(/^[A-Za-z0-9]+$/, { message: "API token must be alphanumeric." }),
});
🤖 Prompt for AI Agents
In
surfsense_web/app/dashboard/[search_space_id]/connectors/add/zendesk-connector/page.tsx
around lines 41 to 48, the api_token field currently validates only a minimum
length of 20 characters. Update this validation to enforce that the api_token is
exactly 40 characters long and contains only alphanumeric characters (both
uppercase and lowercase). Use a regex pattern in the Zod schema to strictly
match 40 alphanumeric characters without any separators.

@MODSetter
Copy link
Owner

@KafilatAdeleke Hey, I just merged the other PR. Could you resolve the merge conflicts and let me know once it's done? I’ll test and merge it after that. Thanks for all your hard work so far! 👍

Copy link

@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: 1

🧹 Nitpick comments (1)
surfsense_backend/app/connectors/zendesk_connector.py (1)

7-11: Enhance parameter validation beyond basic truthy checks.

While the basic validation addresses the previous concern about empty parameters, consider adding format validation for better robustness:

 def __init__(self, subdomain: str, email: str, api_token: str):
     if not subdomain or not email or not api_token:
         raise ValueError("Subdomain, email, and API token cannot be empty.")
+    if not subdomain.strip() or ' ' in subdomain:
+        raise ValueError("Subdomain must be a valid string without spaces")
+    if '@' not in email or '.' not in email.split('@')[-1]:
+        raise ValueError("Email must be a valid email address")
+    if len(api_token.strip()) < 10:
+        raise ValueError("API token appears to be too short")
     self.base_url = f"https://{subdomain}.zendesk.com/api/v2"
     self.auth = (f"{email}/token", api_token)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2532bbf and 23f7278.

📒 Files selected for processing (2)
  • surfsense_backend/app/connectors/zendesk_connector.py (1 hunks)
  • surfsense_web/components/editConnector/types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • surfsense_web/components/editConnector/types.ts
🔇 Additional comments (1)
surfsense_backend/app/connectors/zendesk_connector.py (1)

1-3: LGTM!

The imports are clean and appropriately used throughout the implementation.

@MODSetter MODSetter moved this from Backlog to In review in SurfSense August RoadMap Aug 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In review
Development

Successfully merging this pull request may close these issues.

Add a Zendesk Connector
2 participants