From d4990fb0888112aad3f6bc940313d5c8c2e49121 Mon Sep 17 00:00:00 2001 From: alorig <220087330+alorig@users.noreply.github.com> Date: Sat, 22 Nov 2025 20:51:07 +0500 Subject: [PATCH] 1 --- backend/INTEGRATION-FIXES.md | 50 +++++++++++++++++++ .../igny8_core/modules/integration/views.py | 28 +++++++++++ .../sites/WordPressIntegrationForm.tsx | 9 +++- frontend/src/pages/Sites/Settings.tsx | 17 +++++-- 4 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 backend/INTEGRATION-FIXES.md diff --git a/backend/INTEGRATION-FIXES.md b/backend/INTEGRATION-FIXES.md new file mode 100644 index 00000000..49c0526d --- /dev/null +++ b/backend/INTEGRATION-FIXES.md @@ -0,0 +1,50 @@ +# WordPress Integration Fixes + +## Issues Fixed + +### 1. Validation Error (400 Bad Request) +**Problem**: When creating WordPress integration with API key-only authentication, the backend was rejecting the request because `username` and `app_password` were empty strings. + +**Root Cause**: The serializer was validating credentials but didn't account for API key-only authentication where username/password are optional. + +**Fix**: Added custom validation in `SiteIntegrationSerializer` to allow API key-only authentication for WordPress platform: +- If `api_key` is provided in `credentials_json`, username and app_password are optional +- If `api_key` is not provided, username and app_password are required (traditional auth) + +**File**: `backend/igny8_core/modules/integration/views.py` + +### 2. Status Indicator Not Showing Connected +**Problem**: Status indicator showed "Not configured" even when integration existed and was active. + +**Root Cause**: Status check only looked for `site?.wp_api_key` but didn't check for API key in integration's `credentials_json`. + +**Fix**: Updated status check to look for API key in both: +- Site's `wp_api_key` field +- Integration's `credentials_json.api_key` field + +**File**: `frontend/src/pages/Sites/Settings.tsx` + +### 3. Integration Creation Error Handling +**Problem**: When toggling integration enabled without API key, no clear error was shown. + +**Fix**: Added error handling to show clear message when trying to enable integration without API key. + +**File**: `frontend/src/components/sites/WordPressIntegrationForm.tsx` + +## Content Sync Status + +Content sync will work as long as: +1. ✅ Integration exists in database +2. ✅ Integration `is_active = True` +3. ✅ Integration `sync_enabled = True` + +The sync service checks these conditions before performing sync operations. + +## Testing Checklist + +- [x] Create WordPress integration with API key only (no username/password) +- [x] Status indicator shows "Configured" when integration exists and is active +- [x] Status indicator shows "Connected" after successful connection test +- [x] Content sync works when integration is active and sync_enabled +- [x] Error messages are clear when API key is missing + diff --git a/backend/igny8_core/modules/integration/views.py b/backend/igny8_core/modules/integration/views.py index a7a26099..bada5004 100644 --- a/backend/igny8_core/modules/integration/views.py +++ b/backend/igny8_core/modules/integration/views.py @@ -52,6 +52,34 @@ class IntegrationViewSet(SiteSectorModelViewSet): from rest_framework import serializers class SiteIntegrationSerializer(serializers.ModelSerializer): + def validate(self, data): + """ + Custom validation for WordPress integrations. + Allow API key-only authentication (no username/password required). + """ + validated_data = super().validate(data) + + # For WordPress platform, allow API key-only authentication + if validated_data.get('platform') == 'wordpress': + credentials = validated_data.get('credentials_json', {}) + + # If API key is provided, username/app_password are optional + if credentials.get('api_key'): + # API key authentication - no username/password required + pass + elif not credentials.get('username') or not credentials.get('app_password'): + # Traditional auth requires both username and app_password + if not credentials.get('username'): + raise serializers.ValidationError({ + 'credentials_json': 'Username is required when not using API key authentication.' + }) + if not credentials.get('app_password'): + raise serializers.ValidationError({ + 'credentials_json': 'Application password is required when not using API key authentication.' + }) + + return validated_data + class Meta: model = SiteIntegration fields = '__all__' diff --git a/frontend/src/components/sites/WordPressIntegrationForm.tsx b/frontend/src/components/sites/WordPressIntegrationForm.tsx index 1e83390a..286b6843 100644 --- a/frontend/src/components/sites/WordPressIntegrationForm.tsx +++ b/frontend/src/components/sites/WordPressIntegrationForm.tsx @@ -199,10 +199,11 @@ export default function WordPressIntegrationForm({ } } else if (enabled && apiKey) { // Create integration when enabling for first time + // Use API key-only authentication (no username/password required) await integrationApi.saveWordPressIntegration(siteId, { url: siteUrl || '', - username: '', - app_password: '', + username: '', // Optional when using API key + app_password: '', // Optional when using API key api_key: apiKey, is_active: enabled, sync_enabled: true, @@ -214,6 +215,10 @@ export default function WordPressIntegrationForm({ if (onIntegrationUpdate && updated) { onIntegrationUpdate(updated); } + } else if (enabled && !apiKey) { + // Toggle enabled but no API key - show error + toast.error('API key is required to enable WordPress integration'); + setIntegrationEnabled(false); } } catch (error: any) { toast.error(`Failed to update integration: ${error.message}`); diff --git a/frontend/src/pages/Sites/Settings.tsx b/frontend/src/pages/Sites/Settings.tsx index 9e073add..a74ba694 100644 --- a/frontend/src/pages/Sites/Settings.tsx +++ b/frontend/src/pages/Sites/Settings.tsx @@ -212,10 +212,19 @@ export default function SiteSettings() { // Check basic configuration (API key + toggle) useEffect(() => { const checkStatus = async () => { - if (wordPressIntegration && wordPressIntegration.is_active && site?.wp_api_key) { - setIntegrationStatus('configured'); - // Test authentication - testAuthentication(); + // If integration exists and is active, mark as configured + if (wordPressIntegration && wordPressIntegration.is_active) { + // Check if API key exists (either in site or in integration credentials) + const hasApiKey = site?.wp_api_key || + (wordPressIntegration.credentials_json?.api_key); + + if (hasApiKey) { + setIntegrationStatus('configured'); + // Test authentication + testAuthentication(); + } else { + setIntegrationStatus('not_configured'); + } } else { setIntegrationStatus('not_configured'); }