django-cfg 1.5.8__py3-none-any.whl → 1.5.20__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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

Files changed (159) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/api/commands/serializers.py +152 -0
  3. django_cfg/apps/api/commands/views.py +32 -0
  4. django_cfg/apps/business/accounts/management/commands/otp_test.py +5 -2
  5. django_cfg/apps/business/accounts/serializers/profile.py +42 -0
  6. django_cfg/apps/business/agents/management/commands/create_agent.py +5 -194
  7. django_cfg/apps/business/agents/management/commands/load_agent_templates.py +205 -0
  8. django_cfg/apps/business/agents/management/commands/orchestrator_status.py +4 -2
  9. django_cfg/apps/business/knowbase/management/commands/knowbase_stats.py +4 -2
  10. django_cfg/apps/business/knowbase/management/commands/setup_knowbase.py +4 -2
  11. django_cfg/apps/business/newsletter/management/commands/test_newsletter.py +5 -2
  12. django_cfg/apps/business/payments/management/commands/check_payment_status.py +4 -2
  13. django_cfg/apps/business/payments/management/commands/create_payment.py +4 -2
  14. django_cfg/apps/business/payments/management/commands/sync_currencies.py +4 -2
  15. django_cfg/apps/business/support/serializers.py +3 -2
  16. django_cfg/apps/integrations/centrifugo/apps.py +2 -1
  17. django_cfg/apps/integrations/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2 +151 -12
  18. django_cfg/apps/integrations/centrifugo/management/commands/generate_centrifugo_clients.py +6 -6
  19. django_cfg/apps/integrations/centrifugo/serializers/__init__.py +2 -1
  20. django_cfg/apps/integrations/centrifugo/serializers/publishes.py +22 -2
  21. django_cfg/apps/integrations/centrifugo/services/__init__.py +6 -0
  22. django_cfg/apps/integrations/centrifugo/services/client/__init__.py +6 -1
  23. django_cfg/apps/integrations/centrifugo/services/client/direct_client.py +282 -0
  24. django_cfg/apps/integrations/centrifugo/services/publisher.py +371 -0
  25. django_cfg/apps/integrations/centrifugo/services/token_generator.py +122 -0
  26. django_cfg/apps/integrations/centrifugo/urls.py +8 -0
  27. django_cfg/apps/integrations/centrifugo/views/__init__.py +2 -0
  28. django_cfg/apps/integrations/centrifugo/views/monitoring.py +25 -40
  29. django_cfg/apps/integrations/centrifugo/views/testing_api.py +0 -79
  30. django_cfg/apps/integrations/centrifugo/views/token_api.py +101 -0
  31. django_cfg/apps/integrations/centrifugo/views/wrapper.py +257 -0
  32. django_cfg/apps/integrations/grpc/admin/__init__.py +7 -1
  33. django_cfg/apps/integrations/grpc/admin/config.py +113 -9
  34. django_cfg/apps/integrations/grpc/admin/grpc_api_key.py +129 -0
  35. django_cfg/apps/integrations/grpc/admin/grpc_request_log.py +72 -63
  36. django_cfg/apps/integrations/grpc/admin/grpc_server_status.py +236 -0
  37. django_cfg/apps/integrations/grpc/auth/__init__.py +11 -3
  38. django_cfg/apps/integrations/grpc/auth/api_key_auth.py +320 -0
  39. django_cfg/apps/integrations/grpc/centrifugo/__init__.py +29 -0
  40. django_cfg/apps/integrations/grpc/centrifugo/bridge.py +277 -0
  41. django_cfg/apps/integrations/grpc/centrifugo/config.py +167 -0
  42. django_cfg/apps/integrations/grpc/centrifugo/demo.py +626 -0
  43. django_cfg/apps/integrations/grpc/centrifugo/test_publish.py +229 -0
  44. django_cfg/apps/integrations/grpc/centrifugo/transformers.py +89 -0
  45. django_cfg/apps/integrations/grpc/interceptors/__init__.py +3 -1
  46. django_cfg/apps/integrations/grpc/interceptors/centrifugo.py +541 -0
  47. django_cfg/apps/integrations/grpc/interceptors/logging.py +17 -20
  48. django_cfg/apps/integrations/grpc/interceptors/metrics.py +15 -14
  49. django_cfg/apps/integrations/grpc/interceptors/request_logger.py +79 -59
  50. django_cfg/apps/integrations/grpc/management/commands/compile_proto.py +105 -0
  51. django_cfg/apps/integrations/grpc/management/commands/generate_protos.py +185 -0
  52. django_cfg/apps/integrations/grpc/management/commands/rungrpc.py +474 -95
  53. django_cfg/apps/integrations/grpc/management/commands/test_grpc_integration.py +75 -0
  54. django_cfg/apps/integrations/grpc/management/proto/__init__.py +3 -0
  55. django_cfg/apps/integrations/grpc/management/proto/compiler.py +194 -0
  56. django_cfg/apps/integrations/grpc/managers/__init__.py +2 -0
  57. django_cfg/apps/integrations/grpc/managers/grpc_api_key.py +192 -0
  58. django_cfg/apps/integrations/grpc/managers/grpc_server_status.py +19 -11
  59. django_cfg/apps/integrations/grpc/migrations/0005_grpcapikey.py +143 -0
  60. django_cfg/apps/integrations/grpc/migrations/0006_grpcrequestlog_api_key_and_more.py +34 -0
  61. django_cfg/apps/integrations/grpc/models/__init__.py +2 -0
  62. django_cfg/apps/integrations/grpc/models/grpc_api_key.py +198 -0
  63. django_cfg/apps/integrations/grpc/models/grpc_request_log.py +11 -0
  64. django_cfg/apps/integrations/grpc/models/grpc_server_status.py +39 -4
  65. django_cfg/apps/integrations/grpc/serializers/__init__.py +22 -6
  66. django_cfg/apps/integrations/grpc/serializers/api_keys.py +63 -0
  67. django_cfg/apps/integrations/grpc/serializers/charts.py +118 -120
  68. django_cfg/apps/integrations/grpc/serializers/config.py +65 -51
  69. django_cfg/apps/integrations/grpc/serializers/health.py +7 -7
  70. django_cfg/apps/integrations/grpc/serializers/proto_files.py +74 -0
  71. django_cfg/apps/integrations/grpc/serializers/requests.py +13 -7
  72. django_cfg/apps/integrations/grpc/serializers/service_registry.py +181 -112
  73. django_cfg/apps/integrations/grpc/serializers/services.py +14 -32
  74. django_cfg/apps/integrations/grpc/serializers/stats.py +50 -12
  75. django_cfg/apps/integrations/grpc/serializers/testing.py +66 -58
  76. django_cfg/apps/integrations/grpc/services/__init__.py +2 -0
  77. django_cfg/apps/integrations/grpc/services/discovery.py +7 -1
  78. django_cfg/apps/integrations/grpc/services/monitoring_service.py +149 -43
  79. django_cfg/apps/integrations/grpc/services/proto_files_manager.py +268 -0
  80. django_cfg/apps/integrations/grpc/services/service_registry.py +48 -46
  81. django_cfg/apps/integrations/grpc/services/testing_service.py +10 -15
  82. django_cfg/apps/integrations/grpc/urls.py +8 -0
  83. django_cfg/apps/integrations/grpc/utils/SERVER_LOGGING.md +164 -0
  84. django_cfg/apps/integrations/grpc/utils/__init__.py +4 -13
  85. django_cfg/apps/integrations/grpc/utils/integration_test.py +334 -0
  86. django_cfg/apps/integrations/grpc/utils/proto_gen.py +48 -8
  87. django_cfg/apps/integrations/grpc/utils/streaming_logger.py +378 -0
  88. django_cfg/apps/integrations/grpc/views/__init__.py +4 -0
  89. django_cfg/apps/integrations/grpc/views/api_keys.py +255 -0
  90. django_cfg/apps/integrations/grpc/views/charts.py +21 -14
  91. django_cfg/apps/integrations/grpc/views/config.py +8 -6
  92. django_cfg/apps/integrations/grpc/views/monitoring.py +51 -79
  93. django_cfg/apps/integrations/grpc/views/proto_files.py +214 -0
  94. django_cfg/apps/integrations/grpc/views/services.py +30 -21
  95. django_cfg/apps/integrations/grpc/views/testing.py +45 -43
  96. django_cfg/apps/integrations/rq/views/jobs.py +19 -9
  97. django_cfg/apps/integrations/rq/views/schedule.py +7 -3
  98. django_cfg/apps/system/dashboard/serializers/commands.py +25 -1
  99. django_cfg/apps/system/dashboard/serializers/config.py +95 -9
  100. django_cfg/apps/system/dashboard/serializers/statistics.py +9 -4
  101. django_cfg/apps/system/dashboard/services/commands_service.py +12 -1
  102. django_cfg/apps/system/frontend/views.py +87 -6
  103. django_cfg/apps/system/maintenance/management/commands/maintenance.py +5 -2
  104. django_cfg/apps/system/maintenance/management/commands/process_scheduled_maintenance.py +4 -2
  105. django_cfg/apps/system/maintenance/management/commands/sync_cloudflare.py +5 -2
  106. django_cfg/config.py +33 -0
  107. django_cfg/core/builders/security_builder.py +1 -0
  108. django_cfg/core/generation/integration_generators/api.py +2 -0
  109. django_cfg/core/generation/integration_generators/grpc_generator.py +30 -32
  110. django_cfg/management/commands/check_endpoints.py +2 -2
  111. django_cfg/management/commands/check_settings.py +3 -10
  112. django_cfg/management/commands/clear_constance.py +3 -10
  113. django_cfg/management/commands/create_token.py +4 -11
  114. django_cfg/management/commands/list_urls.py +4 -10
  115. django_cfg/management/commands/migrate_all.py +18 -12
  116. django_cfg/management/commands/migrator.py +4 -11
  117. django_cfg/management/commands/script.py +4 -10
  118. django_cfg/management/commands/show_config.py +8 -16
  119. django_cfg/management/commands/show_urls.py +5 -11
  120. django_cfg/management/commands/superuser.py +4 -11
  121. django_cfg/management/commands/tree.py +5 -10
  122. django_cfg/management/utils/README.md +402 -0
  123. django_cfg/management/utils/__init__.py +29 -0
  124. django_cfg/management/utils/mixins.py +176 -0
  125. django_cfg/middleware/pagination.py +53 -54
  126. django_cfg/models/api/grpc/__init__.py +15 -21
  127. django_cfg/models/api/grpc/config.py +155 -73
  128. django_cfg/models/ngrok/config.py +7 -6
  129. django_cfg/modules/django_client/core/generator/python/files_generator.py +5 -13
  130. django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +16 -4
  131. django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +2 -3
  132. django_cfg/modules/django_client/core/generator/typescript/files_generator.py +6 -5
  133. django_cfg/modules/django_client/core/generator/typescript/generator.py +26 -0
  134. django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +7 -1
  135. django_cfg/modules/django_client/core/generator/typescript/models_generator.py +5 -0
  136. django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +11 -0
  137. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +1 -0
  138. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/function.ts.jinja +29 -1
  139. django_cfg/modules/django_client/core/generator/typescript/templates/hooks/hooks.ts.jinja +4 -0
  140. django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +12 -8
  141. django_cfg/modules/django_client/core/ir/schema.py +15 -1
  142. django_cfg/modules/django_client/core/parser/base.py +126 -30
  143. django_cfg/modules/django_client/management/commands/generate_client.py +5 -2
  144. django_cfg/modules/django_client/management/commands/validate_openapi.py +5 -2
  145. django_cfg/modules/django_email/management/commands/test_email.py +4 -10
  146. django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +16 -13
  147. django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -11
  148. django_cfg/modules/django_twilio/management/commands/test_twilio.py +4 -11
  149. django_cfg/modules/django_unfold/navigation.py +6 -18
  150. django_cfg/pyproject.toml +1 -1
  151. django_cfg/registry/modules.py +1 -4
  152. django_cfg/requirements.txt +52 -0
  153. django_cfg/static/frontend/admin.zip +0 -0
  154. {django_cfg-1.5.8.dist-info → django_cfg-1.5.20.dist-info}/METADATA +1 -1
  155. {django_cfg-1.5.8.dist-info → django_cfg-1.5.20.dist-info}/RECORD +158 -121
  156. django_cfg/apps/integrations/grpc/auth/jwt_auth.py +0 -295
  157. {django_cfg-1.5.8.dist-info → django_cfg-1.5.20.dist-info}/WHEEL +0 -0
  158. {django_cfg-1.5.8.dist-info → django_cfg-1.5.20.dist-info}/entry_points.txt +0 -0
  159. {django_cfg-1.5.8.dist-info → django_cfg-1.5.20.dist-info}/licenses/LICENSE +0 -0
