This commit is contained in:
alorig
2025-11-22 21:10:05 +05:00
parent d4990fb088
commit 9ee03f4f7f
3 changed files with 47 additions and 45 deletions

View File

@@ -16,6 +16,9 @@ from igny8_core.business.integration.services.integration_service import Integra
from igny8_core.business.integration.services.sync_service import SyncService from igny8_core.business.integration.services.sync_service import SyncService
from igny8_core.business.integration.services.sync_health_service import SyncHealthService from igny8_core.business.integration.services.sync_health_service import SyncHealthService
from igny8_core.business.integration.services.content_sync_service import ContentSyncService from igny8_core.business.integration.services.content_sync_service import ContentSyncService
import logging
logger = logging.getLogger(__name__)
class IntegrationViewSet(SiteSectorModelViewSet): class IntegrationViewSet(SiteSectorModelViewSet):
@@ -186,15 +189,21 @@ class IntegrationViewSet(SiteSectorModelViewSet):
# Try to find an existing integration for this site+platform # Try to find an existing integration for this site+platform
integration = SiteIntegration.objects.filter(site=site, platform='wordpress').first() integration = SiteIntegration.objects.filter(site=site, platform='wordpress').first()
# If not found, create a temporary in-memory integration object # If not found, create and save the integration to database
integration_created = False
if not integration: if not integration:
integration = SiteIntegration( integration = SiteIntegration.objects.create(
account=site.account,
site=site, site=site,
platform='wordpress', platform='wordpress',
platform_type='cms',
config_json={'site_url': site_url} if site_url else {}, config_json={'site_url': site_url} if site_url else {},
credentials_json={'api_key': api_key} if api_key else {}, credentials_json={'api_key': api_key} if api_key else {},
is_active=False is_active=True,
sync_enabled=True
) )
integration_created = True
logger.info(f"[IntegrationViewSet] Created WordPress integration {integration.id} for site {site.id}")
service = IntegrationService() service = IntegrationService()
# Mark this as initial connection test since API key was provided in request body # Mark this as initial connection test since API key was provided in request body
@@ -203,8 +212,15 @@ class IntegrationViewSet(SiteSectorModelViewSet):
result = service._test_wordpress_connection(integration, is_initial_connection=is_initial_connection) result = service._test_wordpress_connection(integration, is_initial_connection=is_initial_connection)
if result.get('success'): if result.get('success'):
# Include integration_id in response so plugin can store it
result['integration_id'] = integration.id
result['integration_created'] = integration_created
return success_response(result, request=request) return success_response(result, request=request)
else: else:
# If test failed and we just created integration, delete it
if integration_created:
integration.delete()
logger.info(f"[IntegrationViewSet] Deleted integration {integration.id} due to failed connection test")
return error_response(result.get('message', 'Connection test failed'), None, status.HTTP_400_BAD_REQUEST, request) return error_response(result.get('message', 'Connection test failed'), None, status.HTTP_400_BAD_REQUEST, request)
@action(detail=True, methods=['post']) @action(detail=True, methods=['post'])

View File

