Skip to content

Conversation

@FlexKleks
Copy link
Contributor

@FlexKleks FlexKleks commented Jan 3, 2026

Hey, here's a change to my “PasteFox Share” plugin.

Changes

  • Add custom domain support for paste URLs
  • Add automatic API key validation (falls back to anonymous upload if key is invalid/expired)
  • Add automatic custom domain validation (falls back to pastefox.com if domain is inactive/removed)
  • Add translations for all settings page strings
  • Bump version to 1.1.0

Custom Domains

Users can now select a verified custom domain from their PasteFox account to use for paste URLs. The plugin automatically validates that the domain is still active before using it.

Fallback Behavior

If the configured API key or custom domain becomes unavailable, the plugin gracefully falls back to:

  • Anonymous uploads (7-day expiration, public visibility)
  • Default pastefox.com domain

Summary by CodeRabbit

  • New Features

    • Added Custom Domain support to share pastes from your own verified domain.
    • Domain selection now available in plugin settings (requires API key); verified domains shown, inactive ones disabled.
    • Automatic fallback to pastefox.com if a custom domain is unavailable.
  • Chores

    • Updated plugin version to 1.1.0.
    • Added translations and UI text for custom domain management.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

📝 Walkthrough

Walkthrough

Adds Custom Domain support to PasteFox Share: new config key, translations, README updates, plugin version bump, settings UI to fetch/choose verified domains via API, persistence of selection, and upload logic that validates API key and uses the custom domain or falls back to pastefox.com.

Changes

Cohort / File(s) Summary
Documentation & Manifest
pastefox-share/README.md, pastefox-share/plugin.json
README updated with Custom Domain docs; plugin version bumped from 1.0.01.1.0.
Configuration
pastefox-share/config/pastefox-share.php
New config entry: 'custom_domain' => env('PASTEFOX_CUSTOM_DOMAIN').
Translations
pastefox-share/lang/en/messages.php
Adds translation keys for Custom Domain UI and related helper/error texts (section_custom_domain, custom_domain, custom_domain_none, custom_domain_helper, custom_domain_no_api_key, custom_domain_fetch_error, custom_domain_inactive, etc.).
Settings UI & API integration
pastefox-share/src/PasteFoxSharePlugin.php
Adds HTTP client usage and getCustomDomainOptions() to fetch domains from https://pastefox.com/api/domains; settings form extended with a Select for custom_domain; saveSettings() persists choice to PASTEFOX_CUSTOM_DOMAIN.
Upload logic / Validation
pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php
Adds isApiKeyValid() and getActiveCustomDomain(); upload flow now conditionally includes X-API-Key and uses validated custom domain as base URL or falls back to https://pastefox.com; error handling and conditional payload/header logic added.

Sequence Diagrams

sequenceDiagram
    participant User
    participant Settings as Plugin Settings
    participant API as PasteFox API
    participant Env as Environment
    participant Upload as UploadLogsAction

    User->>Settings: Open settings
    Settings->>API: GET /api/domains (X-API-Key if present)
    API-->>Settings: Domain list (active/inactive)
    Settings->>User: Render domain select (inactive → disabled)
    User->>Settings: Select domain & Save
    Settings->>Env: Persist PASTEFOX_CUSTOM_DOMAIN

    Note over User,Upload: Later — user triggers paste upload
    User->>Upload: Trigger upload
    Upload->>Env: Read api_key & custom_domain
    Upload->>API: Validate API key (isApiKeyValid)
    Upload->>API: Verify configured domain (getActiveCustomDomain)
    alt custom domain valid
        Upload->>API: Create paste using custom domain (X-API-Key header)
    else fallback
        Upload->>API: Create paste at pastefox.com (no X-API-Key)
    end
    API-->>Upload: Returns paste URL
    Upload-->>User: Show paste URL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Add PasteFox Share plugin #63: Original PasteFox Share plugin introduction; modifies the same files/classes extended here (UploadLogsAction, PasteFoxSharePlugin, config, translations, manifest).

Suggested reviewers

  • lajczi
  • rmartinoscar

Poem