@@ -2,10 +2,12 @@
2
2
  Models for gRPC app.
3
3
  """
4
4
 
5
+ from .grpc_api_key import GrpcApiKey
5
6
  from .grpc_request_log import GRPCRequestLog
6
7
  from .grpc_server_status import GRPCServerStatus
7
8
 
8
9
  __all__ = [
10
+ "GrpcApiKey",
9
11
  "GRPCRequestLog",
10
12
  "GRPCServerStatus",
11
13
  ]
@@ -0,0 +1,198 @@
1
+ """
2
+ gRPC API Key Model.
3
+
4
+ Django model for managing API keys used for gRPC authentication.
5
+ Provides secure, revocable authentication for services and CLI tools.
6
+ """
7
+
8
+ import secrets
9
+ from django.conf import settings
10
+ from django.db import models
11
+ from django.utils import timezone
12
+
13
+
14
+ def generate_api_key() -> str:
15
+ """
16
+ Generate a secure random API key.
17
+
18
+ Returns:
19
+ 32-character hex string (128 bits of entropy)
20
+ """
21
+ return secrets.token_hex(32)
22
+
23
+
24
+ class GrpcApiKey(models.Model):
25
+ """
26
+ API Key for gRPC authentication.
27
+
28
+ Provides secure, revocable authentication for:
29
+ - Service-to-service communication
30
+ - CLI tools and scripts
31
+ - Internal systems
32
+ - Development and testing
33
+
34
+ Features:
35
+ - Auto-generated secure keys
36
+ - User association for permissions
37
+ - Expiration support
38
+ - Usage tracking
39
+ - Easy revocation via admin
40
+
41
+ Example:
42
+ >>> # Create API key for a service
43
+ >>> key = GrpcApiKey.objects.create_for_user(
44
+ ... user=admin_user,
45
+ ... name="Analytics Service",
46
+ ... description="Internal analytics microservice"
47
+ ... )
48
+ >>> print(key.key) # Use this in service config
49
+
50
+ >>> # Check if key is valid
51
+ >>> if key.is_valid:
52
+ ... user = key.user
53
+ """
54
+
55
+ # Custom manager
56
+ from ..managers.grpc_api_key import GrpcApiKeyManager
57
+ objects: GrpcApiKeyManager = GrpcApiKeyManager()
58
+
59
+ class KeyTypeChoices(models.TextChoices):
60
+ """Type of API key."""
61
+ SERVICE = "service", "Service-to-Service"
62
+ CLI = "cli", "CLI Tool"
63
+ WEBHOOK = "webhook", "Webhook"
64
+ INTERNAL = "internal", "Internal System"
65
+ DEVELOPMENT = "development", "Development"
66
+
67
+ # Identity
68
+ key = models.CharField(
69
+ max_length=64,
70
+ unique=True,
71
+ default=generate_api_key,
72
+ db_index=True,
73
+ help_text="API key (auto-generated)",
74
+ )
75
+
76
+ name = models.CharField(
77
+ max_length=255,
78
+ help_text="Descriptive name for this key (e.g., 'Analytics Service')",
79
+ )
80
+
81
+ description = models.TextField(
82
+ blank=True,
83
+ help_text="Additional details about this key's purpose",
84
+ )
85
+
86
+ key_type = models.CharField(
87
+ max_length=20,
88
+ choices=KeyTypeChoices.choices,
89
+ default=KeyTypeChoices.SERVICE,
90
+ help_text="Type of API key",
91
+ )
92
+
93
+ # User association
94
+ user = models.ForeignKey(
95
+ settings.AUTH_USER_MODEL,
96
+ on_delete=models.CASCADE,
97
+ related_name="grpc_api_keys",
98
+ help_text="User this key authenticates as",
99
+ )
100
+
101
+ # Status
102
+ is_active = models.BooleanField(
103
+ default=True,
104
+ db_index=True,
105
+ help_text="Whether this key is currently active (can be used)",
106
+ )
107
+
108
+ # Expiration
109
+ expires_at = models.DateTimeField(
110
+ null=True,
111
+ blank=True,
112
+ db_index=True,
113
+ help_text="When this key expires (null = never expires)",
114
+ )
115
+
116
+ # Usage tracking
117
+ last_used_at = models.DateTimeField(
118
+ null=True,
119
+ blank=True,
120
+ help_text="When this key was last used",
121
+ )
122
+
123
+ request_count = models.IntegerField(
124
+ default=0,
125
+ help_text="Total number of requests made with this key",
126
+ )
127
+
128
+ # Metadata
129
+ created_by = models.ForeignKey(
130
+ settings.AUTH_USER_MODEL,
131
+ on_delete=models.SET_NULL,
132
+ null=True,
133
+ blank=True,
134
+ related_name="created_grpc_api_keys",
135
+ help_text="User who created this key",
136
+ )
137
+
138
+ # Timestamps
139
+ created_at = models.DateTimeField(
140
+ auto_now_add=True,
141
+ db_index=True,
142
+ help_text="When this key was created",
143
+ )
144
+
145
+ updated_at = models.DateTimeField(
146
+ auto_now=True,
147
+ help_text="When this key was last updated",
148
+ )
149
+
150
+ class Meta:
151
+ db_table = "django_cfg_grpc_api_key"
152
+ ordering = ["-created_at"]
153
+ indexes = [
154
+ models.Index(fields=["user", "-created_at"]),
155
+ models.Index(fields=["is_active", "-created_at"]),
156
+ models.Index(fields=["expires_at"]),
157
+ models.Index(fields=["key_type", "-created_at"]),
158
+ ]
159
+ verbose_name = "gRPC API Key"
160
+ verbose_name_plural = "gRPC API Keys"
161
+
162
+ def __str__(self) -> str:
163
+ """String representation."""
164
+ status = "✓" if self.is_valid else "✗"
165
+ return f"{status} {self.name} ({self.user.username})"
166
+
167
+ @property
168
+ def is_expired(self) -> bool:
169
+ """Check if key has expired."""
170
+ if not self.expires_at:
171
+ return False
172
+ return timezone.now() > self.expires_at
173
+
174
+ @property
175
+ def is_valid(self) -> bool:
176
+ """Check if key is valid (active and not expired)."""
177
+ return self.is_active and not self.is_expired
178
+
179
+ @property
180
+ def masked_key(self) -> str:
181
+ """Return masked version of key for display."""
182
+ if len(self.key) <= 8:
183
+ return self.key
184
+ return f"{self.key[:4]}...{self.key[-4:]}"
185
+
186
+ def mark_used(self) -> None:
187
+ """Mark this key as used (update last_used_at and increment counter)."""
188
+ self.last_used_at = timezone.now()
189
+ self.request_count += 1
190
+ self.save(update_fields=["last_used_at", "request_count"])
191
+
192
+ def revoke(self) -> None:
193
+ """Revoke this key (set is_active=False)."""
194
+ self.is_active = False
195
+ self.save(update_fields=["is_active"])
196
+
197
+
198
+ __all__ = ["GrpcApiKey", "generate_api_key"]
@@ -9,6 +9,7 @@ from django.conf import settings
9
9
  from django.db import models
10
10
  from django.utils import timezone
11
11
 
12
+ from .grpc_api_key import GrpcApiKey
12
13
 
13
14
  class GRPCRequestLog(models.Model):
14
15
  """
