plugin distribution system

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-09 21:38:14 +00:00
parent cf8181d1f9
commit 80f1709a2e
22 changed files with 2804 additions and 35 deletions

View File

@@ -0,0 +1,107 @@
# Generated by Django 5.2.10 on 2026-01-09 20:27
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('igny8_core_auth', '0020_fix_historical_account'),
]
operations = [
migrations.CreateModel(
name='Plugin',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text="Human-readable plugin name (e.g., 'IGNY8 WP Bridge')", max_length=100)),
('slug', models.SlugField(help_text="URL-safe identifier (e.g., 'igny8-wp-bridge')", unique=True)),
('platform', models.CharField(choices=[('wordpress', 'WordPress'), ('shopify', 'Shopify'), ('custom', 'Custom Site')], help_text='Target platform for this plugin', max_length=20)),
('description', models.TextField(blank=True, help_text='Plugin description for display in download pages')),
('homepage_url', models.URLField(blank=True, help_text='Plugin homepage or documentation URL')),
('is_active', models.BooleanField(db_index=True, default=True, help_text='Whether this plugin is available for download')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': 'Plugin',
'verbose_name_plural': 'Plugins',
'db_table': 'plugins',
'ordering': ['name'],
},
),
migrations.CreateModel(
name='PluginVersion',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('version', models.CharField(help_text="Semantic version string (e.g., '1.0.0', '1.0.1')", max_length=20)),
('version_code', models.IntegerField(help_text='Numeric version for comparison (1.0.1 -> 10001)')),
('status', models.CharField(choices=[('draft', 'Draft'), ('testing', 'Testing'), ('staged', 'Staged'), ('released', 'Released'), ('update_ready', 'Update Ready'), ('deprecated', 'Deprecated')], db_index=True, default='draft', help_text='Release status of this version', max_length=20)),
('file_path', models.CharField(help_text='Relative path to ZIP file in dist/ directory', max_length=500)),
('file_size', models.IntegerField(default=0, help_text='File size in bytes')),
('checksum', models.CharField(blank=True, help_text='SHA256 checksum for integrity verification', max_length=64)),
('changelog', models.TextField(blank=True, help_text="What's new in this version (supports Markdown)")),
('min_api_version', models.CharField(default='1.0', help_text='Minimum IGNY8 API version required', max_length=20)),
('min_platform_version', models.CharField(blank=True, help_text='Minimum platform version (e.g., WordPress 5.0)', max_length=20)),
('min_php_version', models.CharField(default='7.4', help_text='Minimum PHP version required (for WordPress plugins)', max_length=10)),
('created_at', models.DateTimeField(auto_now_add=True)),
('released_at', models.DateTimeField(blank=True, help_text='When this version was released', null=True)),
('force_update', models.BooleanField(default=False, help_text='Force update for critical security fixes')),
('plugin', models.ForeignKey(help_text='Plugin this version belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='plugins.plugin')),
],
options={
'verbose_name': 'Plugin Version',
'verbose_name_plural': 'Plugin Versions',
'db_table': 'plugin_versions',
'ordering': ['-version_code'],
'unique_together': {('plugin', 'version')},
},
),
migrations.CreateModel(
name='PluginInstallation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_active', models.BooleanField(db_index=True, default=True, help_text='Whether the plugin is currently active')),
('last_health_check', models.DateTimeField(blank=True, help_text='Last successful health check timestamp', null=True)),
('health_status', models.CharField(choices=[('healthy', 'Healthy'), ('outdated', 'Outdated'), ('error', 'Error'), ('unknown', 'Unknown')], default='unknown', help_text='Current health status', max_length=20)),
('update_notified_at', models.DateTimeField(blank=True, help_text='When site was notified about pending update', null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('plugin', models.ForeignKey(help_text='Installed plugin', on_delete=django.db.models.deletion.CASCADE, related_name='installations', to='plugins.plugin')),
('site', models.ForeignKey(help_text='Site where plugin is installed', on_delete=django.db.models.deletion.CASCADE, related_name='plugin_installations', to='igny8_core_auth.site')),
('current_version', models.ForeignKey(help_text='Currently installed version', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_installations', to='plugins.pluginversion')),
('pending_update', models.ForeignKey(blank=True, help_text='Pending version update', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pending_installations', to='plugins.pluginversion')),
],
options={
'verbose_name': 'Plugin Installation',
'verbose_name_plural': 'Plugin Installations',
'db_table': 'plugin_installations',
'ordering': ['-updated_at'],
'unique_together': {('site', 'plugin')},
},
),
migrations.CreateModel(
name='PluginDownload',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip_address', models.GenericIPAddressField(blank=True, null=True)),
('user_agent', models.CharField(blank=True, max_length=500)),
('download_type', models.CharField(choices=[('manual', 'Manual Download'), ('update', 'Auto Update'), ('api', 'API Download')], default='manual', max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True)),
('account', models.ForeignKey(blank=True, help_text='Account that initiated the download', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='plugin_downloads', to='igny8_core_auth.account')),
('plugin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='downloads', to='plugins.plugin')),
('site', models.ForeignKey(blank=True, help_text='Site that initiated the download (if authenticated)', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='plugin_downloads', to='igny8_core_auth.site')),
('version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='downloads', to='plugins.pluginversion')),
],
options={
'verbose_name': 'Plugin Download',
'verbose_name_plural': 'Plugin Downloads',
'db_table': 'plugin_downloads',
'ordering': ['-created_at'],
'indexes': [models.Index(fields=['plugin', 'created_at'], name='plugin_down_plugin__5771ff_idx'), models.Index(fields=['version', 'created_at'], name='plugin_down_version_2bcf49_idx')],
},
),
]