🐰 I sniffed the code, a domain to share,
Hopped through settings with API flair,
Verified names in dropdown air,
Fallback ready, so no despair,
Logs land safely — hop, share, and care!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature being added: custom domain support with automatic fallback validation, which aligns with all the changes across configuration, UI, translations, and logic.
✨ Finishing touches
  • 📝 Generate docstrings

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.

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

🧹 Nitpick comments (3)
pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php (2)

149-168: Consider caching API key validation results.

Every log upload triggers an HTTP request to validate the API key. For frequently accessed servers, this creates unnecessary load and latency. API keys rarely change, making them good candidates for caching.

Consider using Laravel's cache to store validation results for a reasonable TTL (e.g., 5-10 minutes):

protected function isApiKeyValid(?string $apiKey): bool
{
    if (blank($apiKey)) {
        return false;
    }

    $cacheKey = 'pastefox_api_key_valid_' . hash('sha256', $apiKey);
    
    return cache()->remember($cacheKey, 300, function () use ($apiKey) {
        try {
            $response = Http::withHeaders([
                'X-API-Key' => $apiKey,
                'Content-Type' => 'application/json',
            ])
                ->timeout(5)
                ->get('https://pastefox.com/api/domains')
                ->json();

            return $response['success'] ?? false;
        } catch (\Exception $e) {
            return false;
        }
    });
}

Note: If you implement the consolidated API call from the previous comment, apply caching to the consolidated method instead.


118-147: Silent failure in domain validation could hide configuration issues.

While graceful fallback is appropriate for availability issues, completely silent failure makes it difficult for administrators to diagnose why their custom domain isn't working (e.g., typo in domain name, domain not activated, API connectivity issues).

Consider logging a warning when the configured domain is invalid or inactive:

protected function getActiveCustomDomain(?string $apiKey): ?string
{
    $configuredDomain = config('pastefox-share.custom_domain');

    if (blank($configuredDomain) || blank($apiKey)) {
        return null;
    }

    try {
        $response = Http::withHeaders([
            'X-API-Key' => $apiKey,
            'Content-Type' => 'application/json',
        ])
            ->timeout(5)
            ->get('https://pastefox.com/api/domains')
            ->json();

        if ($response['success'] ?? false) {
            foreach ($response['domains'] ?? [] as $domain) {
                if ($domain['domain'] === $configuredDomain && ($domain['isActive'] ?? false)) {
                    return $configuredDomain;
                }
            }
+            // Domain configured but not found or inactive
+            logger()->warning("PasteFox custom domain '{$configuredDomain}' is not active, falling back to pastefox.com");
        }
    } catch (\Exception $e) {
-        // Silently fail, fall back to default
+        logger()->warning("Failed to fetch PasteFox domains: {$e->getMessage()}");
    }

    return null;
}

This helps administrators identify configuration issues while maintaining the graceful fallback behavior.

pastefox-share/src/PasteFoxSharePlugin.php (1)

104-140: Add PHPDoc return type annotation to satisfy PHPStan.

The static analysis error indicates the return type lacks a value type specification. Additionally, the Content-Type header is unnecessary for GET requests.

