django-cfg 1.2.17__py3-none-any.whl → 1.2.18__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/models/__init__.py +68 -0
  3. django_cfg/apps/accounts/models/activity.py +34 -0
  4. django_cfg/apps/accounts/models/auth.py +50 -0
  5. django_cfg/apps/accounts/models/base.py +8 -0
  6. django_cfg/apps/accounts/models/choices.py +32 -0
  7. django_cfg/apps/accounts/models/integrations.py +75 -0
  8. django_cfg/apps/accounts/models/registration.py +52 -0
  9. django_cfg/apps/accounts/models/user.py +80 -0
  10. django_cfg/apps/maintenance/__init__.py +53 -24
  11. django_cfg/apps/maintenance/admin/__init__.py +7 -18
  12. django_cfg/apps/maintenance/admin/api_key_admin.py +185 -0
  13. django_cfg/apps/maintenance/admin/log_admin.py +156 -0
  14. django_cfg/apps/maintenance/admin/scheduled_admin.py +390 -0
  15. django_cfg/apps/maintenance/admin/site_admin.py +448 -0
  16. django_cfg/apps/maintenance/apps.py +9 -96
  17. django_cfg/apps/maintenance/management/commands/maintenance.py +193 -307
  18. django_cfg/apps/maintenance/management/commands/process_scheduled_maintenance.py +241 -0
  19. django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +152 -111
  20. django_cfg/apps/maintenance/managers/__init__.py +7 -12
  21. django_cfg/apps/maintenance/managers/cloudflare_site_manager.py +192 -0
  22. django_cfg/apps/maintenance/managers/maintenance_log_manager.py +151 -0
  23. django_cfg/apps/maintenance/migrations/0001_initial.py +145 -705
  24. django_cfg/apps/maintenance/migrations/0002_cloudflaresite_maintenance_url.py +21 -0
  25. django_cfg/apps/maintenance/models/__init__.py +23 -21
  26. django_cfg/apps/maintenance/models/cloudflare_api_key.py +109 -0
  27. django_cfg/apps/maintenance/models/cloudflare_site.py +125 -0
  28. django_cfg/apps/maintenance/models/maintenance_log.py +131 -0
  29. django_cfg/apps/maintenance/models/scheduled_maintenance.py +307 -0
  30. django_cfg/apps/maintenance/services/__init__.py +37 -16
  31. django_cfg/apps/maintenance/services/bulk_operations_service.py +400 -0
  32. django_cfg/apps/maintenance/services/maintenance_service.py +230 -0
  33. django_cfg/apps/maintenance/services/scheduled_maintenance_service.py +381 -0
  34. django_cfg/apps/maintenance/services/site_sync_service.py +390 -0
  35. django_cfg/apps/maintenance/utils/__init__.py +12 -0
  36. django_cfg/apps/maintenance/utils/retry_utils.py +109 -0
  37. django_cfg/config.py +3 -0
  38. django_cfg/core/config.py +4 -6
  39. django_cfg/modules/django_unfold/dashboard.py +4 -5
  40. {django_cfg-1.2.17.dist-info → django_cfg-1.2.18.dist-info}/METADATA +52 -1
  41. {django_cfg-1.2.17.dist-info → django_cfg-1.2.18.dist-info}/RECORD +45 -55
  42. django_cfg/apps/maintenance/README.md +0 -305
  43. django_cfg/apps/maintenance/admin/deployments_admin.py +0 -251
  44. django_cfg/apps/maintenance/admin/events_admin.py +0 -374
  45. django_cfg/apps/maintenance/admin/monitoring_admin.py +0 -215
  46. django_cfg/apps/maintenance/admin/sites_admin.py +0 -464
  47. django_cfg/apps/maintenance/managers/deployments.py +0 -287
  48. django_cfg/apps/maintenance/managers/events.py +0 -374
  49. django_cfg/apps/maintenance/managers/monitoring.py +0 -301
  50. django_cfg/apps/maintenance/managers/sites.py +0 -335
  51. django_cfg/apps/maintenance/models/cloudflare.py +0 -316
  52. django_cfg/apps/maintenance/models/maintenance.py +0 -334
  53. django_cfg/apps/maintenance/models/monitoring.py +0 -393
  54. django_cfg/apps/maintenance/models/sites.py +0 -419
  55. django_cfg/apps/maintenance/serializers/__init__.py +0 -60
  56. django_cfg/apps/maintenance/serializers/actions.py +0 -310
  57. django_cfg/apps/maintenance/serializers/base.py +0 -44
  58. django_cfg/apps/maintenance/serializers/deployments.py +0 -209
  59. django_cfg/apps/maintenance/serializers/events.py +0 -210
  60. django_cfg/apps/maintenance/serializers/monitoring.py +0 -278
  61. django_cfg/apps/maintenance/serializers/sites.py +0 -213
  62. django_cfg/apps/maintenance/services/README.md +0 -168
  63. django_cfg/apps/maintenance/services/cloudflare_client.py +0 -441
  64. django_cfg/apps/maintenance/services/dns_manager.py +0 -497
  65. django_cfg/apps/maintenance/services/maintenance_manager.py +0 -504
  66. django_cfg/apps/maintenance/services/site_sync.py +0 -448
  67. django_cfg/apps/maintenance/services/sync_command_service.py +0 -330
  68. django_cfg/apps/maintenance/services/worker_manager.py +0 -264
  69. django_cfg/apps/maintenance/signals.py +0 -38
  70. django_cfg/apps/maintenance/urls.py +0 -36
  71. django_cfg/apps/maintenance/views/__init__.py +0 -18
  72. django_cfg/apps/maintenance/views/base.py +0 -61
  73. django_cfg/apps/maintenance/views/deployments.py +0 -175
  74. django_cfg/apps/maintenance/views/events.py +0 -204
  75. django_cfg/apps/maintenance/views/monitoring.py +0 -213
  76. django_cfg/apps/maintenance/views/sites.py +0 -338
  77. django_cfg/models/cloudflare.py +0 -316
  78. /django_cfg/apps/accounts/{models.py → __models.py} +0 -0
  79. {django_cfg-1.2.17.dist-info → django_cfg-1.2.18.dist-info}/WHEEL +0 -0
  80. {django_cfg-1.2.17.dist-info → django_cfg-1.2.18.dist-info}/entry_points.txt +0 -0
  81. {django_cfg-1.2.17.dist-info → django_cfg-1.2.18.dist-info}/licenses/LICENSE +0 -0