@@ -178,46 +178,29 @@ export default function WordPressIntegrationForm({
return key.substring(0, 8) + '**********' + key.substring(key.length - 4); return key.substring(0, 8) + '**********' + key.substring(key.length - 4);
}; };
// Toggle integration enabled status // Toggle integration sync enabled status (not creation - that happens automatically)
const [integrationEnabled, setIntegrationEnabled] = useState(integration?.is_active ?? true); const [integrationEnabled, setIntegrationEnabled] = useState(integration?.sync_enabled ?? false);
const handleToggleIntegration = async (enabled: boolean) => { const handleToggleIntegration = async (enabled: boolean) => {
try { try {
setIntegrationEnabled(enabled); setIntegrationEnabled(enabled);
if (integration) { if (integration) {
// Update existing integration // Update existing integration - only toggle sync_enabled, not creation
await integrationApi.updateIntegration(integration.id, { await integrationApi.updateIntegration(integration.id, {
is_active: enabled, sync_enabled: enabled,
} as any); } as any);
toast.success(enabled ? 'Integration enabled' : 'Integration disabled'); toast.success(enabled ? 'Sync enabled' : 'Sync disabled');
// Reload integration // Reload integration
const updated = await integrationApi.getWordPressIntegration(siteId); const updated = await integrationApi.getWordPressIntegration(siteId);
if (onIntegrationUpdate && updated) { if (onIntegrationUpdate && updated) {
onIntegrationUpdate(updated); onIntegrationUpdate(updated);
} }
} else if (enabled && apiKey) { } else {
// Create integration when enabling for first time // Integration doesn't exist - it should be created automatically by plugin
// Use API key-only authentication (no username/password required) // when user connects from WordPress side
await integrationApi.saveWordPressIntegration(siteId, { toast.info('Integration will be created automatically when you connect from WordPress plugin. Please connect from the plugin first.');
url: siteUrl || '',
username: '', // Optional when using API key
app_password: '', // Optional when using API key
api_key: apiKey,
is_active: enabled,
sync_enabled: true,
});
toast.success('Integration created and enabled');
// Reload integration
const updated = await integrationApi.getWordPressIntegration(siteId);
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); setIntegrationEnabled(false);
} }
} catch (error: any) { } catch (error: any) {
@@ -229,7 +212,7 @@ export default function WordPressIntegrationForm({
useEffect(() => { useEffect(() => {
if (integration) { if (integration) {
setIntegrationEnabled(integration.is_active ?? true); setIntegrationEnabled(integration.sync_enabled ?? false);
} }
}, [integration]); }, [integration]);
@@ -255,7 +238,7 @@ export default function WordPressIntegrationForm({
{apiKey && ( {apiKey && (
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="text-sm font-medium text-gray-700 dark:text-gray-300"> <span className="text-sm font-medium text-gray-700 dark:text-gray-300">
{integrationEnabled ? 'Enabled' : 'Disabled'} {integrationEnabled ? 'Sync Enabled' : 'Sync Disabled'}
</span> </span>
<button <button
type="button" type="button"

View File

@@ -209,22 +209,14 @@ export default function SiteSettings() {
const [integrationStatus, setIntegrationStatus] = useState<'connected' | 'configured' | 'not_configured'>('not_configured'); const [integrationStatus, setIntegrationStatus] = useState<'connected' | 'configured' | 'not_configured'>('not_configured');
const [testingAuth, setTestingAuth] = useState(false); const [testingAuth, setTestingAuth] = useState(false);
// Check basic configuration (API key + toggle) // Check basic configuration - integration must exist in DB and have sync_enabled
useEffect(() => { useEffect(() => {
const checkStatus = async () => { const checkStatus = async () => {
// If integration exists and is active, mark as configured // Integration must exist in database and have sync_enabled = true
if (wordPressIntegration && wordPressIntegration.is_active) { if (wordPressIntegration && wordPressIntegration.id && wordPressIntegration.sync_enabled) {
// Check if API key exists (either in site or in integration credentials) setIntegrationStatus('configured');
const hasApiKey = site?.wp_api_key || // Test authentication
(wordPressIntegration.credentials_json?.api_key); testAuthentication();
if (hasApiKey) {
setIntegrationStatus('configured');
// Test authentication
testAuthentication();
} else {
setIntegrationStatus('not_configured');
}
} else { } else {
setIntegrationStatus('not_configured'); setIntegrationStatus('not_configured');
} }
@@ -232,6 +224,17 @@ export default function SiteSettings() {
checkStatus(); checkStatus();
}, [wordPressIntegration, site]); }, [wordPressIntegration, site]);
// Auto-refresh integration list periodically to detect plugin-created integrations
useEffect(() => {
const interval = setInterval(() => {
if (!wordPressIntegration) {
loadIntegrations();
}
}, 5000); // Check every 5 seconds if integration doesn't exist
return () => clearInterval(interval);
}, [wordPressIntegration]);
// Test authentication with WordPress API // Test authentication with WordPress API
const testAuthentication = async () => { const testAuthentication = async () => {
if (testingAuth || !wordPressIntegration?.id) return; if (testingAuth || !wordPressIntegration?.id) return;