django admin Groups reorg, Frontend udpates for site settings, #Migration runs
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
System module models - for global settings and prompts
|
||||
"""
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from igny8_core.auth.models import AccountBaseModel
|
||||
|
||||
# Import settings models
|
||||
@@ -10,6 +11,141 @@ from .settings_models import (
|
||||
)
|
||||
|
||||
|
||||
class IntegrationProvider(models.Model):
|
||||
"""
|
||||
Centralized storage for ALL external service API keys.
|
||||
|
||||
Per final-model-schemas.md:
|
||||
| Field | Type | Required | Notes |
|
||||
|-------|------|----------|-------|
|
||||
| provider_id | CharField(50) PK | Yes | openai, runware, stripe, paypal, resend |
|
||||
| display_name | CharField(100) | Yes | Human-readable name |
|
||||
| provider_type | CharField(20) | Yes | ai / payment / email / storage |
|
||||
| api_key | CharField(500) | No | Primary API key |
|
||||
| api_secret | CharField(500) | No | Secondary secret (Stripe, PayPal) |
|
||||
| webhook_secret | CharField(500) | No | Webhook signing secret |
|
||||
| api_endpoint | URLField | No | Custom endpoint (optional) |
|
||||
| config | JSONField | No | Provider-specific config |
|
||||
| is_active | BooleanField | Yes | Enable/disable provider |
|
||||
| is_sandbox | BooleanField | Yes | Test mode flag |
|
||||
| updated_by | FK(User) | No | Audit trail |
|
||||
| created_at | DateTime | Auto | |
|
||||
| updated_at | DateTime | Auto | |
|
||||
"""
|
||||
PROVIDER_TYPE_CHOICES = [
|
||||
('ai', 'AI Provider'),
|
||||
('payment', 'Payment Gateway'),
|
||||
('email', 'Email Service'),
|
||||
('storage', 'Storage Service'),
|
||||
]
|
||||
|
||||
# Primary Key
|
||||
provider_id = models.CharField(
|
||||
max_length=50,
|
||||
unique=True,
|
||||
primary_key=True,
|
||||
help_text="Unique identifier (e.g., 'openai', 'stripe', 'resend')"
|
||||
)
|
||||
|
||||
# Display name
|
||||
display_name = models.CharField(
|
||||
max_length=100,
|
||||
help_text="Human-readable name"
|
||||
)
|
||||
|
||||
# Provider type
|
||||
provider_type = models.CharField(
|
||||
max_length=20,
|
||||
choices=PROVIDER_TYPE_CHOICES,
|
||||
default='ai',
|
||||
db_index=True,
|
||||
help_text="ai / payment / email / storage"
|
||||
)
|
||||
|
||||
# Authentication
|
||||
api_key = models.CharField(
|
||||
max_length=500,
|
||||
blank=True,
|
||||
help_text="Primary API key"
|
||||
)
|
||||
api_secret = models.CharField(
|
||||
max_length=500,
|
||||
blank=True,
|
||||
help_text="Secondary secret (Stripe, PayPal)"
|
||||
)
|
||||
webhook_secret = models.CharField(
|
||||
max_length=500,
|
||||
blank=True,
|
||||
help_text="Webhook signing secret"
|
||||
)
|
||||
|
||||
# Endpoints
|
||||
api_endpoint = models.URLField(
|
||||
blank=True,
|
||||
help_text="Custom endpoint (optional)"
|
||||
)
|
||||
|
||||
# Configuration
|
||||
config = models.JSONField(
|
||||
default=dict,
|
||||
blank=True,
|
||||
help_text="Provider-specific config"
|
||||
)
|
||||
|
||||
# Status
|
||||
is_active = models.BooleanField(
|
||||
default=True,
|
||||
db_index=True,
|
||||
help_text="Enable/disable provider"
|
||||
)
|
||||
is_sandbox = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Test mode flag"
|
||||
)
|
||||
|
||||
# Audit
|
||||
updated_by = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='integration_provider_updates',
|
||||
help_text="Audit trail"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'igny8_integration_providers'
|
||||
verbose_name = 'Integration Provider'
|
||||
verbose_name_plural = 'Integration Providers'
|
||||
ordering = ['provider_type', 'display_name']
|
||||
|
||||
def __str__(self):
|
||||
status = "Active" if self.is_active else "Inactive"
|
||||
mode = "(Sandbox)" if self.is_sandbox else ""
|
||||
return f"{self.display_name} - {status} {mode}".strip()
|
||||
|
||||
@classmethod
|
||||
def get_provider(cls, provider_id: str):
|
||||
"""Get provider by ID, returns None if not found or inactive"""
|
||||
try:
|
||||
return cls.objects.get(provider_id=provider_id, is_active=True)
|
||||
except cls.DoesNotExist:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_api_key(cls, provider_id: str) -> str:
|
||||
"""Get API key for a provider"""
|
||||
provider = cls.get_provider(provider_id)
|
||||
return provider.api_key if provider else ""
|
||||
|
||||
@classmethod
|
||||
def get_providers_by_type(cls, provider_type: str):
|
||||
"""Get all active providers of a type"""
|
||||
return cls.objects.filter(provider_type=provider_type, is_active=True)
|
||||
|
||||
|
||||
class AIPrompt(AccountBaseModel):
|
||||
"""
|
||||
Account-specific AI Prompt templates.
|
||||
|
||||
Reference in New Issue
Block a user