@@ -1,213 +0,0 @@
1
- """
2
- Site management serializers.
3
-
4
- Serializers for CloudflareSite and SiteGroup models.
5
- """
6
-
7
- from rest_framework import serializers
8
- from drf_spectacular.utils import extend_schema_serializer, OpenApiExample
9
-
10
- from ..models import CloudflareSite, SiteGroup
11
- from .base import UserSerializer
12
-
13
-
14
- @extend_schema_serializer(
15
- examples=[
16
- OpenApiExample(
17
- 'Production Site',
18
- summary='A production Cloudflare site',
19
- description='Example of a production site configuration',
20
- value={
21
- 'name': 'My Production Site',
22
- 'domain': 'example.com',
23
- 'zone_id': 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
24
- 'account_id': 'z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4',
25
- 'api_token': 'your-cloudflare-api-token',
26
- 'environment': 'production',
27
- 'project': 'main-website',
28
- 'tags': ['critical', 'ecommerce']
29
- }
30
- ),
31
- OpenApiExample(
32
- 'Staging Site',
33
- summary='A staging environment site',
34
- description='Example of a staging site configuration',
35
- value={
36
- 'name': 'Staging Environment',
37
- 'domain': 'staging.example.com',
38
- 'zone_id': 'b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7',
39
- 'account_id': 'y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4j3',
40
- 'api_token': 'your-cloudflare-api-token',
41
- 'environment': 'staging',
42
- 'project': 'main-website',
43
- 'tags': ['testing']
44
- }
45
- )
46
- ]
47
- )
48
- class CloudflareSiteSerializer(serializers.ModelSerializer):
49
- """Serializer for CloudflareSite model with full details."""
50
-
51
- owner = UserSerializer(read_only=True)
52
- maintenance_duration = serializers.ReadOnlyField()
53
- health_check_endpoint = serializers.ReadOnlyField()
54
- is_production = serializers.ReadOnlyField()
55
-
56
- class Meta:
57
- model = CloudflareSite
58
- fields = [
59
- 'id', 'name', 'domain', 'zone_id', 'account_id', 'api_token',
60
- 'environment', 'project', 'tags', 'owner', 'current_status',
61
- 'maintenance_active', 'monitoring_enabled', 'worker_name',
62
- 'health_check_url', 'check_interval', 'failure_threshold',
63
- 'maintenance_duration', 'health_check_endpoint', 'is_production',
64
- 'last_maintenance_at', 'last_status_check', 'created_at', 'updated_at'
65
- ]
66
- read_only_fields = [
67
- 'id', 'owner', 'current_status', 'maintenance_duration',
68
- 'health_check_endpoint', 'is_production', 'last_maintenance_at',
69
- 'last_status_check', 'created_at', 'updated_at'
70
- ]
71
- extra_kwargs = {
72
- 'api_token': {'write_only': True},
73
- 'zone_id': {
74
- 'help_text': 'Cloudflare Zone ID (32 characters)',
75
- 'min_length': 32,
76
- 'max_length': 32
77
- },
78
- 'account_id': {
79
- 'help_text': 'Cloudflare Account ID (32 characters)',
80
- 'min_length': 32,
81
- 'max_length': 32
82
- },
83
- 'name': {
84
- 'help_text': 'Human-readable name for the site'
85
- },
86
- 'domain': {
87
- 'help_text': 'Domain name (without protocol or www)'
88
- },
89
- 'environment': {
90
- 'help_text': 'Environment type (production, staging, development, testing)'
91
- },
92
- 'project': {
93
- 'help_text': 'Project name for grouping sites'
94
- },
95
- 'tags': {
96
- 'help_text': 'List of tags for categorization'
97
- }
98
- }
99
-
100
-
101
- class CloudflareSiteCreateSerializer(serializers.ModelSerializer):
102
- """Serializer for creating CloudflareSite with validation."""
103
-
104
- class Meta:
105
- model = CloudflareSite
106
- fields = [
107
- 'name', 'domain', 'zone_id', 'account_id', 'api_token',
108
- 'environment', 'project', 'tags', 'monitoring_enabled',
109
- 'worker_name', 'health_check_url', 'check_interval', 'failure_threshold'
110
- ]
111
- extra_kwargs = {
112
- 'api_token': {'write_only': True},
113
- 'zone_id': {
114
- 'help_text': 'Cloudflare Zone ID (32 characters)',
115
- 'min_length': 32,
116
- 'max_length': 32
117
- },
118
- 'account_id': {
119
- 'help_text': 'Cloudflare Account ID (32 characters)',
120
- 'min_length': 32,
121
- 'max_length': 32
122
- }
123
- }
124
-
125
- def validate_domain(self, value):
126
- """Validate domain format."""
127
- if value.startswith(('http://', 'https://')):
128
- raise serializers.ValidationError(
129
- "Domain should not include protocol (http:// or https://)"
130
- )
131
- if value.startswith('www.'):
132
- raise serializers.ValidationError(
133
- "Domain should not include www prefix"
134
- )
135
- return value.lower()
136
-
137
- def validate_zone_id(self, value):
138
- """Validate zone_id format."""
139
- if len(value) != 32:
140
- raise serializers.ValidationError(
141
- "Zone ID must be exactly 32 characters long"
142
- )
143
- return value
144
-
145
- def validate_account_id(self, value):
146
- """Validate account_id format."""
147
- if len(value) != 32:
148
- raise serializers.ValidationError(
149
- "Account ID must be exactly 32 characters long"
150
- )
151
- return value
152
-
153
-
154
- class CloudflareSiteListSerializer(serializers.ModelSerializer):
155
- """Lightweight serializer for site lists."""
156
-
157
- owner = serializers.StringRelatedField(read_only=True)
158
- is_production = serializers.ReadOnlyField()
159
-
160
- class Meta:
161
- model = CloudflareSite
162
- fields = [
163
- 'id', 'name', 'domain', 'environment', 'project', 'tags',
164
- 'owner', 'current_status', 'maintenance_active', 'is_production',
165
- 'last_maintenance_at', 'created_at'
166
- ]
167
- read_only_fields = fields
168
-
169
-
170
- class SiteGroupSerializer(serializers.ModelSerializer):
171
- """Serializer for SiteGroup model."""
172
-
173
- owner = UserSerializer(read_only=True)
174
- sites = CloudflareSiteListSerializer(many=True, read_only=True)
175
- sites_count = serializers.ReadOnlyField()
176
- active_sites_count = serializers.ReadOnlyField()
177
- maintenance_sites_count = serializers.ReadOnlyField()
178
-
179
- class Meta:
180
- model = SiteGroup
181
- fields = [
182
- 'id', 'name', 'description', 'owner', 'sites', 'sites_count',
183
- 'active_sites_count', 'maintenance_sites_count', 'created_at', 'updated_at'
184
- ]
185
- read_only_fields = [
186
- 'id', 'owner', 'sites', 'sites_count', 'active_sites_count',
187
- 'maintenance_sites_count', 'created_at', 'updated_at'
188
- ]
189
- extra_kwargs = {
190
- 'name': {
191
- 'help_text': 'Name of the site group'
192
- },
193
- 'description': {
194
- 'help_text': 'Optional description of the group purpose'
195
- }
196
- }
197
-
198
-
199
- class SiteGroupCreateSerializer(serializers.ModelSerializer):
200
- """Serializer for creating SiteGroup."""
201
-
202
- class Meta:
203
- model = SiteGroup
204
- fields = ['name', 'description']
205
-
206
- def validate_name(self, value):
207
- """Validate group name uniqueness for user."""
208
- user = self.context['request'].user
209
- if SiteGroup.objects.filter(owner=user, name=value).exists():
210
- raise serializers.ValidationError(
211
- "You already have a group with this name"
212
- )
213
- return value
@@ -1,168 +0,0 @@
1
- # Maintenance Services
2
-
3
- Modern Cloudflare services using the official `cloudflare` Python library.
4
-
5
- ## Overview
6
-
7
- This package provides clean, type-safe, and reliable integration with Cloudflare API v4 for maintenance mode management.
8
-
9
- ## Services
10
-
11
- ### CloudflareClient
12
- Core client with rate limiting, retry logic, and error handling.
13
-
14
- ```python
15
- from django_cfg.apps.maintenance.services import CloudflareClient
16
- from django_cfg.models.cloudflare import CloudflareConfig
17
-
18
- config = CloudflareConfig(api_token="your_token", domain="example.com")
19
- client = CloudflareClient(config)
20
-
21
- # List zones
22
- zones = client.list_zones()
23
-
24
- # Create DNS record
25
- record = client.create_dns_record(
26
- zone_id="zone_id",
27
- record_type="A",
28
- name="api.example.com",
29
- content="1.2.3.4"
30
- )
31
- ```
32
-
33
- ### SiteSyncService
34
- Synchronizes Django CloudflareSite models with Cloudflare zones.
35
-
36
- ```python
37
- from django_cfg.apps.maintenance.services import SiteSyncService
38
-
39
- sync_service = SiteSyncService(config)
40
-
41
- # Sync all sites for a user
42
- stats = sync_service.sync_user_sites(
43
- user=user,
44
- dry_run=False,
45
- force_update=True
46
- )
47
- ```
48
-
49
- ### MaintenanceManager
50
- Manages maintenance mode using Cloudflare Workers.
51
-
52
- ```python
53
- from django_cfg.apps.maintenance.services import MaintenanceManager
54
-
55
- manager = MaintenanceManager(config)
56
-
57
- # Enable maintenance mode
58
- result = manager.enable_maintenance(
59
- site=site,
60
- maintenance_event=event,
61
- custom_message="We'll be back soon!"
62
- )
63
-
64
- # Disable maintenance mode
65
- result = manager.disable_maintenance(site=site)
66
- ```
67
-
68
- ### WorkerManager
69
- High-level Workers management.
70
-
71
- ```python
72
- from django_cfg.apps.maintenance.services import WorkerManager
73
-
74
- worker_manager = WorkerManager(config)
75
-
76
- # Deploy a Worker
77
- result = worker_manager.deploy_worker(
78
- account_id="account_id",
79
- script_name="my-worker",
80
- script_content=worker_code,
81
- routes=[{"zone_id": "zone_id", "pattern": "example.com/*"}]
82
- )
83
- ```
84
-
85
- ### DNSManager
86
- DNS operations with validation and bulk operations.
87
-
88
- ```python
89
- from django_cfg.apps.maintenance.services import DNSManager
90
-
91
- dns_manager = DNSManager(config)
92
-
93
- # Create DNS record
94
- result = dns_manager.create_dns_record(
95
- zone_id="zone_id",
96
- record_type="A",
97
- name="api.example.com",
98
- content="1.2.3.4"
99
- )
100
-
101
- # Bulk create records
102
- result = dns_manager.bulk_create_records(
103
- zone_id="zone_id",
104
- records=[
105
- {"record_type": "A", "name": "api", "content": "1.2.3.4"},
106
- {"record_type": "CNAME", "name": "www", "content": "example.com"}
107
- ]
108
- )
109
- ```
110
-
111
- ## Features
112
-
113
- - **Official Library**: Uses the official `cloudflare` Python library
114
- - **Rate Limiting**: Built-in rate limiting and retry logic
115
- - **Error Handling**: Comprehensive error handling with fallbacks
116
- - **Type Safety**: Full type hints and validation
117
- - **Bulk Operations**: Support for bulk DNS and Worker operations
118
- - **Logging**: Detailed logging for debugging and monitoring
119
- - **Django Integration**: Seamless integration with Django models
120
-
121
- ## Admin Integration
122
-
123
- The services are integrated with Django Admin through Unfold actions:
124
-
125
- - **Sync with Cloudflare**: Sync site DNS records
126
- - **Validate Configuration**: Validate site configuration against Cloudflare
127
- - **Bulk Operations**: Enable/disable maintenance for multiple sites
128
-
129
- ## Management Commands
130
-
131
- ```bash
132
- # Sync sites with Cloudflare
133
- python manage.py sync_cloudflare --user admin@example.com --api-token your_token
134
-
135
- # Dry run
136
- python manage.py sync_cloudflare --user admin@example.com --api-token your_token --dry-run
137
- ```
138
-
139
- ## Requirements
140
-
141
- - `cloudflare>=3.0.0`
142
- - Django 5.2+
143
- - Python 3.10+
144
-
145
- ## Migration from Old Services
146
-
147
- The old services in `services_old/` used manual HTTP requests. The new services provide:
148
-
149
- 1. **Better Error Handling**: Automatic retries and rate limiting
150
- 2. **Type Safety**: Full type hints and validation
151
- 3. **Official Support**: Uses the official Cloudflare library
152
- 4. **Modern Architecture**: Clean, maintainable code structure
153
- 5. **Better Testing**: Easier to mock and test
154
-
155
- ## Configuration
156
-
157
- Services use `CloudflareConfig` from `django_cfg.models.cloudflare`:
158
-
159
- ```python
160
- from django_cfg.models.cloudflare import CloudflareConfig
161
-
162
- config = CloudflareConfig(
163
- api_token="your_cloudflare_api_token",
164
- domain="your_domain.com"
165
- )
166
- ```
167
-
168
- For production, store API tokens securely and implement proper token rotation.