1
This commit is contained in:
50
backend/INTEGRATION-FIXES.md
Normal file
50
backend/INTEGRATION-FIXES.md
Normal file
@@ -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
|
||||||
|
|
||||||
@@ -52,6 +52,34 @@ class IntegrationViewSet(SiteSectorModelViewSet):
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
class SiteIntegrationSerializer(serializers.ModelSerializer):
|
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:
|
class Meta:
|
||||||
model = SiteIntegration
|
model = SiteIntegration
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|||||||
@@ -199,10 +199,11 @@ export default function WordPressIntegrationForm({
|
|||||||
}
|
}
|
||||||
} else if (enabled && apiKey) {
|
} else if (enabled && apiKey) {
|
||||||
// Create integration when enabling for first time
|
// Create integration when enabling for first time
|
||||||
|
// Use API key-only authentication (no username/password required)
|
||||||
await integrationApi.saveWordPressIntegration(siteId, {
|
await integrationApi.saveWordPressIntegration(siteId, {
|
||||||
url: siteUrl || '',
|
url: siteUrl || '',
|
||||||
username: '',
|
username: '', // Optional when using API key
|
||||||
app_password: '',
|
app_password: '', // Optional when using API key
|
||||||
api_key: apiKey,
|
api_key: apiKey,
|
||||||
is_active: enabled,
|
is_active: enabled,
|
||||||
sync_enabled: true,
|
sync_enabled: true,
|
||||||
@@ -214,6 +215,10 @@ export default function WordPressIntegrationForm({
|
|||||||
if (onIntegrationUpdate && updated) {
|
if (onIntegrationUpdate && updated) {
|
||||||
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) {
|
} catch (error: any) {
|
||||||
toast.error(`Failed to update integration: ${error.message}`);
|
toast.error(`Failed to update integration: ${error.message}`);
|
||||||
|
|||||||
@@ -212,10 +212,19 @@ export default function SiteSettings() {
|
|||||||
// Check basic configuration (API key + toggle)
|
// Check basic configuration (API key + toggle)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkStatus = async () => {
|
const checkStatus = async () => {
|
||||||
if (wordPressIntegration && wordPressIntegration.is_active && site?.wp_api_key) {
|
// If integration exists and is active, mark as configured
|
||||||
setIntegrationStatus('configured');
|
if (wordPressIntegration && wordPressIntegration.is_active) {
|
||||||
// Test authentication
|
// Check if API key exists (either in site or in integration credentials)
|
||||||
testAuthentication();
|
const hasApiKey = site?.wp_api_key ||
|
||||||
|
(wordPressIntegration.credentials_json?.api_key);
|
||||||
|
|
||||||
|
if (hasApiKey) {
|
||||||
|
setIntegrationStatus('configured');
|
||||||
|
// Test authentication
|
||||||
|
testAuthentication();
|
||||||
|
} else {
|
||||||
|
setIntegrationStatus('not_configured');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setIntegrationStatus('not_configured');
|
setIntegrationStatus('not_configured');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user