🔎 Proposed fix
+    /**
+     * @return array<string, string>
+     */
     protected function getCustomDomainOptions(): array
     {
         $options = ['' => trans('pastefox-share::messages.custom_domain_none')];

         $apiKey = config('pastefox-share.api_key');
         if (blank($apiKey)) {
             return $options;
         }

         try {
             $response = Http::withHeaders([
                 'X-API-Key' => $apiKey,
-                'Content-Type' => 'application/json',
             ])
                 ->timeout(10)
                 ->get('https://pastefox.com/api/domains')
                 ->json();
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c2ca0f6 and e53dece.

📒 Files selected for processing (6)
  • pastefox-share/README.md
  • pastefox-share/config/pastefox-share.php
  • pastefox-share/lang/en/messages.php
  • pastefox-share/plugin.json
  • pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php
  • pastefox-share/src/PasteFoxSharePlugin.php
🧰 Additional context used
🪛 GitHub Check: PHPStan
pastefox-share/src/PasteFoxSharePlugin.php

[failure] 104-104:
Method FlexKleks\PasteFoxShare\PasteFoxSharePlugin::getCustomDomainOptions() return type has no value type specified in iterable type array.

🪛 markdownlint-cli2 (0.18.1)
pastefox-share/README.md

24-24: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (7)
pastefox-share/plugin.json (1)

5-5: LGTM! Appropriate version bump.

The version increment to 1.1.0 correctly reflects the addition of custom domain support as a new feature.

pastefox-share/config/pastefox-share.php (1)

9-9: LGTM! Configuration entry follows established patterns.

The custom domain configuration is consistent with other optional settings in the file.

pastefox-share/lang/en/messages.php (1)

40-49: LGTM! Comprehensive translation coverage.

The translation keys are well-structured and provide clear, user-friendly messaging for the custom domain feature.

pastefox-share/README.md (2)

22-29: LGTM! Clear configuration documentation.

The updated settings table clearly documents all available configuration options including the new custom domain feature.


38-50: LGTM! Comprehensive custom domain documentation.

The documentation clearly explains:

  • How to set up custom domains
  • The verification process
  • Automatic fallback behavior

This provides users with the information needed to configure and use the feature.

pastefox-share/src/PasteFoxSharePlugin.php (2)

87-100: Well-structured conditional UI behavior.

The custom domain section properly gates functionality based on API key presence—disabling the select and showing appropriate helper text when no API key is configured. The disableOptionWhen pattern using the :disabled suffix cleanly prevents selection of inactive domains while still showing them in the dropdown.


150-150: LGTM!

Persistence of the new setting follows the established pattern. Per the AI summary, runtime validation in UploadLogsAction handles fallback when a configured domain becomes inactive.

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

🧹 Nitpick comments (2)
pastefox-share/src/PasteFoxSharePlugin.php (2)

138-140: Consider logging errors while maintaining graceful fallback.

Silent error handling prevents debugging issues with the API integration. Consider logging the exception while still returning default options for graceful degradation.

💡 Suggested refactor to add logging
 } catch (\Exception $e) {
-    // Silently fail, just return default options
+    \Log::warning('Failed to fetch custom domains from PasteFox API', [
+        'error' => $e->getMessage(),
+    ]);
 }

122-122: Consider extracting the API URL to a constant or config.

Hardcoding the API URL makes it harder to test or support different environments (staging, local development, etc.).

💡 Suggested refactor

Add to your config file:

'api_base_url' => env('PASTEFOX_API_URL', 'https://pastefox.com'),

Then update the code:

-    ->get('https://pastefox.com/api/domains')
+    ->get(config('pastefox-share.api_base_url') . '/api/domains')
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e53dece and d762559.

📒 Files selected for processing (1)
  • pastefox-share/src/PasteFoxSharePlugin.php
🔇 Additional comments (3)
pastefox-share/src/PasteFoxSharePlugin.php (3)

13-13: LGTM!

The Http facade import is correctly added to support the API call in getCustomDomainOptions().


153-153: LGTM!

The persistence of the custom domain setting follows the established pattern and is correctly implemented.


127-136: The logic is not inconsistent. The status field validates that the domain is registered in the PasteFox system (status === 'ACTIVE'), while isActive represents the user's preference to enable or disable the domain in their dashboard settings. These are complementary validation layers—one system-level, one user-level—not redundant checks.

Additionally, the :disabled suffix pattern is the proper Filament framework convention. Line 94 shows ->disableOptionWhen(fn (string $value): bool => str_ends_with($value, ':disabled')), which is the intended API for presenting disabled options in the select field. This is not a data/UI mixing issue but correct framework integration.

Likely an incorrect or invalid review comment.

@Boy132 Boy132 merged commit 39f9c1f into pelican-dev:main Jan 3, 2026
4 checks passed
@Boy132
Copy link
Member

Boy132 commented Jan 3, 2026

For future reference, please create a separate branch for pull requests and don't use main.

@FlexKleks
Copy link
Contributor Author

FlexKleks commented Jan 3, 2026 via email

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants