django bacekdn opeartioanl fixes and site wp integration api fixes
This commit is contained in:
@@ -244,14 +244,15 @@ class IntegrationService:
|
||||
}
|
||||
}
|
||||
|
||||
# Get API key from site
|
||||
# Get API key from Site.wp_api_key (SINGLE source of truth)
|
||||
# API key is stored on Site model for authentication by APIKeyAuthentication
|
||||
api_key = integration.site.wp_api_key
|
||||
|
||||
if not api_key:
|
||||
return {
|
||||
'success': False,
|
||||
'message': 'API key not configured.',
|
||||
'details': {}
|
||||
'message': 'API key not configured. Generate an API key in Site Settings.',
|
||||
'details': {'site_id': integration.site.id, 'site_name': integration.site.name}
|
||||
}
|
||||
|
||||
# Initialize health check results
|
||||
|
||||
@@ -39,8 +39,8 @@ class SyncMetadataService:
|
||||
try:
|
||||
# Get WordPress site URL and API key
|
||||
site_url = integration.config_json.get('site_url', '')
|
||||
credentials = integration.get_credentials()
|
||||
api_key = credentials.get('api_key', '')
|
||||
# API key is stored in Site.wp_api_key (SINGLE source of truth)
|
||||
api_key = integration.site.wp_api_key or ''
|
||||
|
||||
if not site_url:
|
||||
return {
|
||||
@@ -51,7 +51,7 @@ class SyncMetadataService:
|
||||
if not api_key:
|
||||
return {
|
||||
'success': False,
|
||||
'error': 'Missing api_key in integration credentials'
|
||||
'error': 'API key not configured for site. Generate one in Site Settings.'
|
||||
}
|
||||
|
||||
# Call WordPress metadata endpoint
|
||||
|
||||
@@ -142,44 +142,67 @@ class Keywords(SoftDeletableModel, SiteSectorBaseModel):
|
||||
@property
|
||||
def keyword(self):
|
||||
"""Get keyword text from seed_keyword"""
|
||||
return self.seed_keyword.keyword if self.seed_keyword else ''
|
||||
try:
|
||||
return self.seed_keyword.keyword if self.seed_keyword else ''
|
||||
except self.__class__.seed_keyword.RelatedObjectDoesNotExist:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
"""Get volume from override or seed_keyword"""
|
||||
return self.volume_override if self.volume_override is not None else (self.seed_keyword.volume if self.seed_keyword else 0)
|
||||
try:
|
||||
seed_kw = self.seed_keyword
|
||||
except self.__class__.seed_keyword.RelatedObjectDoesNotExist:
|
||||
seed_kw = None
|
||||
return self.volume_override if self.volume_override is not None else (seed_kw.volume if seed_kw else 0)
|
||||
|
||||
@property
|
||||
def difficulty(self):
|
||||
"""Get difficulty from override or seed_keyword"""
|
||||
return self.difficulty_override if self.difficulty_override is not None else (self.seed_keyword.difficulty if self.seed_keyword else 0)
|
||||
try:
|
||||
seed_kw = self.seed_keyword
|
||||
except self.__class__.seed_keyword.RelatedObjectDoesNotExist:
|
||||
seed_kw = None
|
||||
return self.difficulty_override if self.difficulty_override is not None else (seed_kw.difficulty if seed_kw else 0)
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
"""Get country from seed_keyword"""
|
||||
return self.seed_keyword.country if self.seed_keyword else 'US'
|
||||
try:
|
||||
return self.seed_keyword.country if self.seed_keyword else 'US'
|
||||
except self.__class__.seed_keyword.RelatedObjectDoesNotExist:
|
||||
return 'US'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""Validate that seed_keyword's industry/sector matches site's industry/sector"""
|
||||
if self.seed_keyword and self.site and self.sector:
|
||||
# Skip validation if seed_keyword is None (during soft delete or orphaned)
|
||||
try:
|
||||
seed_kw = self.seed_keyword
|
||||
except self.__class__.seed_keyword.RelatedObjectDoesNotExist:
|
||||
seed_kw = None
|
||||
|
||||
if seed_kw and self.site and self.sector:
|
||||
# Validate industry match
|
||||
if self.site.industry != self.seed_keyword.industry:
|
||||
if self.site.industry != seed_kw.industry:
|
||||
from django.core.exceptions import ValidationError
|
||||
raise ValidationError(
|
||||
f"SeedKeyword industry ({self.seed_keyword.industry.name}) must match site industry ({self.site.industry.name})"
|
||||
f"SeedKeyword industry ({seed_kw.industry.name}) must match site industry ({self.site.industry.name})"
|
||||
)
|
||||
|
||||
# Validate sector match (site sector's industry_sector must match seed_keyword's sector)
|
||||
if self.sector.industry_sector != self.seed_keyword.sector:
|
||||
if self.sector.industry_sector != seed_kw.sector:
|
||||
from django.core.exceptions import ValidationError
|
||||
raise ValidationError(
|
||||
f"SeedKeyword sector ({self.seed_keyword.sector.name}) must match site sector's industry sector ({self.sector.industry_sector.name if self.sector.industry_sector else 'None'})"
|
||||
f"SeedKeyword sector ({seed_kw.sector.name}) must match site sector's industry sector ({self.sector.industry_sector.name if self.sector.industry_sector else 'None'})"
|
||||
)
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return self.keyword
|
||||
try:
|
||||
return self.seed_keyword.keyword if self.seed_keyword else f'Keyword #{self.pk}'
|
||||
except self.__class__.seed_keyword.RelatedObjectDoesNotExist:
|
||||
return f'Keyword #{self.pk} (orphaned)'
|
||||
|
||||
|
||||
class ContentIdeas(SoftDeletableModel, SiteSectorBaseModel):
|
||||
|
||||
@@ -139,9 +139,13 @@ class PublisherService:
|
||||
|
||||
if integration:
|
||||
logger.info(f"[PublisherService._publish_to_destination] ✅ Integration found: id={integration.id}")
|
||||
# Merge config_json and credentials_json
|
||||
# Merge config_json (site_url, etc.)
|
||||
destination_config.update(integration.config_json or {})
|
||||
destination_config.update(integration.get_credentials() or {})
|
||||
|
||||
# API key is stored in Site.wp_api_key (SINGLE source of truth)
|
||||
if integration.site.wp_api_key:
|
||||
destination_config['api_key'] = integration.site.wp_api_key
|
||||
|
||||
logger.info(f"[PublisherService._publish_to_destination] 🔑 Config merged: has_api_key={bool(destination_config.get('api_key'))}, has_site_url={bool(destination_config.get('site_url'))}")
|
||||
|
||||
# Ensure site_url is set (from config or from site model)
|
||||
@@ -342,13 +346,16 @@ class PublisherService:
|
||||
destinations = []
|
||||
for integration in integrations:
|
||||
config = integration.config_json.copy()
|
||||
credentials = integration.get_credentials()
|
||||
|
||||
destination_config = {
|
||||
'platform': integration.platform,
|
||||
**config,
|
||||
**credentials
|
||||
}
|
||||
|
||||
# API key is stored in Site.wp_api_key (SINGLE source of truth)
|
||||
if integration.site.wp_api_key:
|
||||
destination_config['api_key'] = integration.site.wp_api_key
|
||||
|
||||
destinations.append(destination_config)
|
||||
|
||||
# Also add 'sites' destination if not in platforms filter or if platforms is None
|
||||
|
||||
Reference in New Issue
Block a user