Skip to content

Conversation

@arifulhoque7
Copy link
Contributor

@arifulhoque7 arifulhoque7 commented Dec 24, 2025

Fix REST API 401 authentication errors by adding nonce middleware

  • Add restNonce to weDocsAdminVars in Assets.php
  • Configure apiFetch nonce middleware in docs and settings controls
  • Remove duplicate adminUrl and hasManageCap entries in Assets.php
  • Import apiFetch in aiService.js and convert WordPress REST API calls
  • Ensures proper authentication for all REST API requests in admin

Summary by CodeRabbit

Release Notes

  • Improvements
    • Streamlined REST API authentication and security
    • Enhanced error handling with clearer messages for AI-related operations
    • Improved consistency in API response handling across the application

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

Walkthrough

Adds REST API nonce middleware authentication setup across control files. Migrates AI service API calls from native fetch to WordPress apiFetch with updated endpoint paths. Improves error handling and response normalization in API operations while maintaining backward compatibility.

Changes

Cohort / File(s) Summary
REST API Nonce Middleware Setup
src/data/docs/controls.js, src/data/settings/controls.js
Conditionally initializes apiFetch nonce middleware at module load when window.weDocsAdminVars.restNonce is present. Authentication middleware now applies to downstream API requests. No changes to existing control signatures.
AI Service API Migration
src/utils/aiService.js
Replaces native fetch with WordPress apiFetch across all AI operations. Updates endpoint paths to /wp/v2/docs/ format. Refactors getAiSettings and generateContent with enhanced error handling, try-catch blocks, and consistent response formatting (content/usage structure). Simplifies nonce and URL handling via apiFetch integration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Need Testing, Needs Review

Suggested reviewers

  • iftakharul-islam

Poem

🐰 Hops through the code with glee,
WordPress apiFetch flows so free,
Nonce middleware stands tall and true,
API calls refreshed, authentication too! 🔐
Errors handled with rabbit care,
Well-hopped changes everywhere! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change in the pull request, which is configuring nonce middleware to fix REST API authentication errors across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • 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

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

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

Caution

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

⚠️ Outside diff range comments (1)
src/utils/aiService.js (1)

173-231: Critical: Broken error handling with unreachable code and undefined variables.

The error handling in generateContent is fundamentally broken after the migration to apiFetch:

  1. Undefined response (lines 189, 202, 212): The response variable from the old fetch() call no longer exists. apiFetch throws errors directly rather than returning a Response object.
  2. Undeclared errorData (line 192): Used before declaration, causing a ReferenceError.
  3. Unreachable code (lines 222-228): This block comes after the catch ends and will never execute since the try block returns at line 184.
🔎 Proposed fix
         try {
             const data = await apiFetch({
                 path: '/wp/v2/docs/ai/generate',
                 method: 'POST',
                 data: requestBody
             });

             // Return in format expected by callers
             return {
                 content: data.content || '',
                 usage: data.usage || null
             };
         } catch (error) {
-            let errorMessage = __('AI content generation failed. Please try again.', 'wedocs');
-
-            try {
-                const responseText = await response.text();
-
-                if (responseText.trim().startsWith('{')) {
-                    errorData = JSON.parse(responseText);
-                    // Use the message from the API, which should already be user-friendly
-                    errorMessage = errorData.message || errorData.code || errorMessage;
-
-                    // Clean up HTML error messages (WordPress fatal errors)
-                    if (errorMessage.includes('<p>') || errorMessage.includes('critical error')) {
-                        errorMessage = __('A server error occurred. Please try again or contact support if the problem persists.', 'wedocs');
-                    }
-                } else {
-                    // For non-JSON responses, provide user-friendly message
-                    if (response.status === 500) {
-                        errorMessage = __('A server error occurred. Please try again.', 'wedocs');
-                    } else if (response.status === 403) {
-                        errorMessage = __('You do not have permission to perform this action.', 'wedocs');
-                    } else {
-                        errorMessage = __('An error occurred. Please try again.', 'wedocs');
-                    }
-                }
-            } catch (parseError) {
-                // If we can't parse the error, provide a generic user-friendly message
-                if (response.status === 500) {
-                    errorMessage = __('A server error occurred. Please try again.', 'wedocs');
-                } else {
-                    errorMessage = __('An error occurred. Please try again.', 'wedocs');
-                }
-            }
-
-            throw new Error(errorMessage);
+            // apiFetch already parses error responses and provides error.message
+            let errorMessage = error.message || __('AI content generation failed. Please try again.', 'wedocs');
+
+            // Clean up HTML error messages (WordPress fatal errors)
+            if (errorMessage.includes('<p>') || errorMessage.includes('critical error')) {
+                errorMessage = __('A server error occurred. Please try again or contact support if the problem persists.', 'wedocs');
+            }
+
+            throw new Error(errorMessage);
         }
