django admin Groups reorg, Frontend udpates for site settings, #Migration runs
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-04 06:11
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0014_update_runware_models'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='globalintegrationsettings',
|
||||
name='anthropic_model',
|
||||
field=models.CharField(choices=[('claude-3-5-sonnet-20241022', 'Claude 3.5 Sonnet - $3.00 / $15.00 per 1M tokens'), ('claude-3-5-haiku-20241022', 'Claude 3.5 Haiku - $1.00 / $5.00 per 1M tokens'), ('claude-3-opus-20240229', 'Claude 3 Opus - $15.00 / $75.00 per 1M tokens'), ('claude-3-sonnet-20240229', 'Claude 3 Sonnet - $3.00 / $15.00 per 1M tokens'), ('claude-3-haiku-20240307', 'Claude 3 Haiku - $0.25 / $1.25 per 1M tokens')], default='claude-3-5-sonnet-20241022', help_text='Default Claude model (accounts can override if plan allows)', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='globalintegrationsettings',
|
||||
name='default_image_service',
|
||||
field=models.CharField(choices=[('openai', 'OpenAI DALL-E'), ('runware', 'Runware')], default='openai', help_text='Default image generation service for all accounts (openai=DALL-E, runware=Runware, bria=Bria)', max_length=20),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='globalintegrationsettings',
|
||||
name='image_style',
|
||||
field=models.CharField(choices=[('photorealistic', 'Photorealistic'), ('illustration', 'Illustration'), ('3d_render', '3D Render'), ('minimal_flat', 'Minimal / Flat Design'), ('artistic', 'Artistic / Painterly'), ('cartoon', 'Cartoon / Stylized')], default='photorealistic', help_text='Default image style for all providers (accounts can override if plan allows)', max_length=30),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='globalmodulesettings',
|
||||
name='linker_enabled',
|
||||
field=models.BooleanField(default=False, help_text='Enable Linker module platform-wide (Phase 2)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='globalmodulesettings',
|
||||
name='optimizer_enabled',
|
||||
field=models.BooleanField(default=False, help_text='Enable Optimizer module platform-wide (Phase 2)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='globalmodulesettings',
|
||||
name='site_builder_enabled',
|
||||
field=models.BooleanField(default=False, help_text='Enable Site Builder module platform-wide (DEPRECATED)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='moduleenablesettings',
|
||||
name='linker_enabled',
|
||||
field=models.BooleanField(default=False, help_text='Enable Linker module (Phase 2)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='moduleenablesettings',
|
||||
name='optimizer_enabled',
|
||||
field=models.BooleanField(default=False, help_text='Enable Optimizer module (Phase 2)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='moduleenablesettings',
|
||||
name='site_builder_enabled',
|
||||
field=models.BooleanField(default=False, help_text='Enable Site Builder module (DEPRECATED)'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='IntegrationProvider',
|
||||
fields=[
|
||||
('provider_id', models.CharField(help_text="Unique identifier (e.g., 'openai', 'stripe', 'resend')", max_length=50, primary_key=True, serialize=False, unique=True)),
|
||||
('display_name', models.CharField(help_text='Human-readable name', max_length=100)),
|
||||
('provider_type', models.CharField(choices=[('ai', 'AI Provider'), ('email', 'Email Service'), ('payment', 'Payment Gateway'), ('storage', 'Storage Service'), ('analytics', 'Analytics'), ('other', 'Other')], db_index=True, default='ai', max_length=20)),
|
||||
('api_key', models.CharField(blank=True, help_text='Primary API key or token', max_length=500)),
|
||||
('api_secret', models.CharField(blank=True, help_text='Secondary secret (for OAuth, Stripe secret key, etc.)', max_length=500)),
|
||||
('webhook_secret', models.CharField(blank=True, help_text='Webhook signing secret (Stripe, PayPal)', max_length=500)),
|
||||
('api_endpoint', models.URLField(blank=True, help_text='Custom API endpoint (if not default)')),
|
||||
('webhook_url', models.URLField(blank=True, help_text='Webhook URL configured at provider')),
|
||||
('config', models.JSONField(blank=True, default=dict, help_text='Provider-specific config: rate limits, regions, modes, etc.')),
|
||||
('is_active', models.BooleanField(db_index=True, default=True)),
|
||||
('is_sandbox', models.BooleanField(default=False, help_text='True if using sandbox/test mode (Stripe test keys, PayPal sandbox)')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='integration_provider_updates', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Integration Provider',
|
||||
'verbose_name_plural': 'Integration Providers',
|
||||
'db_table': 'igny8_integration_providers',
|
||||
'ordering': ['provider_type', 'display_name'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,136 @@
|
||||
# Generated manually for data migration
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def populate_integration_providers(apps, schema_editor):
|
||||
"""
|
||||
Populate IntegrationProvider with all 3rd party integrations.
|
||||
API keys will need to be configured in Django admin after migration.
|
||||
"""
|
||||
IntegrationProvider = apps.get_model('system', 'IntegrationProvider')
|
||||
|
||||
providers = [
|
||||
# AI Providers
|
||||
{
|
||||
'provider_id': 'openai',
|
||||
'display_name': 'OpenAI',
|
||||
'provider_type': 'ai',
|
||||
'api_key': '', # To be configured in admin
|
||||
'config': {
|
||||
'default_model': 'gpt-5.1',
|
||||
'models': ['gpt-4o-mini', 'gpt-4o', 'gpt-5.1', 'dall-e-3'],
|
||||
},
|
||||
'is_active': True,
|
||||
},
|
||||
{
|
||||
'provider_id': 'runware',
|
||||
'display_name': 'Runware',
|
||||
'provider_type': 'ai',
|
||||
'api_key': '', # To be configured in admin
|
||||
'config': {
|
||||
'default_model': 'runware:97@1',
|
||||
'models': ['runware:97@1', 'google:4@2'],
|
||||
},
|
||||
'is_active': True,
|
||||
},
|
||||
{
|
||||
'provider_id': 'anthropic',
|
||||
'display_name': 'Anthropic (Claude)',
|
||||
'provider_type': 'ai',
|
||||
'api_key': '',
|
||||
'config': {
|
||||
'default_model': 'claude-3-5-sonnet-20241022',
|
||||
},
|
||||
'is_active': False, # Not currently used
|
||||
},
|
||||
{
|
||||
'provider_id': 'google',
|
||||
'display_name': 'Google Cloud',
|
||||
'provider_type': 'ai',
|
||||
'api_key': '',
|
||||
'config': {},
|
||||
'is_active': False, # Future: Gemini
|
||||
},
|
||||
|
||||
# Payment Providers
|
||||
{
|
||||
'provider_id': 'stripe',
|
||||
'display_name': 'Stripe',
|
||||
'provider_type': 'payment',
|
||||
'api_key': '', # Public key
|
||||
'api_secret': '', # Secret key
|
||||
'webhook_secret': '',
|
||||
'config': {
|
||||
'currency': 'usd',
|
||||
},
|
||||
'is_active': True,
|
||||
'is_sandbox': True, # Start in test mode
|
||||
},
|
||||
{
|
||||
'provider_id': 'paypal',
|
||||
'display_name': 'PayPal',
|
||||
'provider_type': 'payment',
|
||||
'api_key': '', # Client ID
|
||||
'api_secret': '', # Client Secret
|
||||
'webhook_secret': '',
|
||||
'api_endpoint': 'https://api-m.sandbox.paypal.com', # Sandbox endpoint
|
||||
'config': {
|
||||
'currency': 'usd',
|
||||
},
|
||||
'is_active': True,
|
||||
'is_sandbox': True,
|
||||
},
|
||||
|
||||
# Email Providers
|
||||
{
|
||||
'provider_id': 'resend',
|
||||
'display_name': 'Resend',
|
||||
'provider_type': 'email',
|
||||
'api_key': '',
|
||||
'config': {
|
||||
'from_email': 'noreply@igny8.com',
|
||||
'from_name': 'IGNY8',
|
||||
},
|
||||
'is_active': True,
|
||||
},
|
||||
|
||||
# Storage Providers (Future)
|
||||
{
|
||||
'provider_id': 'cloudflare_r2',
|
||||
'display_name': 'Cloudflare R2',
|
||||
'provider_type': 'storage',
|
||||
'api_key': '', # Access Key ID
|
||||
'api_secret': '', # Secret Access Key
|
||||
'config': {
|
||||
'bucket': '',
|
||||
'endpoint': '',
|
||||
},
|
||||
'is_active': False,
|
||||
},
|
||||
]
|
||||
|
||||
for provider_data in providers:
|
||||
IntegrationProvider.objects.update_or_create(
|
||||
provider_id=provider_data['provider_id'],
|
||||
defaults=provider_data
|
||||
)
|
||||
|
||||
|
||||
def reverse_migration(apps, schema_editor):
|
||||
"""Remove seeded providers"""
|
||||
IntegrationProvider = apps.get_model('system', 'IntegrationProvider')
|
||||
IntegrationProvider.objects.filter(
|
||||
provider_id__in=['openai', 'runware', 'anthropic', 'google', 'stripe', 'paypal', 'resend', 'cloudflare_r2']
|
||||
).delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0015_add_integration_provider'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(populate_integration_providers, reverse_migration),
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-04 08:43
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0016_populate_integration_providers'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# AccountIntegrationOverride was already deleted in a previous migration
|
||||
# Keeping this migration empty for now
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-04 08:43
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0017_create_ai_settings'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SystemAISettings',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('temperature', models.FloatField(default=0.7, help_text='AI temperature (0.0-2.0). Higher = more creative.')),
|
||||
('max_tokens', models.IntegerField(default=8192, help_text='Max response tokens')),
|
||||
('image_style', models.CharField(choices=[('photorealistic', 'Photorealistic'), ('illustration', 'Illustration'), ('3d_render', '3D Render'), ('minimal_flat', 'Minimal / Flat Design'), ('artistic', 'Artistic / Painterly'), ('cartoon', 'Cartoon / Stylized')], default='photorealistic', help_text='Default image style', max_length=30)),
|
||||
('image_quality', models.CharField(choices=[('standard', 'Standard'), ('hd', 'HD')], default='standard', help_text='Default image quality (standard/hd)', max_length=20)),
|
||||
('max_images_per_article', models.IntegerField(default=4, help_text='Max in-article images (1-8)')),
|
||||
('image_size', models.CharField(choices=[('1024x1024', '1024x1024 (Square)'), ('1792x1024', '1792x1024 (Landscape)'), ('1024x1792', '1024x1792 (Portrait)')], default='1024x1024', help_text='Default image dimensions', max_length=20)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='system_ai_settings_updates', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'System AI Settings',
|
||||
'verbose_name_plural': 'System AI Settings',
|
||||
'db_table': 'igny8_system_ai_settings',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,91 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-04 10:40
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0018_create_ai_settings_table'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='accountsettings',
|
||||
name='config',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='accountsettings',
|
||||
name='is_active',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='integrationprovider',
|
||||
name='webhook_url',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='modulesettings',
|
||||
name='config',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='accountsettings',
|
||||
name='value',
|
||||
field=models.JSONField(default=dict, help_text='Setting value'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='accountsettings',
|
||||
name='key',
|
||||
field=models.CharField(db_index=True, help_text='Setting key', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='api_endpoint',
|
||||
field=models.URLField(blank=True, help_text='Custom endpoint (optional)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='api_key',
|
||||
field=models.CharField(blank=True, help_text='Primary API key', max_length=500),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='api_secret',
|
||||
field=models.CharField(blank=True, help_text='Secondary secret (Stripe, PayPal)', max_length=500),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='config',
|
||||
field=models.JSONField(blank=True, default=dict, help_text='Provider-specific config'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='is_active',
|
||||
field=models.BooleanField(db_index=True, default=True, help_text='Enable/disable provider'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='is_sandbox',
|
||||
field=models.BooleanField(default=False, help_text='Test mode flag'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='provider_type',
|
||||
field=models.CharField(choices=[('ai', 'AI Provider'), ('payment', 'Payment Gateway'), ('email', 'Email Service'), ('storage', 'Storage Service')], db_index=True, default='ai', help_text='ai / payment / email / storage', max_length=20),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='updated_by',
|
||||
field=models.ForeignKey(blank=True, help_text='Audit trail', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='integration_provider_updates', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='integrationprovider',
|
||||
name='webhook_secret',
|
||||
field=models.CharField(blank=True, help_text='Webhook signing secret', max_length=500),
|
||||
),
|
||||
# AccountIntegrationOverride table doesn't exist in DB, so skip delete
|
||||
# migrations.DeleteModel(
|
||||
# name='AccountIntegrationOverride',
|
||||
# ),
|
||||
]
|
||||
Reference in New Issue
Block a user