django-cfg 1.5.8__py3-none-any.whl → 1.5.14__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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/api/commands/serializers.py +152 -0
- django_cfg/apps/api/commands/views.py +32 -0
- django_cfg/apps/business/accounts/management/commands/otp_test.py +5 -2
- django_cfg/apps/business/agents/management/commands/create_agent.py +5 -194
- django_cfg/apps/business/agents/management/commands/load_agent_templates.py +205 -0
- django_cfg/apps/business/agents/management/commands/orchestrator_status.py +4 -2
- django_cfg/apps/business/knowbase/management/commands/knowbase_stats.py +4 -2
- django_cfg/apps/business/knowbase/management/commands/setup_knowbase.py +4 -2
- django_cfg/apps/business/newsletter/management/commands/test_newsletter.py +5 -2
- django_cfg/apps/business/payments/management/commands/check_payment_status.py +4 -2
- django_cfg/apps/business/payments/management/commands/create_payment.py +4 -2
- django_cfg/apps/business/payments/management/commands/sync_currencies.py +4 -2
- django_cfg/apps/integrations/centrifugo/management/commands/generate_centrifugo_clients.py +5 -5
- django_cfg/apps/integrations/centrifugo/serializers/__init__.py +2 -1
- django_cfg/apps/integrations/centrifugo/serializers/publishes.py +22 -2
- django_cfg/apps/integrations/centrifugo/views/monitoring.py +25 -40
- django_cfg/apps/integrations/grpc/admin/__init__.py +7 -1
- django_cfg/apps/integrations/grpc/admin/config.py +113 -9
- django_cfg/apps/integrations/grpc/admin/grpc_api_key.py +129 -0
- django_cfg/apps/integrations/grpc/admin/grpc_request_log.py +72 -63
- django_cfg/apps/integrations/grpc/admin/grpc_server_status.py +236 -0
- django_cfg/apps/integrations/grpc/auth/__init__.py +11 -3
- django_cfg/apps/integrations/grpc/auth/api_key_auth.py +320 -0
- django_cfg/apps/integrations/grpc/interceptors/logging.py +17 -20
- django_cfg/apps/integrations/grpc/interceptors/metrics.py +15 -14
- django_cfg/apps/integrations/grpc/interceptors/request_logger.py +79 -59
- django_cfg/apps/integrations/grpc/management/commands/generate_protos.py +130 -0
- django_cfg/apps/integrations/grpc/management/commands/rungrpc.py +171 -96
- django_cfg/apps/integrations/grpc/management/commands/test_grpc_integration.py +75 -0
- django_cfg/apps/integrations/grpc/managers/__init__.py +2 -0
- django_cfg/apps/integrations/grpc/managers/grpc_api_key.py +192 -0
- django_cfg/apps/integrations/grpc/managers/grpc_server_status.py +19 -11
- django_cfg/apps/integrations/grpc/migrations/0005_grpcapikey.py +143 -0
- django_cfg/apps/integrations/grpc/migrations/0006_grpcrequestlog_api_key_and_more.py +34 -0
- django_cfg/apps/integrations/grpc/models/__init__.py +2 -0
- django_cfg/apps/integrations/grpc/models/grpc_api_key.py +198 -0
- django_cfg/apps/integrations/grpc/models/grpc_request_log.py +11 -0
- django_cfg/apps/integrations/grpc/models/grpc_server_status.py +39 -4
- django_cfg/apps/integrations/grpc/serializers/__init__.py +22 -6
- django_cfg/apps/integrations/grpc/serializers/api_keys.py +63 -0
- django_cfg/apps/integrations/grpc/serializers/charts.py +118 -120
- django_cfg/apps/integrations/grpc/serializers/config.py +65 -51
- django_cfg/apps/integrations/grpc/serializers/health.py +7 -7
- django_cfg/apps/integrations/grpc/serializers/proto_files.py +74 -0
- django_cfg/apps/integrations/grpc/serializers/requests.py +13 -7
- django_cfg/apps/integrations/grpc/serializers/service_registry.py +181 -112
- django_cfg/apps/integrations/grpc/serializers/services.py +14 -32
- django_cfg/apps/integrations/grpc/serializers/stats.py +50 -12
- django_cfg/apps/integrations/grpc/serializers/testing.py +66 -58
- django_cfg/apps/integrations/grpc/services/__init__.py +2 -0
- django_cfg/apps/integrations/grpc/services/monitoring_service.py +149 -43
- django_cfg/apps/integrations/grpc/services/proto_files_manager.py +268 -0
- django_cfg/apps/integrations/grpc/services/service_registry.py +48 -46
- django_cfg/apps/integrations/grpc/services/testing_service.py +10 -15
- django_cfg/apps/integrations/grpc/urls.py +8 -0
- django_cfg/apps/integrations/grpc/utils/__init__.py +4 -13
- django_cfg/apps/integrations/grpc/utils/integration_test.py +334 -0
- django_cfg/apps/integrations/grpc/utils/proto_gen.py +48 -8
- django_cfg/apps/integrations/grpc/utils/streaming_logger.py +177 -0
- django_cfg/apps/integrations/grpc/views/__init__.py +4 -0
- django_cfg/apps/integrations/grpc/views/api_keys.py +255 -0
- django_cfg/apps/integrations/grpc/views/charts.py +21 -14
- django_cfg/apps/integrations/grpc/views/config.py +8 -6
- django_cfg/apps/integrations/grpc/views/monitoring.py +51 -79
- django_cfg/apps/integrations/grpc/views/proto_files.py +214 -0
- django_cfg/apps/integrations/grpc/views/services.py +30 -21
- django_cfg/apps/integrations/grpc/views/testing.py +45 -43
- django_cfg/apps/integrations/rq/views/jobs.py +19 -9
- django_cfg/apps/integrations/rq/views/schedule.py +7 -3
- django_cfg/apps/system/dashboard/serializers/commands.py +25 -1
- django_cfg/apps/system/dashboard/services/commands_service.py +12 -1
- django_cfg/apps/system/maintenance/management/commands/maintenance.py +5 -2
- django_cfg/apps/system/maintenance/management/commands/process_scheduled_maintenance.py +4 -2
- django_cfg/apps/system/maintenance/management/commands/sync_cloudflare.py +5 -2
- django_cfg/config.py +33 -0
- django_cfg/core/generation/integration_generators/grpc_generator.py +30 -32
- django_cfg/management/commands/check_endpoints.py +2 -2
- django_cfg/management/commands/check_settings.py +3 -10
- django_cfg/management/commands/clear_constance.py +3 -10
- django_cfg/management/commands/create_token.py +4 -11
- django_cfg/management/commands/list_urls.py +4 -10
- django_cfg/management/commands/migrate_all.py +18 -12
- django_cfg/management/commands/migrator.py +4 -11
- django_cfg/management/commands/script.py +4 -10
- django_cfg/management/commands/show_config.py +8 -16
- django_cfg/management/commands/show_urls.py +5 -11
- django_cfg/management/commands/superuser.py +4 -11
- django_cfg/management/commands/tree.py +5 -10
- django_cfg/management/utils/README.md +402 -0
- django_cfg/management/utils/__init__.py +29 -0
- django_cfg/management/utils/mixins.py +176 -0
- django_cfg/middleware/pagination.py +53 -54
- django_cfg/models/api/grpc/__init__.py +15 -21
- django_cfg/models/api/grpc/config.py +155 -73
- django_cfg/models/ngrok/config.py +7 -6
- django_cfg/modules/django_client/core/generator/python/files_generator.py +5 -13
- django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +16 -4
- django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +2 -3
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +6 -5
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +12 -8
- django_cfg/modules/django_client/core/parser/base.py +114 -30
- django_cfg/modules/django_client/management/commands/generate_client.py +5 -2
- django_cfg/modules/django_client/management/commands/validate_openapi.py +5 -2
- django_cfg/modules/django_email/management/commands/test_email.py +4 -10
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +16 -13
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -11
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +4 -11
- django_cfg/modules/django_unfold/navigation.py +6 -18
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/modules.py +1 -4
- django_cfg/requirements.txt +52 -0
- django_cfg/static/frontend/admin.zip +0 -0
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/METADATA +1 -1
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/RECORD +118 -97
- django_cfg/apps/integrations/grpc/auth/jwt_auth.py +0 -295
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/WHEEL +0 -0
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.5.8.dist-info → django_cfg-1.5.14.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,17 +3,19 @@ Knowledge Base statistics command.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from django.contrib.auth import get_user_model
|
|
6
|
-
from django.core.management.base import BaseCommand
|
|
7
6
|
from django.db import models
|
|
8
7
|
from django.db.models import Avg, Count, ExpressionWrapper, F, Q, Sum
|
|
9
8
|
from django.db.models.functions import Extract
|
|
10
9
|
|
|
10
|
+
from django_cfg.management.utils import SafeCommand
|
|
11
|
+
|
|
11
12
|
User = get_user_model()
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class Command(
|
|
15
|
+
class Command(SafeCommand):
|
|
15
16
|
"""Display Knowledge Base statistics."""
|
|
16
17
|
|
|
18
|
+
command_name = 'knowbase_stats'
|
|
17
19
|
help = 'Display Knowledge Base usage statistics'
|
|
18
20
|
|
|
19
21
|
def add_arguments(self, parser):
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
Setup command for Knowledge Base application.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from django.core.management.base import BaseCommand
|
|
6
5
|
from django.db import connection
|
|
7
6
|
|
|
7
|
+
from django_cfg.management.utils import AdminCommand
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
class Command(AdminCommand):
|
|
10
11
|
"""Setup Knowledge Base with pgvector extension and initial data."""
|
|
11
12
|
|
|
13
|
+
command_name = 'setup_knowbase'
|
|
12
14
|
help = 'Setup Knowledge Base with pgvector extension and run migrations'
|
|
13
15
|
|
|
14
16
|
def add_arguments(self, parser):
|
|
@@ -3,7 +3,9 @@ Management command to test newsletter sending functionality.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from django.contrib.auth import get_user_model
|
|
6
|
-
from django.core.management.base import
|
|
6
|
+
from django.core.management.base import CommandError
|
|
7
|
+
|
|
8
|
+
from django_cfg.management.utils import SafeCommand
|
|
7
9
|
|
|
8
10
|
from django_cfg.apps.business.newsletter.models import Newsletter, NewsletterCampaign, NewsletterSubscription
|
|
9
11
|
from django_cfg.apps.business.newsletter.services.email_service import NewsletterEmailService
|
|
@@ -11,7 +13,8 @@ from django_cfg.apps.business.newsletter.services.email_service import Newslette
|
|
|
11
13
|
User = get_user_model()
|
|
12
14
|
|
|
13
15
|
|
|
14
|
-
class Command(
|
|
16
|
+
class Command(SafeCommand):
|
|
17
|
+
command_name = 'test_newsletter'
|
|
15
18
|
help = 'Test newsletter sending functionality'
|
|
16
19
|
|
|
17
20
|
def add_arguments(self, parser):
|
|
@@ -7,11 +7,12 @@ Uses questionary for interactive selection or accepts payment ID as argument.
|
|
|
7
7
|
from uuid import UUID
|
|
8
8
|
|
|
9
9
|
import questionary
|
|
10
|
-
from django.core.management.base import BaseCommand
|
|
11
10
|
from rich.console import Console
|
|
12
11
|
from rich.panel import Panel
|
|
13
12
|
from rich.table import Table
|
|
14
13
|
|
|
14
|
+
from django_cfg.management.utils import InteractiveCommand
|
|
15
|
+
|
|
15
16
|
from django_cfg.apps.business.payments.models import Payment
|
|
16
17
|
from django_cfg.apps.business.payments.services import PaymentService, CheckStatusRequest
|
|
17
18
|
from django_cfg.apps.business.payments.api.views import get_nowpayments_provider
|
|
@@ -19,7 +20,8 @@ from django_cfg.apps.business.payments.api.views import get_nowpayments_provider
|
|
|
19
20
|
console = Console()
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
class Command(
|
|
23
|
+
class Command(InteractiveCommand):
|
|
24
|
+
command_name = 'check_payment_status'
|
|
23
25
|
help = 'Check payment status interactively or by payment ID'
|
|
24
26
|
|
|
25
27
|
def add_arguments(self, parser):
|
|
@@ -8,11 +8,12 @@ from decimal import Decimal, InvalidOperation
|
|
|
8
8
|
|
|
9
9
|
import questionary
|
|
10
10
|
from django.contrib.auth import get_user_model
|
|
11
|
-
from django.core.management.base import BaseCommand
|
|
12
11
|
from rich.console import Console
|
|
13
12
|
from rich.panel import Panel
|
|
14
13
|
from rich.table import Table
|
|
15
14
|
|
|
15
|
+
from django_cfg.management.utils import InteractiveCommand
|
|
16
|
+
|
|
16
17
|
from django_cfg.apps.business.payments.models import Currency, Payment
|
|
17
18
|
from django_cfg.apps.business.payments.services import PaymentService, CreatePaymentRequest
|
|
18
19
|
from django_cfg.apps.business.payments.api.views import get_nowpayments_provider
|
|
@@ -21,7 +22,8 @@ User = get_user_model()
|
|
|
21
22
|
console = Console()
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
class Command(
|
|
25
|
+
class Command(InteractiveCommand):
|
|
26
|
+
command_name = 'create_payment'
|
|
25
27
|
help = 'Create a payment interactively using questionary wizard'
|
|
26
28
|
|
|
27
29
|
def add_arguments(self, parser):
|
|
@@ -5,19 +5,21 @@ Fetches available currencies from NowPayments and updates local database.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import questionary
|
|
8
|
-
from django.core.management.base import BaseCommand
|
|
9
8
|
from rich.console import Console
|
|
10
9
|
from rich.panel import Panel
|
|
11
10
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
12
11
|
from rich.table import Table
|
|
13
12
|
|
|
13
|
+
from django_cfg.management.utils import AdminCommand
|
|
14
|
+
|
|
14
15
|
from django_cfg.apps.business.payments.models import Currency
|
|
15
16
|
from django_cfg.apps.business.payments.api.views import get_nowpayments_provider
|
|
16
17
|
|
|
17
18
|
console = Console()
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class Command(
|
|
21
|
+
class Command(AdminCommand):
|
|
22
|
+
command_name = 'sync_currencies'
|
|
21
23
|
help = 'Sync currencies from NowPayments provider'
|
|
22
24
|
|
|
23
25
|
def add_arguments(self, parser):
|
|
@@ -6,25 +6,25 @@ Usage:
|
|
|
6
6
|
python manage.py generate_centrifugo_clients -o ./clients --python --verbose
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import logging
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
from typing import List
|
|
12
11
|
|
|
13
|
-
from django.core.management.base import
|
|
12
|
+
from django.core.management.base import CommandError
|
|
14
13
|
from django.utils.termcolors import colorize
|
|
15
14
|
|
|
15
|
+
from django_cfg.management.utils import AdminCommand
|
|
16
|
+
|
|
16
17
|
from django_cfg.apps.integrations.centrifugo.codegen.discovery import discover_rpc_methods_from_router
|
|
17
18
|
from django_cfg.apps.integrations.centrifugo.codegen.generators.python_thin import PythonThinGenerator
|
|
18
19
|
from django_cfg.apps.integrations.centrifugo.codegen.generators.typescript_thin import TypeScriptThinGenerator
|
|
19
20
|
from django_cfg.apps.integrations.centrifugo.codegen.generators.go_thin import GoThinGenerator
|
|
20
21
|
from django_cfg.apps.integrations.centrifugo.router import get_global_router
|
|
21
22
|
|
|
22
|
-
logger = logging.getLogger(__name__)
|
|
23
|
-
|
|
24
23
|
|
|
25
|
-
class Command(
|
|
24
|
+
class Command(AdminCommand):
|
|
26
25
|
"""Generate type-safe client SDKs for Centrifugo WebSocket RPC."""
|
|
27
26
|
|
|
27
|
+
command_name = 'generate_centrifugo_clients'
|
|
28
28
|
help = "Generate type-safe client SDKs for Centrifugo WebSocket RPC from @websocket_rpc handlers"
|
|
29
29
|
|
|
30
30
|
def add_arguments(self, parser):
|
|
@@ -16,13 +16,14 @@ from .admin_api import (
|
|
|
16
16
|
)
|
|
17
17
|
from .channels import ChannelListSerializer, ChannelStatsSerializer
|
|
18
18
|
from .health import HealthCheckSerializer
|
|
19
|
-
from .publishes import RecentPublishesSerializer
|
|
19
|
+
from .publishes import PublishSerializer, RecentPublishesSerializer
|
|
20
20
|
from .stats import CentrifugoOverviewStatsSerializer
|
|
21
21
|
|
|
22
22
|
__all__ = [
|
|
23
23
|
# Monitoring API (Django logs)
|
|
24
24
|
"HealthCheckSerializer",
|
|
25
25
|
"CentrifugoOverviewStatsSerializer",
|
|
26
|
+
"PublishSerializer",
|
|
26
27
|
"RecentPublishesSerializer",
|
|
27
28
|
"ChannelStatsSerializer",
|
|
28
29
|
"ChannelListSerializer",
|
|
@@ -2,11 +2,31 @@
|
|
|
2
2
|
Publishes serializers for Centrifugo monitoring API.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
5
8
|
from pydantic import BaseModel, Field
|
|
9
|
+
from rest_framework import serializers
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PublishSerializer(serializers.Serializer):
|
|
13
|
+
"""Single publish item for DRF pagination."""
|
|
14
|
+
|
|
15
|
+
message_id = serializers.CharField()
|
|
16
|
+
channel = serializers.CharField()
|
|
17
|
+
status = serializers.CharField()
|
|
18
|
+
wait_for_ack = serializers.BooleanField()
|
|
19
|
+
acks_received = serializers.IntegerField()
|
|
20
|
+
acks_expected = serializers.IntegerField()
|
|
21
|
+
duration_ms = serializers.FloatField(allow_null=True)
|
|
22
|
+
created_at = serializers.DateTimeField()
|
|
23
|
+
completed_at = serializers.DateTimeField(allow_null=True)
|
|
24
|
+
error_code = serializers.CharField(allow_null=True)
|
|
25
|
+
error_message = serializers.CharField(allow_null=True)
|
|
6
26
|
|
|
7
27
|
|
|
8
28
|
class RecentPublishesSerializer(BaseModel):
|
|
9
|
-
"""Recent publishes list."""
|
|
29
|
+
"""Recent publishes list (DEPRECATED - use DRF pagination instead)."""
|
|
10
30
|
|
|
11
31
|
publishes: list[dict] = Field(description="List of recent publishes")
|
|
12
32
|
count: int = Field(description="Number of publishes returned")
|
|
@@ -15,4 +35,4 @@ class RecentPublishesSerializer(BaseModel):
|
|
|
15
35
|
has_more: bool = Field(default=False, description="Whether more results are available")
|
|
16
36
|
|
|
17
37
|
|
|
18
|
-
__all__ = ["RecentPublishesSerializer"]
|
|
38
|
+
__all__ = ["PublishSerializer", "RecentPublishesSerializer"]
|
|
@@ -23,6 +23,7 @@ from ..serializers import (
|
|
|
23
23
|
ChannelListSerializer,
|
|
24
24
|
ChannelStatsSerializer,
|
|
25
25
|
HealthCheckSerializer,
|
|
26
|
+
PublishSerializer,
|
|
26
27
|
RecentPublishesSerializer,
|
|
27
28
|
)
|
|
28
29
|
from ..services import get_centrifugo_config
|
|
@@ -30,18 +31,20 @@ from ..services import get_centrifugo_config
|
|
|
30
31
|
logger = get_logger("centrifugo.monitoring")
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
class CentrifugoMonitorViewSet(AdminAPIMixin, viewsets.
|
|
34
|
+
class CentrifugoMonitorViewSet(AdminAPIMixin, viewsets.GenericViewSet):
|
|
34
35
|
"""
|
|
35
36
|
ViewSet for Centrifugo monitoring and statistics.
|
|
36
37
|
|
|
37
38
|
Provides comprehensive monitoring data for Centrifugo publishes including:
|
|
38
39
|
- Health checks
|
|
39
40
|
- Overview statistics
|
|
40
|
-
- Recent publishes
|
|
41
|
+
- Recent publishes (with DRF pagination)
|
|
41
42
|
- Channel-level statistics
|
|
42
43
|
Requires admin authentication (JWT, Session, or Basic Auth).
|
|
43
44
|
"""
|
|
44
45
|
|
|
46
|
+
serializer_class = PublishSerializer
|
|
47
|
+
|
|
45
48
|
@extend_schema(
|
|
46
49
|
tags=["Centrifugo Monitoring"],
|
|
47
50
|
summary="Get Centrifugo health status",
|
|
@@ -126,13 +129,20 @@ class CentrifugoMonitorViewSet(AdminAPIMixin, viewsets.ViewSet):
|
|
|
126
129
|
@extend_schema(
|
|
127
130
|
tags=["Centrifugo Monitoring"],
|
|
128
131
|
summary="Get recent publishes",
|
|
129
|
-
description="Returns a list of recent Centrifugo publishes with their details.",
|
|
132
|
+
description="Returns a paginated list of recent Centrifugo publishes with their details. Uses standard DRF pagination.",
|
|
130
133
|
parameters=[
|
|
131
134
|
OpenApiParameter(
|
|
132
|
-
name="
|
|
135
|
+
name="page",
|
|
133
136
|
type=OpenApiTypes.INT,
|
|
134
137
|
location=OpenApiParameter.QUERY,
|
|
135
|
-
description="
|
|
138
|
+
description="Page number",
|
|
139
|
+
required=False,
|
|
140
|
+
),
|
|
141
|
+
OpenApiParameter(
|
|
142
|
+
name="page_size",
|
|
143
|
+
type=OpenApiTypes.INT,
|
|
144
|
+
location=OpenApiParameter.QUERY,
|
|
145
|
+
description="Items per page (default: 10, max: 100)",
|
|
136
146
|
required=False,
|
|
137
147
|
),
|
|
138
148
|
OpenApiParameter(
|
|
@@ -149,16 +159,9 @@ class CentrifugoMonitorViewSet(AdminAPIMixin, viewsets.ViewSet):
|
|
|
149
159
|
description="Filter by status (success, failed, timeout, pending, partial)",
|
|
150
160
|
required=False,
|
|
151
161
|
),
|
|
152
|
-
OpenApiParameter(
|
|
153
|
-
name="offset",
|
|
154
|
-
type=OpenApiTypes.INT,
|
|
155
|
-
location=OpenApiParameter.QUERY,
|
|
156
|
-
description="Offset for pagination (default: 0)",
|
|
157
|
-
required=False,
|
|
158
|
-
),
|
|
159
162
|
],
|
|
160
163
|
responses={
|
|
161
|
-
200:
|
|
164
|
+
200: PublishSerializer(many=True),
|
|
162
165
|
400: {"description": "Invalid parameters"},
|
|
163
166
|
},
|
|
164
167
|
)
|
|
@@ -166,28 +169,23 @@ class CentrifugoMonitorViewSet(AdminAPIMixin, viewsets.ViewSet):
|
|
|
166
169
|
def publishes(self, request):
|
|
167
170
|
"""Get recent Centrifugo publishes."""
|
|
168
171
|
try:
|
|
169
|
-
count = int(request.GET.get("count", 50))
|
|
170
|
-
count = min(count, 200) # Max 200
|
|
171
|
-
|
|
172
172
|
channel = request.GET.get("channel")
|
|
173
|
-
status_filter = request.GET.get("status")
|
|
174
|
-
offset = int(request.GET.get("offset", 0)) # NEW: offset for pagination
|
|
173
|
+
status_filter = request.GET.get("status")
|
|
175
174
|
|
|
176
175
|
queryset = CentrifugoLog.objects.all()
|
|
177
176
|
|
|
178
177
|
if channel:
|
|
179
178
|
queryset = queryset.filter(channel=channel)
|
|
180
179
|
|
|
181
|
-
#
|
|
180
|
+
# Filter by status
|
|
182
181
|
if status_filter and status_filter in ["success", "failed", "timeout", "pending", "partial"]:
|
|
183
182
|
queryset = queryset.filter(status=status_filter)
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
total = queryset.count()
|
|
184
|
+
queryset = queryset.order_by("-created_at")
|
|
187
185
|
|
|
188
|
-
#
|
|
186
|
+
# Convert queryset to list of dicts for serialization
|
|
189
187
|
publishes_list = list(
|
|
190
|
-
queryset.
|
|
188
|
+
queryset.values(
|
|
191
189
|
"message_id",
|
|
192
190
|
"channel",
|
|
193
191
|
"status",
|
|
@@ -202,23 +200,10 @@ class CentrifugoMonitorViewSet(AdminAPIMixin, viewsets.ViewSet):
|
|
|
202
200
|
)
|
|
203
201
|
)
|
|
204
202
|
|
|
205
|
-
#
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if pub["completed_at"]:
|
|
210
|
-
pub["completed_at"] = pub["completed_at"].isoformat()
|
|
211
|
-
|
|
212
|
-
response_data = {
|
|
213
|
-
"publishes": publishes_list,
|
|
214
|
-
"count": len(publishes_list),
|
|
215
|
-
"total_available": total,
|
|
216
|
-
"offset": offset, # NEW: for pagination
|
|
217
|
-
"has_more": (offset + count) < total, # NEW: pagination helper
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
serializer = RecentPublishesSerializer(**response_data)
|
|
221
|
-
return Response(serializer.model_dump())
|
|
203
|
+
# Use DRF pagination
|
|
204
|
+
page = self.paginate_queryset(publishes_list)
|
|
205
|
+
serializer = PublishSerializer(page, many=True)
|
|
206
|
+
return self.get_paginated_response(serializer.data)
|
|
222
207
|
|
|
223
208
|
except ValueError as e:
|
|
224
209
|
logger.warning(f"Recent publishes validation error: {e}")
|
|
@@ -2,10 +2,16 @@
|
|
|
2
2
|
Admin interface for gRPC app.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .config import grpcrequestlog_config
|
|
5
|
+
from .config import grpcapikey_config, grpcrequestlog_config, grpcserverstatus_config
|
|
6
|
+
from .grpc_api_key import GrpcApiKeyAdmin
|
|
6
7
|
from .grpc_request_log import GRPCRequestLogAdmin
|
|
8
|
+
from .grpc_server_status import GRPCServerStatusAdmin
|
|
7
9
|
|
|
8
10
|
__all__ = [
|
|
11
|
+
"GrpcApiKeyAdmin",
|
|
9
12
|
"GRPCRequestLogAdmin",
|
|
13
|
+
"GRPCServerStatusAdmin",
|
|
14
|
+
"grpcapikey_config",
|
|
10
15
|
"grpcrequestlog_config",
|
|
16
|
+
"grpcserverstatus_config",
|
|
11
17
|
]
|
|
@@ -7,31 +7,33 @@ Declarative AdminConfig using PydanticAdmin patterns.
|
|
|
7
7
|
from django_cfg.modules.django_admin import (
|
|
8
8
|
AdminConfig,
|
|
9
9
|
BadgeField,
|
|
10
|
+
BooleanField,
|
|
10
11
|
DateTimeField,
|
|
12
|
+
FieldsetConfig,
|
|
11
13
|
Icons,
|
|
14
|
+
TextField,
|
|
12
15
|
UserField,
|
|
13
16
|
)
|
|
14
17
|
|
|
15
|
-
from ..models import GRPCRequestLog, GRPCServerStatus
|
|
18
|
+
from ..models import GRPCRequestLog, GRPCServerStatus, GrpcApiKey
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
# Declarative configuration for GRPCRequestLog
|
|
19
22
|
grpcrequestlog_config = AdminConfig(
|
|
20
23
|
model=GRPCRequestLog,
|
|
21
24
|
# Performance optimization
|
|
22
|
-
select_related=["user"],
|
|
25
|
+
select_related=["user", "api_key"],
|
|
23
26
|
|
|
24
27
|
# List display
|
|
25
28
|
list_display=[
|
|
26
|
-
"full_method",
|
|
27
29
|
"service_badge",
|
|
28
30
|
"method_badge",
|
|
29
31
|
"status",
|
|
30
32
|
"grpc_status_code_display",
|
|
31
33
|
"user",
|
|
34
|
+
"api_key_display",
|
|
32
35
|
"duration_display",
|
|
33
36
|
"created_at",
|
|
34
|
-
"completed_at"
|
|
35
37
|
],
|
|
36
38
|
|
|
37
39
|
# Auto-generated display methods
|
|
@@ -54,7 +56,7 @@ grpcrequestlog_config = AdminConfig(
|
|
|
54
56
|
DateTimeField(name="completed_at", title="Completed", ordering="completed_at"),
|
|
55
57
|
],
|
|
56
58
|
# Filters
|
|
57
|
-
list_filter=["status", "grpc_status_code", "service_name", "method_name", "is_authenticated", "created_at"],
|
|
59
|
+
list_filter=["status", "grpc_status_code", "service_name", "method_name", "is_authenticated", "api_key", "created_at"],
|
|
58
60
|
search_fields=[
|
|
59
61
|
"request_id",
|
|
60
62
|
"service_name",
|
|
@@ -62,11 +64,13 @@ grpcrequestlog_config = AdminConfig(
|
|
|
62
64
|
"full_method",
|
|
63
65
|
"user__username",
|
|
64
66
|
"user__email",
|
|
67
|
+
"api_key__name",
|
|
68
|
+
"api_key__key",
|
|
65
69
|
"error_message",
|
|
66
70
|
"client_ip",
|
|
67
71
|
],
|
|
68
|
-
# Autocomplete for user
|
|
69
|
-
autocomplete_fields=["user"],
|
|
72
|
+
# Autocomplete for user and api_key fields
|
|
73
|
+
autocomplete_fields=["user", "api_key"],
|
|
70
74
|
# Readonly fields
|
|
71
75
|
readonly_fields=[
|
|
72
76
|
"id",
|
|
@@ -94,7 +98,7 @@ grpcserverstatus_config = AdminConfig(
|
|
|
94
98
|
list_display=[
|
|
95
99
|
"instance_id",
|
|
96
100
|
"address",
|
|
97
|
-
"
|
|
101
|
+
"status",
|
|
98
102
|
"pid",
|
|
99
103
|
"hostname",
|
|
100
104
|
"uptime_display",
|
|
@@ -141,6 +145,11 @@ grpcserverstatus_config = AdminConfig(
|
|
|
141
145
|
"updated_at",
|
|
142
146
|
"uptime_display",
|
|
143
147
|
"is_running",
|
|
148
|
+
"server_config_display",
|
|
149
|
+
"process_info_display",
|
|
150
|
+
"registered_services_display",
|
|
151
|
+
"error_display",
|
|
152
|
+
"lifecycle_display",
|
|
144
153
|
],
|
|
145
154
|
|
|
146
155
|
# Date hierarchy
|
|
@@ -154,4 +163,99 @@ grpcserverstatus_config = AdminConfig(
|
|
|
154
163
|
)
|
|
155
164
|
|
|
156
165
|
|
|
157
|
-
|
|
166
|
+
# Declarative configuration for GrpcApiKey
|
|
167
|
+
grpcapikey_config = AdminConfig(
|
|
168
|
+
model=GrpcApiKey,
|
|
169
|
+
|
|
170
|
+
# Performance optimization
|
|
171
|
+
select_related=["user", "created_by"],
|
|
172
|
+
|
|
173
|
+
# List display
|
|
174
|
+
list_display=[
|
|
175
|
+
"status_indicator",
|
|
176
|
+
"name",
|
|
177
|
+
"key_type",
|
|
178
|
+
"user",
|
|
179
|
+
"masked_key_display",
|
|
180
|
+
"request_count_display",
|
|
181
|
+
"last_used_at",
|
|
182
|
+
"expires_display",
|
|
183
|
+
"created_at",
|
|
184
|
+
],
|
|
185
|
+
|
|
186
|
+
# Auto-generated display methods
|
|
187
|
+
display_fields=[
|
|
188
|
+
TextField(name="name", title="Name", ordering="name"),
|
|
189
|
+
BadgeField(
|
|
190
|
+
name="key_type",
|
|
191
|
+
title="Type",
|
|
192
|
+
label_map={
|
|
193
|
+
"service": "info",
|
|
194
|
+
"cli": "primary",
|
|
195
|
+
"webhook": "warning",
|
|
196
|
+
"internal": "secondary",
|
|
197
|
+
"development": "danger",
|
|
198
|
+
},
|
|
199
|
+
),
|
|
200
|
+
UserField(name="user", title="User", header=True, ordering="user__username"),
|
|
201
|
+
DateTimeField(name="last_used_at", title="Last Used", ordering="last_used_at"),
|
|
202
|
+
DateTimeField(name="created_at", title="Created", ordering="created_at"),
|
|
203
|
+
],
|
|
204
|
+
|
|
205
|
+
# Filters
|
|
206
|
+
list_filter=["is_active", "key_type", "created_at", "expires_at", "user"],
|
|
207
|
+
search_fields=["name", "description", "user__username", "user__email", "key"],
|
|
208
|
+
|
|
209
|
+
# Readonly fields
|
|
210
|
+
readonly_fields=[
|
|
211
|
+
"key_display",
|
|
212
|
+
"masked_key",
|
|
213
|
+
"request_count",
|
|
214
|
+
"last_used_at",
|
|
215
|
+
"created_at",
|
|
216
|
+
"updated_at",
|
|
217
|
+
"created_by",
|
|
218
|
+
],
|
|
219
|
+
|
|
220
|
+
# Fieldsets
|
|
221
|
+
fieldsets=[
|
|
222
|
+
FieldsetConfig(
|
|
223
|
+
title="Basic Information",
|
|
224
|
+
fields=["name", "description", "key_type", "is_active"],
|
|
225
|
+
),
|
|
226
|
+
FieldsetConfig(
|
|
227
|
+
title="API Key",
|
|
228
|
+
fields=["key_display", "masked_key"],
|
|
229
|
+
),
|
|
230
|
+
FieldsetConfig(
|
|
231
|
+
title="User Association",
|
|
232
|
+
fields=["user", "created_by"],
|
|
233
|
+
),
|
|
234
|
+
FieldsetConfig(
|
|
235
|
+
title="Expiration",
|
|
236
|
+
fields=["expires_at"],
|
|
237
|
+
),
|
|
238
|
+
FieldsetConfig(
|
|
239
|
+
title="Usage Statistics",
|
|
240
|
+
fields=["request_count", "last_used_at"],
|
|
241
|
+
collapsed=True,
|
|
242
|
+
),
|
|
243
|
+
FieldsetConfig(
|
|
244
|
+
title="Timestamps",
|
|
245
|
+
fields=["created_at", "updated_at"],
|
|
246
|
+
collapsed=True,
|
|
247
|
+
),
|
|
248
|
+
],
|
|
249
|
+
|
|
250
|
+
# Autocomplete for user field
|
|
251
|
+
autocomplete_fields=["user"],
|
|
252
|
+
|
|
253
|
+
# Ordering
|
|
254
|
+
ordering=["-created_at"],
|
|
255
|
+
|
|
256
|
+
# Per page
|
|
257
|
+
list_per_page=50,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
__all__ = ["grpcrequestlog_config", "grpcserverstatus_config", "grpcapikey_config"]
|