@@ -138,6 +139,15 @@ class GRPCRequestLog(models.Model):
138
139
  help_text="Authenticated user (if applicable)",
139
140
  )
140
141
 
142
+ api_key = models.ForeignKey(
143
+ GrpcApiKey,
144
+ on_delete=models.SET_NULL,
145
+ null=True,
146
+ blank=True,
147
+ related_name="request_logs",
148
+ help_text="API key used for authentication (if applicable)",
149
+ )
150
+
141
151
  is_authenticated = models.BooleanField(
142
152
  default=False,
143
153
  db_index=True,
@@ -186,6 +196,7 @@ class GRPCRequestLog(models.Model):
186
196
  models.Index(fields=["method_name", "-created_at"]),
187
197
  models.Index(fields=["status", "-created_at"]),
188
198
  models.Index(fields=["user", "-created_at"]),
199
+ models.Index(fields=["api_key", "-created_at"]),
189
200
  models.Index(fields=["grpc_status_code", "-created_at"]),
190
201
  ]
191
202
  verbose_name = "gRPC Request Log"
@@ -174,11 +174,17 @@ class GRPCServerStatus(models.Model):
174
174
 
175
175
  @property
176
176
  def is_running(self) -> bool:
177
- """Check if server is currently running."""
177
+ """
178
+ Check if server is currently running.
179
+
180
+ Uses environment-aware detection:
181
+ - Production: Assumes external server (Docker), relies on heartbeat only
182
+ - Development/Test: Checks local process + heartbeat
183
+ """
178
184
  if self.status not in [self.StatusChoices.RUNNING, self.StatusChoices.STARTING]:
179
185
  return False
180
186
 
181
- # Check if process is still alive
187
+ # Check if process is still alive (auto-detects external servers)
182
188
  if not self._is_process_alive():
183
189
  return False
184
190
 
@@ -227,12 +233,41 @@ class GRPCServerStatus(models.Model):
227
233
  return " ".join(parts)
228
234
 
229
235
  def _is_process_alive(self) -> bool:
230
- """Check if the process is still running."""
236
+ """
237
+ Check if the process is still running.
238
+
239
+ Uses environment-aware detection:
240
+ - Production mode: Skip PID check (assumes external server in Docker)
241
+ - Development/Test: Check PID with graceful fallback for containers
242
+ """
243
+ try:
244
+ from django_cfg.core import get_current_config
245
+
246
+ # Auto-detect based on env_mode
247
+ config = get_current_config()
248
+ if config and str(config.env_mode) == "production":
249
+ # Production = external server in separate container
250
+ # Don't check PID, rely on heartbeat only
251
+ return True
252
+
253
+ except Exception:
254
+ # Config not available, use fallback logic
255
+ pass
256
+
257
+ # Development/Test or fallback: check PID with graceful handling
231
258
  try:
232
259
  # Send signal 0 to check if process exists
233
260
  os.kill(self.pid, 0)
234
261
  return True
235
- except (OSError, ProcessLookupError):
262
+ except ProcessLookupError:
263
+ # PID not found - could be different namespace (Docker)
264
+ # Don't mark as dead immediately, rely on heartbeat
265
+ return True
266
+ except PermissionError:
267
+ # Process exists but no permission to signal
268
+ return True
269
+ except OSError:
270
+ # Other OS error (e.g., process died)
236
271
  return False
237
272
 
238
273
  def mark_running(self):
@@ -2,6 +2,17 @@
2
2
  Pydantic serializers for gRPC monitoring API.
3
3
  """
4
4
 
5
+ from .api_keys import (
6
+ ApiKeyListSerializer,
7
+ ApiKeySerializer,
8
+ ApiKeyStatsSerializer,
9
+ )
10
+ from .proto_files import (
11
+ ProtoFileDetailSerializer,
12
+ ProtoFileListSerializer,
13
+ ProtoGenerateRequestSerializer,
14
+ ProtoGenerateResponseSerializer,
15
+ )
5
16
  from .charts import (
6
17
  DashboardChartsSerializer,
7
18
  ErrorDistributionChartSerializer,
@@ -17,14 +28,12 @@ from .requests import RecentRequestsSerializer
17
28
  from .service_registry import (
18
29
  MethodDetailSerializer,
19
30
  ServiceDetailSerializer,
20
- ServiceListSerializer as ServiceRegistryListSerializer,
31
+ ServiceListSerializer,
21
32
  ServiceMethodsSerializer,
22
33
  )
23
34
  from .services import (
24
35
  MethodListSerializer,
25
36
  MethodStatsSerializer,
26
- MonitoringServiceStatsSerializer,
27
- ServiceListSerializer,
28
37
  )
29
38
  from .stats import GRPCOverviewStatsSerializer
30
39
  from .testing import (
@@ -39,15 +48,13 @@ __all__ = [
39
48
  "GRPCHealthCheckSerializer",
40
49
  "GRPCOverviewStatsSerializer",
41
50
  "RecentRequestsSerializer",
42
- "MonitoringServiceStatsSerializer",
43
- "ServiceListSerializer",
44
51
  "MethodStatsSerializer",
45
52
  "MethodListSerializer",
46
53
  # Config
47
54
  "GRPCConfigSerializer",
48
55
  "GRPCServerInfoSerializer",
49
56
  # Service Registry
50
- "ServiceRegistryListSerializer",
57
+ "ServiceListSerializer",
51
58
  "ServiceDetailSerializer",
52
59
  "ServiceMethodsSerializer",
53
60
  "MethodDetailSerializer",
@@ -64,4 +71,13 @@ __all__ = [
64
71
  "ServerLifecycleChartSerializer",
65
72
  "ErrorDistributionChartSerializer",
66
73
  "DashboardChartsSerializer",
74
+ # API Keys
75
+ "ApiKeySerializer",
76
+ "ApiKeyListSerializer",
77
+ "ApiKeyStatsSerializer",
78
+ # Proto Files
79
+ "ProtoFileDetailSerializer",
80
+ "ProtoFileListSerializer",
81
+ "ProtoGenerateRequestSerializer",
82
+ "ProtoGenerateResponseSerializer",
67
83
  ]
@@ -0,0 +1,63 @@
1
+ """
2
+ DRF serializers for gRPC API Keys.
3
+
4
+ Read-only serializers for listing and viewing API keys.
5
+ Create/Update/Delete operations handled through Django Admin.
6
+ """
7
+
8
+ from rest_framework import serializers
9
+
10
+
11
+ class ApiKeySerializer(serializers.Serializer):
12
+ """API Key information (read-only)."""
13
+
14
+ id = serializers.IntegerField(help_text="Database ID")
15
+ name = serializers.CharField(help_text="Key name/description")
16
+ key_type = serializers.CharField(help_text="Type of API key")
17
+ masked_key = serializers.CharField(help_text="Masked API key (first 4 and last 4 chars)")
18
+ is_active = serializers.BooleanField(help_text="Whether key is active")
19
+ is_valid = serializers.BooleanField(help_text="Whether key is valid (active and not expired)")
20
+ user_id = serializers.IntegerField(help_text="User ID")
21
+ username = serializers.CharField(help_text="Username")
22
+ user_email = serializers.CharField(help_text="User email", allow_blank=True)
23
+ request_count = serializers.IntegerField(help_text="Total requests made with this key")
24
+ last_used_at = serializers.DateTimeField(
25
+ allow_null=True,
26
+ help_text="When key was last used"
27
+ )
28
+ expires_at = serializers.DateTimeField(
29
+ allow_null=True,
30
+ help_text="When key expires (null = never)"
31
+ )
32
+ created_at = serializers.DateTimeField(help_text="When key was created")
33
+ created_by = serializers.CharField(
34
+ allow_null=True,
35
+ help_text="User who created this key"
36
+ )
37
+
38
+
39
+ class ApiKeyListSerializer(serializers.Serializer):
40
+ """List of API keys response."""
41
+
42
+ results = ApiKeySerializer(many=True, help_text="List of API keys")
43
+ count = serializers.IntegerField(help_text="Total number of API keys")
44
+
45
+
46
+ class ApiKeyStatsSerializer(serializers.Serializer):
47
+ """API Key usage statistics."""
48
+
49
+ total_keys = serializers.IntegerField(help_text="Total API keys")
50
+ active_keys = serializers.IntegerField(help_text="Active API keys")
51
+ expired_keys = serializers.IntegerField(help_text="Expired API keys")
52
+ total_requests = serializers.IntegerField(help_text="Total requests across all keys")
53
+ keys_by_type = serializers.DictField(
54
+ child=serializers.IntegerField(),
55
+ help_text="Count of keys by type"
56
+ )
57
+
58
+
59
+ __all__ = [
60
+ "ApiKeySerializer",
61
+ "ApiKeyListSerializer",
62
+ "ApiKeyStatsSerializer",
63
+ ]