-
-        const data = await response.json();
-
-        // Return in format expected by callers
-        return {
-            content: data.content || '',
-            usage: data.usage || null
-        };
     } catch (error) {
         throw error;
     }
🧹 Nitpick comments (2)
src/data/settings/controls.js (1)

3-6: Potential duplicate nonce middleware registration.

This middleware setup is duplicated in src/data/docs/controls.js (lines 3-6). If both modules are loaded on the same page, apiFetch.use() will register the nonce middleware twice, which adds unnecessary overhead to every request.

Consider extracting this setup into a shared initialization module that ensures the middleware is registered only once (e.g., using a flag or a dedicated bootstrap file).

🔎 Proposed approach: shared initialization

Create a shared module like src/utils/apiInit.js:

import apiFetch from '@wordpress/api-fetch';

let initialized = false;

export function initApiFetch() {
  if (initialized) return;
  
  if (typeof window.weDocsAdminVars !== 'undefined' && window.weDocsAdminVars.restNonce) {
    apiFetch.use(apiFetch.createNonceMiddleware(window.weDocsAdminVars.restNonce));
  }
  
  initialized = true;
}

Then import and call initApiFetch() in each controls file.

src/utils/aiService.js (1)

341-366: Inconsistent API call approach: makeApiCall still uses native fetch.

While generateContent was migrated to apiFetch, this method still uses native fetch with manual nonce handling. This creates inconsistency:

  • Uses weDocsEditorVars.nonce here vs weDocsAdminVars.restNonce in the middleware
  • Requires manual X-WP-Nonce header and credentials: 'include'
  • Uses full /wp-json/ prefix instead of relative path

Consider migrating this method to apiFetch as well for consistency. If weDocsEditorVars context is required, you may need to register a nonce middleware for it or verify that weDocsAdminVars.restNonce is available in the editor context.

🔎 Proposed refactor to use apiFetch
 async makeApiCall(provider, apiKey, endpoint, payload, model = null) {
     // Extract options from payload (provider-specific payloads vary)
     const options = this.extractOptionsFromPayload(provider, payload);

-    // Use WordPress REST API endpoint instead of direct API calls
-    const restUrl = '/wp-json/wp/v2/docs/ai/generate';
-
-    // Get nonce from localized script
-    const nonce = window.weDocsEditorVars?.nonce || '';
-
-    const response = await fetch(restUrl, {
+    const response = await apiFetch({
+        path: '/wp/v2/docs/ai/generate',
         method: 'POST',
-        credentials: 'include', // Include cookies for authentication
-        headers: {
-            'Content-Type': 'application/json',
-            'X-WP-Nonce': nonce
-        },
-        body: JSON.stringify({
+        data: {
             prompt: options.prompt,
             provider: provider,
             model: model || options.model,
             maxTokens: options.maxTokens || 2000,
             temperature: options.temperature || 0.7,
             systemPrompt: options.systemPrompt
-        })
+        }
     });

-    if (!response.ok) {
-        // ... error handling ...
-    }
-
-    const data = await response.json();
-
-    // Return in format expected by parseResponse
-    return data;
+    return response;
 }

Note: This would require ensuring the nonce middleware is registered in the editor context as well.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05da333 and deb9d4a.

📒 Files selected for processing (3)
  • src/data/docs/controls.js
  • src/data/settings/controls.js
  • src/utils/aiService.js
🧰 Additional context used
🧬 Code graph analysis (1)
src/utils/aiService.js (3)
src/components/Settings/index.js (1)
  • settings (18-21)
assets/js/frontend.js (1)
  • data (163-166)
src/editor/AiDocWriterModal.js (1)
  • error (37-37)
🔇 Additional comments (3)
src/data/docs/controls.js (1)

3-6: Nonce middleware setup is correct but duplicated.

This is identical to the setup in src/data/settings/controls.js. The implementation is correct for enabling authenticated REST API calls. See the comment on the other file regarding consolidation to avoid duplicate registrations.

src/utils/aiService.js (2)

17-17: Good addition of apiFetch import.

The import of apiFetch aligns with the PR objective to use WordPress's authenticated API fetch mechanism.


74-81: LGTM - Simplified settings fetch.

The migration from native fetch to apiFetch removes boilerplate and leverages the nonce middleware for authentication.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants