2396 lines
87 KiB
Python
2396 lines
87 KiB
Python
"""
|
|
Integration app views with comprehensive CRUD operations following healthcare best practices.
|
|
"""
|
|
|
|
from django.shortcuts import render, get_object_or_404, redirect
|
|
from django.contrib.auth.decorators import login_required, permission_required
|
|
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
|
from django.contrib import messages
|
|
from django.utils.decorators import method_decorator
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.decorators.http import require_POST
|
|
from django.views.generic import (
|
|
ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView, FormView
|
|
)
|
|
from django.urls import reverse_lazy, reverse
|
|
from django.http import JsonResponse, HttpResponse
|
|
from django.db.models import Q, Count, Avg, Sum
|
|
from django.utils import timezone
|
|
from django.core.paginator import Paginator
|
|
from django.db import transaction
|
|
from datetime import datetime, timedelta, date
|
|
import json
|
|
import requests
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from .models import (
|
|
ExternalSystem, IntegrationEndpoint, DataMapping, IntegrationExecution,
|
|
WebhookEndpoint, WebhookExecution, IntegrationLog
|
|
)
|
|
from .forms import (
|
|
ExternalSystemForm, IntegrationEndpointForm, DataMappingForm,
|
|
WebhookEndpointForm
|
|
)
|
|
import logging
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# ============================================================================
|
|
# DASHBOARD AND OVERVIEW VIEWS
|
|
# ============================================================================
|
|
|
|
class IntegrationDashboardView(LoginRequiredMixin, TemplateView):
|
|
"""
|
|
Main integration dashboard with comprehensive statistics and recent activity.
|
|
"""
|
|
template_name = 'integration/dashboard.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
# Basic statistics
|
|
context.update({
|
|
'total_systems': ExternalSystem.objects.filter(tenant=self.request.user.tenant).count(),
|
|
'total_endpoints': IntegrationEndpoint.objects.filter(external_system__tenant=self.request.user.tenant).count(),
|
|
'total_mappings': DataMapping.objects.filter(endpoint__external_system__tenant=self.request.user.tenant).count(),
|
|
'total_webhooks': WebhookEndpoint.objects.filter(external_system__tenant=self.request.user.tenant).count(),
|
|
})
|
|
|
|
# Recent activity
|
|
context.update({
|
|
'recent_executions': IntegrationExecution.objects.filter(
|
|
endpoint__external_system__tenant=self.request.user.tenant
|
|
).order_by('-started_at')[:10],
|
|
|
|
'recent_webhook_executions': WebhookExecution.objects.filter(
|
|
webhook__external_system__tenant=self.request.user.tenant
|
|
).order_by('-processed_at')[:5],
|
|
|
|
'recent_logs': IntegrationLog.objects.filter(
|
|
endpoint__external_system__tenant=self.request.user.tenant
|
|
).order_by('-timestamp')[:10],
|
|
})
|
|
|
|
# Execution statistics
|
|
today = timezone.now().date()
|
|
context.update({
|
|
'executions_today': IntegrationExecution.objects.filter(
|
|
endpoint__external_system__tenant=self.request.user.tenant,
|
|
started_at__date=today
|
|
).count(),
|
|
|
|
'successful_executions': IntegrationExecution.objects.filter(
|
|
endpoint__external_system__tenant=self.request.user.tenant,
|
|
started_at__date=today,
|
|
status='SUCCESS'
|
|
).count(),
|
|
|
|
'failed_executions': IntegrationExecution.objects.filter(
|
|
endpoint__external_system__tenant=self.request.user.tenant,
|
|
started_at__date=today,
|
|
status='FAILED'
|
|
).count(),
|
|
})
|
|
|
|
# System health
|
|
context.update({
|
|
'healthy_systems': ExternalSystem.objects.filter(
|
|
tenant=self.request.user.tenant,
|
|
is_active=True,
|
|
is_healthy=True
|
|
).count(),
|
|
|
|
'unhealthy_systems': ExternalSystem.objects.filter(
|
|
tenant=self.request.user.tenant,
|
|
is_active=True,
|
|
is_healthy=False,
|
|
).count(),
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
# ============================================================================
|
|
# EXTERNAL SYSTEM VIEWS (FULL CRUD - Master Data)
|
|
# ============================================================================
|
|
|
|
class ExternalSystemListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all external systems with filtering and search capabilities.
|
|
"""
|
|
model = ExternalSystem
|
|
template_name = 'integration/external_system_list.html'
|
|
context_object_name = 'external_systems'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
# Search functionality
|
|
search = self.request.GET.get('search')
|
|
if search:
|
|
queryset = queryset.filter(
|
|
Q(system_name__icontains=search) |
|
|
Q(description__icontains=search) |
|
|
Q(base_url__icontains=search)
|
|
)
|
|
|
|
# Filter by system type
|
|
system_type = self.request.GET.get('system_type')
|
|
if system_type:
|
|
queryset = queryset.filter(system_type=system_type)
|
|
|
|
# Filter by status
|
|
is_active = self.request.GET.get('is_active')
|
|
if is_active:
|
|
queryset = queryset.filter(is_active=is_active == 'true')
|
|
|
|
# Filter by health status
|
|
health_status = self.request.GET.get('health_status')
|
|
if health_status:
|
|
queryset = queryset.filter(last_health_check_status=health_status)
|
|
|
|
return queryset.order_by('system_name')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['search'] = self.request.GET.get('search', '')
|
|
context['selected_system_type'] = self.request.GET.get('system_type', '')
|
|
context['selected_is_active'] = self.request.GET.get('is_active', '')
|
|
context['selected_health_status'] = self.request.GET.get('health_status', '')
|
|
return context
|
|
|
|
|
|
class ExternalSystemDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific external system.
|
|
"""
|
|
model = ExternalSystem
|
|
template_name = 'integration/external_system_detail.html'
|
|
context_object_name = 'external_system'
|
|
|
|
def get_queryset(self):
|
|
return ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
external_system = self.get_object()
|
|
|
|
# Related endpoints
|
|
context['endpoints'] = IntegrationEndpoint.objects.filter(
|
|
external_system=external_system
|
|
).order_by('endpoint_name')
|
|
|
|
# Recent executions
|
|
context['recent_executions'] = IntegrationExecution.objects.filter(
|
|
endpoint__external_system=external_system
|
|
).order_by('-execution_time')[:10]
|
|
|
|
# Execution statistics
|
|
context['total_executions'] = IntegrationExecution.objects.filter(
|
|
endpoint__external_system=external_system
|
|
).count()
|
|
|
|
context['successful_executions'] = IntegrationExecution.objects.filter(
|
|
endpoint__external_system=external_system,
|
|
status='SUCCESS'
|
|
).count()
|
|
|
|
return context
|
|
|
|
|
|
class ExternalSystemCreateView(LoginRequiredMixin, CreateView):
|
|
"""
|
|
Create a new external system.
|
|
"""
|
|
model = ExternalSystem
|
|
form_class = ExternalSystemForm
|
|
template_name = 'integration/systems/external_system_form.html'
|
|
success_url = reverse_lazy('integration:external_system_list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
messages.success(self.request, 'External system created successfully.')
|
|
return super().form_valid(form)
|
|
|
|
|
|
class ExternalSystemUpdateView(LoginRequiredMixin, UpdateView):
|
|
"""
|
|
Update an existing external system.
|
|
"""
|
|
model = ExternalSystem
|
|
form_class = ExternalSystemForm
|
|
template_name = 'integration/systems/external_system_form.html'
|
|
|
|
def get_queryset(self):
|
|
return ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_success_url(self):
|
|
return reverse('integration:external_system_detail', kwargs={'pk': self.object.pk})
|
|
|
|
def form_valid(self, form):
|
|
messages.success(self.request, 'External system updated successfully.')
|
|
return super().form_valid(form)
|
|
|
|
|
|
class ExternalSystemDeleteView(LoginRequiredMixin, DeleteView):
|
|
"""
|
|
Delete an external system.
|
|
"""
|
|
model = ExternalSystem
|
|
template_name = 'integration/systems/external_system_confirm_delete.html'
|
|
success_url = reverse_lazy('integration:external_system_list')
|
|
|
|
def get_queryset(self):
|
|
return ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def delete(self, request, *args, **kwargs):
|
|
external_system = self.get_object()
|
|
|
|
# Check if system has endpoints
|
|
if IntegrationEndpoint.objects.filter(external_system=external_system).exists():
|
|
messages.error(request, 'Cannot delete system that has integration endpoints.')
|
|
return redirect('integration:external_system_detail', pk=external_system.pk)
|
|
|
|
messages.success(request, f'External system {external_system.system_name} deleted successfully.')
|
|
return super().delete(request, *args, **kwargs)
|
|
|
|
|
|
# ============================================================================
|
|
# INTEGRATION ENDPOINT VIEWS (FULL CRUD - Operational Data)
|
|
# ============================================================================
|
|
|
|
class IntegrationEndpointListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all integration endpoints with filtering capabilities.
|
|
"""
|
|
model = IntegrationEndpoint
|
|
template_name = 'integration/integration_endpoint_list.html'
|
|
context_object_name = 'endpoints'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = IntegrationEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
# Search functionality
|
|
search = self.request.GET.get('search')
|
|
if search:
|
|
queryset = queryset.filter(
|
|
Q(endpoint_name__icontains=search) |
|
|
Q(description__icontains=search) |
|
|
Q(endpoint_url__icontains=search)
|
|
)
|
|
|
|
# Filter by external system
|
|
external_system = self.request.GET.get('external_system')
|
|
if external_system:
|
|
queryset = queryset.filter(external_system_id=external_system)
|
|
|
|
# Filter by method
|
|
method = self.request.GET.get('method')
|
|
if method:
|
|
queryset = queryset.filter(method=method)
|
|
|
|
# Filter by status
|
|
is_active = self.request.GET.get('is_active')
|
|
if is_active:
|
|
queryset = queryset.filter(is_active=is_active == 'true')
|
|
|
|
return queryset.select_related('external_system').order_by('endpoint_name')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['external_systems'] = ExternalSystem.objects.filter(
|
|
tenant=self.request.user.tenant
|
|
).order_by('system_name')
|
|
context['search'] = self.request.GET.get('search', '')
|
|
context['selected_external_system'] = self.request.GET.get('external_system', '')
|
|
context['selected_method'] = self.request.GET.get('method', '')
|
|
context['selected_is_active'] = self.request.GET.get('is_active', '')
|
|
return context
|
|
|
|
|
|
class IntegrationEndpointDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific integration endpoint.
|
|
"""
|
|
model = IntegrationEndpoint
|
|
template_name = 'integration/integration_endpoint_detail.html'
|
|
context_object_name = 'endpoint'
|
|
|
|
def get_queryset(self):
|
|
return IntegrationEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
endpoint = self.get_object()
|
|
|
|
# Data mappings
|
|
context['data_mappings'] = DataMapping.objects.filter(
|
|
endpoint=endpoint
|
|
).order_by('field_name')
|
|
|
|
# Recent executions
|
|
context['recent_executions'] = IntegrationExecution.objects.filter(
|
|
endpoint=endpoint
|
|
).order_by('-execution_time')[:10]
|
|
|
|
# Execution statistics
|
|
context['total_executions'] = IntegrationExecution.objects.filter(
|
|
endpoint=endpoint
|
|
).count()
|
|
|
|
context['successful_executions'] = IntegrationExecution.objects.filter(
|
|
endpoint=endpoint,
|
|
status='SUCCESS'
|
|
).count()
|
|
|
|
return context
|
|
|
|
|
|
class IntegrationEndpointCreateView(LoginRequiredMixin, CreateView):
|
|
"""
|
|
Create a new integration endpoint.
|
|
"""
|
|
model = IntegrationEndpoint
|
|
form_class = IntegrationEndpointForm
|
|
template_name = 'integration/integration_endpoint_form.html'
|
|
success_url = reverse_lazy('integration:integration_endpoint_list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
messages.success(self.request, 'Integration endpoint created successfully.')
|
|
return super().form_valid(form)
|
|
|
|
def get_form_kwargs(self):
|
|
kwargs = super().get_form_kwargs()
|
|
kwargs['user'] = self.request.user
|
|
return kwargs
|
|
|
|
|
|
class IntegrationEndpointUpdateView(LoginRequiredMixin, UpdateView):
|
|
"""
|
|
Update an existing integration endpoint.
|
|
"""
|
|
model = IntegrationEndpoint
|
|
form_class = IntegrationEndpointForm
|
|
template_name = 'integration/integration_endpoint_form.html'
|
|
|
|
def get_queryset(self):
|
|
return IntegrationEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_success_url(self):
|
|
return reverse('integration:integration_endpoint_detail', kwargs={'pk': self.object.pk})
|
|
|
|
def form_valid(self, form):
|
|
messages.success(self.request, 'Integration endpoint updated successfully.')
|
|
return super().form_valid(form)
|
|
|
|
def get_form_kwargs(self):
|
|
kwargs = super().get_form_kwargs()
|
|
kwargs['user'] = self.request.user
|
|
return kwargs
|
|
|
|
|
|
class IntegrationEndpointDeleteView(LoginRequiredMixin, DeleteView):
|
|
"""
|
|
Delete an integration endpoint.
|
|
"""
|
|
model = IntegrationEndpoint
|
|
template_name = 'integration/integration_endpoint_confirm_delete.html'
|
|
success_url = reverse_lazy('integration:integration_endpoint_list')
|
|
|
|
def get_queryset(self):
|
|
return IntegrationEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def delete(self, request, *args, **kwargs):
|
|
messages.success(request, 'Integration endpoint deleted successfully.')
|
|
return super().delete(request, *args, **kwargs)
|
|
|
|
|
|
# ============================================================================
|
|
# DATA MAPPING VIEWS (FULL CRUD - Operational Data)
|
|
# ============================================================================
|
|
|
|
class DataMappingListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all data mappings with filtering capabilities.
|
|
"""
|
|
model = DataMapping
|
|
template_name = 'integration/data_mapping_list.html'
|
|
context_object_name = 'data_mappings'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = DataMapping.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
# Search functionality
|
|
search = self.request.GET.get('search')
|
|
if search:
|
|
queryset = queryset.filter(
|
|
Q(field_name__icontains=search) |
|
|
Q(source_field__icontains=search) |
|
|
Q(target_field__icontains=search)
|
|
)
|
|
|
|
# Filter by endpoint
|
|
endpoint = self.request.GET.get('endpoint')
|
|
if endpoint:
|
|
queryset = queryset.filter(endpoint_id=endpoint)
|
|
|
|
# Filter by direction
|
|
direction = self.request.GET.get('direction')
|
|
if direction:
|
|
queryset = queryset.filter(direction=direction)
|
|
|
|
# Filter by status
|
|
is_active = self.request.GET.get('is_active')
|
|
if is_active:
|
|
queryset = queryset.filter(is_active=is_active == 'true')
|
|
|
|
return queryset.select_related('endpoint').order_by('field_name')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['endpoints'] = IntegrationEndpoint.objects.filter(
|
|
tenant=self.request.user.tenant
|
|
).order_by('endpoint_name')
|
|
context['search'] = self.request.GET.get('search', '')
|
|
context['selected_endpoint'] = self.request.GET.get('endpoint', '')
|
|
context['selected_direction'] = self.request.GET.get('direction', '')
|
|
context['selected_is_active'] = self.request.GET.get('is_active', '')
|
|
return context
|
|
|
|
|
|
class DataMappingDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific data mapping.
|
|
"""
|
|
model = DataMapping
|
|
template_name = 'integration/data_mapping_detail.html'
|
|
context_object_name = 'data_mapping'
|
|
|
|
def get_queryset(self):
|
|
return DataMapping.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
|
|
class DataMappingCreateView(LoginRequiredMixin, CreateView):
|
|
"""
|
|
Create a new data mapping.
|
|
"""
|
|
model = DataMapping
|
|
form_class = DataMappingForm
|
|
template_name = 'integration/data_mapping_form.html'
|
|
success_url = reverse_lazy('integration:data_mapping_list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
messages.success(self.request, 'Data mapping created successfully.')
|
|
return super().form_valid(form)
|
|
|
|
def get_form_kwargs(self):
|
|
kwargs = super().get_form_kwargs()
|
|
kwargs['user'] = self.request.user
|
|
return kwargs
|
|
|
|
|
|
class DataMappingUpdateView(LoginRequiredMixin, UpdateView):
|
|
"""
|
|
Update an existing data mapping.
|
|
"""
|
|
model = DataMapping
|
|
form_class = DataMappingForm
|
|
template_name = 'integration/data_mapping_form.html'
|
|
|
|
def get_queryset(self):
|
|
return DataMapping.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_success_url(self):
|
|
return reverse('integration:data_mapping_detail', kwargs={'pk': self.object.pk})
|
|
|
|
def form_valid(self, form):
|
|
messages.success(self.request, 'Data mapping updated successfully.')
|
|
return super().form_valid(form)
|
|
|
|
def get_form_kwargs(self):
|
|
kwargs = super().get_form_kwargs()
|
|
kwargs['user'] = self.request.user
|
|
return kwargs
|
|
|
|
|
|
class DataMappingDeleteView(LoginRequiredMixin, DeleteView):
|
|
"""
|
|
Delete a data mapping.
|
|
"""
|
|
model = DataMapping
|
|
template_name = 'integration/data_mapping_confirm_delete.html'
|
|
success_url = reverse_lazy('integration:data_mapping_list')
|
|
|
|
def get_queryset(self):
|
|
return DataMapping.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def delete(self, request, *args, **kwargs):
|
|
messages.success(request, 'Data mapping deleted successfully.')
|
|
return super().delete(request, *args, **kwargs)
|
|
|
|
|
|
class IntegrationExecutionListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all integration executions (read-only).
|
|
"""
|
|
model = IntegrationExecution
|
|
template_name = 'integration/executions/integration_execution_list.html'
|
|
context_object_name = 'executions'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
tenant = self.request.user.tenant
|
|
queryset = IntegrationExecution.objects.filter(endpoint__external_system__tenant=tenant)
|
|
|
|
# Filter by endpoint
|
|
endpoint = self.request.GET.get('endpoint')
|
|
if endpoint:
|
|
queryset = queryset.filter(endpoint_id=endpoint)
|
|
|
|
# Filter by status
|
|
status = self.request.GET.get('status')
|
|
if status:
|
|
queryset = queryset.filter(status=status)
|
|
|
|
# Filter by date range
|
|
start_date = self.request.GET.get('start_date')
|
|
end_date = self.request.GET.get('end_date')
|
|
if start_date:
|
|
queryset = queryset.filter(started_at__date__gte=start_date)
|
|
if end_date:
|
|
queryset = queryset.filter(completed_at__date__lte=end_date)
|
|
|
|
return queryset.select_related('endpoint').order_by('-completed_at')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
tenant = self.request.user.tenant
|
|
context = super().get_context_data(**kwargs)
|
|
context['endpoints'] = IntegrationEndpoint.objects.filter(
|
|
external_system__tenant=tenant
|
|
).order_by('name')
|
|
context['selected_endpoint'] = self.request.GET.get('endpoint', '')
|
|
context['selected_status'] = self.request.GET.get('status', '')
|
|
context['start_date'] = self.request.GET.get('start_date', '')
|
|
context['end_date'] = self.request.GET.get('end_date', '')
|
|
return context
|
|
|
|
|
|
class IntegrationExecutionDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific integration execution.
|
|
"""
|
|
model = IntegrationExecution
|
|
template_name = 'integration/executions/integration_execution_detail.html'
|
|
context_object_name = 'execution'
|
|
|
|
def get_queryset(self):
|
|
return IntegrationExecution.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
|
|
class WebhookEndpointListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all webhook endpoints with filtering capabilities.
|
|
"""
|
|
model = WebhookEndpoint
|
|
template_name = 'integration/webhooks/webhook_endpoint_list.html'
|
|
context_object_name = 'webhook_endpoints'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
# Search functionality
|
|
search = self.request.GET.get('search')
|
|
if search:
|
|
queryset = queryset.filter(
|
|
Q(endpoint_name__icontains=search) |
|
|
Q(description__icontains=search) |
|
|
Q(webhook_url__icontains=search)
|
|
)
|
|
|
|
# Filter by event type
|
|
event_type = self.request.GET.get('event_type')
|
|
if event_type:
|
|
queryset = queryset.filter(event_type=event_type)
|
|
|
|
# Filter by status
|
|
is_active = self.request.GET.get('is_active')
|
|
if is_active:
|
|
queryset = queryset.filter(is_active=is_active == 'true')
|
|
|
|
return queryset.order_by('endpoint_name')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['search'] = self.request.GET.get('search', '')
|
|
context['selected_event_type'] = self.request.GET.get('event_type', '')
|
|
context['selected_is_active'] = self.request.GET.get('is_active', '')
|
|
return context
|
|
|
|
|
|
class WebhookEndpointDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific webhook endpoint.
|
|
"""
|
|
model = WebhookEndpoint
|
|
template_name = 'integration/webhooks/webhook_endpoint_detail.html'
|
|
context_object_name = 'webhook_endpoint'
|
|
|
|
def get_queryset(self):
|
|
return WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
webhook_endpoint = self.get_object()
|
|
|
|
# Recent executions
|
|
context['recent_executions'] = WebhookExecution.objects.filter(
|
|
webhook_endpoint=webhook_endpoint
|
|
).order_by('-execution_time')[:10]
|
|
|
|
# Execution statistics
|
|
context['total_executions'] = WebhookExecution.objects.filter(
|
|
webhook_endpoint=webhook_endpoint
|
|
).count()
|
|
|
|
context['successful_executions'] = WebhookExecution.objects.filter(
|
|
webhook_endpoint=webhook_endpoint,
|
|
status='SUCCESS'
|
|
).count()
|
|
|
|
return context
|
|
|
|
|
|
class WebhookEndpointCreateView(LoginRequiredMixin, CreateView):
|
|
"""
|
|
Create a new webhook endpoint.
|
|
"""
|
|
model = WebhookEndpoint
|
|
form_class = WebhookEndpointForm
|
|
template_name = 'integration/webhooks/webhook_endpoint_form.html'
|
|
success_url = reverse_lazy('integration:webhook_endpoint_list')
|
|
|
|
def form_valid(self, form):
|
|
form.instance.tenant = self.request.user.tenant
|
|
messages.success(self.request, 'Webhook endpoint created successfully.')
|
|
return super().form_valid(form)
|
|
|
|
|
|
class WebhookEndpointUpdateView(LoginRequiredMixin, UpdateView):
|
|
"""
|
|
Update an existing webhook endpoint.
|
|
"""
|
|
model = WebhookEndpoint
|
|
form_class = WebhookEndpointForm
|
|
template_name = 'integration/webhooks/webhook_endpoint_form.html'
|
|
|
|
def get_queryset(self):
|
|
return WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def get_success_url(self):
|
|
return reverse('integration:webhook_endpoint_detail', kwargs={'pk': self.object.pk})
|
|
|
|
def form_valid(self, form):
|
|
messages.success(self.request, 'Webhook endpoint updated successfully.')
|
|
return super().form_valid(form)
|
|
|
|
|
|
class WebhookEndpointDeleteView(LoginRequiredMixin, DeleteView):
|
|
"""
|
|
Delete a webhook endpoint.
|
|
"""
|
|
model = WebhookEndpoint
|
|
template_name = 'integration/webhooks/webhook_endpoint_confirm_delete.html'
|
|
success_url = reverse_lazy('integration:webhook_endpoint_list')
|
|
|
|
def get_queryset(self):
|
|
return WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
def delete(self, request, *args, **kwargs):
|
|
messages.success(request, 'Webhook endpoint deleted successfully.')
|
|
return super().delete(request, *args, **kwargs)
|
|
|
|
|
|
class WebhookExecutionListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all webhook executions (read-only).
|
|
"""
|
|
model = WebhookExecution
|
|
template_name = 'integration/executions/webhook_execution_list.html'
|
|
context_object_name = 'webhook_executions'
|
|
paginate_by = 20
|
|
|
|
def get_queryset(self):
|
|
queryset = WebhookExecution.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
# Filter by webhook endpoint
|
|
webhook_endpoint = self.request.GET.get('webhook_endpoint')
|
|
if webhook_endpoint:
|
|
queryset = queryset.filter(webhook_endpoint_id=webhook_endpoint)
|
|
|
|
# Filter by status
|
|
status = self.request.GET.get('status')
|
|
if status:
|
|
queryset = queryset.filter(status=status)
|
|
|
|
# Filter by date range
|
|
start_date = self.request.GET.get('start_date')
|
|
end_date = self.request.GET.get('end_date')
|
|
if start_date:
|
|
queryset = queryset.filter(execution_time__date__gte=start_date)
|
|
if end_date:
|
|
queryset = queryset.filter(execution_time__date__lte=end_date)
|
|
|
|
return queryset.select_related('webhook_endpoint').order_by('-execution_time')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['webhook_endpoints'] = WebhookEndpoint.objects.filter(
|
|
tenant=self.request.user.tenant
|
|
).order_by('endpoint_name')
|
|
context['selected_webhook_endpoint'] = self.request.GET.get('webhook_endpoint', '')
|
|
context['selected_status'] = self.request.GET.get('status', '')
|
|
context['start_date'] = self.request.GET.get('start_date', '')
|
|
context['end_date'] = self.request.GET.get('end_date', '')
|
|
return context
|
|
|
|
|
|
class WebhookExecutionDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific webhook execution.
|
|
"""
|
|
model = WebhookExecution
|
|
template_name = 'integration/executions/webhook_execution_detail.html'
|
|
context_object_name = 'webhook_execution'
|
|
|
|
def get_queryset(self):
|
|
return WebhookExecution.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
|
|
class IntegrationLogListView(LoginRequiredMixin, ListView):
|
|
"""
|
|
List all integration logs (read-only).
|
|
"""
|
|
model = IntegrationLog
|
|
template_name = 'integration/logs/integration_log_list.html'
|
|
context_object_name = 'integration_logs'
|
|
paginate_by = 50
|
|
|
|
def get_queryset(self):
|
|
queryset = IntegrationLog.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
# Filter by log level
|
|
log_level = self.request.GET.get('log_level')
|
|
if log_level:
|
|
queryset = queryset.filter(log_level=log_level)
|
|
|
|
# Filter by component
|
|
component = self.request.GET.get('component')
|
|
if component:
|
|
queryset = queryset.filter(component__icontains=component)
|
|
|
|
# Filter by date range
|
|
start_date = self.request.GET.get('start_date')
|
|
end_date = self.request.GET.get('end_date')
|
|
if start_date:
|
|
queryset = queryset.filter(timestamp__date__gte=start_date)
|
|
if end_date:
|
|
queryset = queryset.filter(timestamp__date__lte=end_date)
|
|
|
|
return queryset.order_by('-timestamp')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['selected_log_level'] = self.request.GET.get('log_level', '')
|
|
context['selected_component'] = self.request.GET.get('component', '')
|
|
context['start_date'] = self.request.GET.get('start_date', '')
|
|
context['end_date'] = self.request.GET.get('end_date', '')
|
|
return context
|
|
|
|
|
|
class IntegrationLogDetailView(LoginRequiredMixin, DetailView):
|
|
"""
|
|
Display detailed information about a specific integration log.
|
|
"""
|
|
model = IntegrationLog
|
|
template_name = 'integration/logs/integration_log_detail.html'
|
|
context_object_name = 'integration_log'
|
|
|
|
def get_queryset(self):
|
|
return IntegrationLog.objects.filter(tenant=self.request.user.tenant)
|
|
|
|
|
|
@login_required
|
|
def integration_stats(request):
|
|
"""
|
|
Return integration statistics for dashboard updates.
|
|
"""
|
|
today = timezone.now().date()
|
|
|
|
context = {
|
|
'total_systems': ExternalSystem.objects.filter(tenant=request.user.tenant).count(),
|
|
'total_endpoints': IntegrationEndpoint.objects.filter(endpoint__external_system__tenant=request.user.tenant).count(),
|
|
'total_mappings': DataMapping.objects.filter(tenant=request.user.tenant).count(),
|
|
'total_webhooks': WebhookEndpoint.objects.filter(tenant=request.user.tenant).count(),
|
|
'executions_today': IntegrationExecution.objects.filter(
|
|
tenant=request.user.tenant,
|
|
execution_time__date=today
|
|
).count(),
|
|
'successful_executions': IntegrationExecution.objects.filter(
|
|
tenant=request.user.tenant,
|
|
execution_time__date=today,
|
|
status='SUCCESS'
|
|
).count(),
|
|
'healthy_systems': ExternalSystem.objects.filter(
|
|
tenant=request.user.tenant,
|
|
is_active=True,
|
|
last_health_check_status='HEALTHY'
|
|
).count(),
|
|
}
|
|
|
|
return render(request, 'integration/partials/integration_stats.html', context)
|
|
|
|
|
|
@login_required
|
|
def system_health(request):
|
|
"""
|
|
Return system health information for dashboard updates.
|
|
"""
|
|
context = {
|
|
'healthy_systems': ExternalSystem.objects.filter(
|
|
tenant=request.user.tenant,
|
|
is_active=True,
|
|
is_healthy=True
|
|
).count(),
|
|
'unhealthy_systems': ExternalSystem.objects.filter(
|
|
tenant=request.user.tenant,
|
|
is_active=True,
|
|
is_healthy=False
|
|
).count(),
|
|
}
|
|
|
|
return render(request, 'integration/partials/system_health.html', context)
|
|
|
|
|
|
@login_required
|
|
def test_connection(request, system_id):
|
|
"""
|
|
Test connection to an external system.
|
|
"""
|
|
try:
|
|
external_system = ExternalSystem.objects.get(
|
|
id=system_id,
|
|
tenant=request.user.tenant
|
|
)
|
|
|
|
# Simulate connection test (implement actual logic based on system type)
|
|
try:
|
|
# Basic URL connectivity test
|
|
response = requests.get(
|
|
external_system.base_url,
|
|
timeout=external_system.timeout_seconds or 30,
|
|
verify=False # In production, handle SSL verification properly
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
external_system.last_health_check_time = timezone.now()
|
|
external_system.last_health_check_status = 'HEALTHY'
|
|
external_system.last_health_check_message = 'Connection successful'
|
|
external_system.save()
|
|
|
|
messages.success(request, f'Connection to {external_system.name} successful.')
|
|
else:
|
|
external_system.last_health_check_time = timezone.now()
|
|
external_system.last_health_check_status = 'UNHEALTHY'
|
|
external_system.last_health_check_message = f'HTTP {response.status_code}'
|
|
external_system.save()
|
|
|
|
messages.warning(request, f'Connection to {external_system.name} returned HTTP {response.status_code}.')
|
|
|
|
except requests.RequestException as e:
|
|
external_system.last_health_check_time = timezone.now()
|
|
external_system.last_health_check_status = 'UNHEALTHY'
|
|
external_system.last_health_check_message = str(e)
|
|
external_system.save()
|
|
|
|
messages.error(request, f'Connection to {external_system.name} failed: {str(e)}')
|
|
|
|
except ExternalSystem.DoesNotExist:
|
|
messages.error(request, 'External system not found.')
|
|
|
|
return redirect('integration:external_system_detail', pk=system_id)
|
|
|
|
|
|
@login_required
|
|
def execute_endpoint(request, endpoint_id):
|
|
"""
|
|
Execute an integration endpoint.
|
|
"""
|
|
try:
|
|
endpoint = IntegrationEndpoint.objects.get(
|
|
id=endpoint_id,
|
|
tenant=request.user.tenant
|
|
)
|
|
|
|
# Create execution record
|
|
execution = IntegrationExecution.objects.create(
|
|
tenant=request.user.tenant,
|
|
endpoint=endpoint,
|
|
execution_time=timezone.now(),
|
|
status='RUNNING',
|
|
triggered_by=request.user
|
|
)
|
|
|
|
try:
|
|
# Simulate endpoint execution (implement actual logic)
|
|
# This would involve calling the actual endpoint with proper data
|
|
|
|
execution.status = 'SUCCESS'
|
|
execution.completion_time = timezone.now()
|
|
execution.response_data = '{"status": "success", "message": "Endpoint executed successfully"}'
|
|
execution.save()
|
|
|
|
messages.success(request, f'Endpoint {endpoint.name} executed successfully.')
|
|
|
|
except Exception as e:
|
|
execution.status = 'FAILED'
|
|
execution.completion_time = timezone.now()
|
|
execution.error_message = str(e)
|
|
execution.save()
|
|
|
|
messages.error(request, f'Endpoint execution failed: {str(e)}')
|
|
|
|
except IntegrationEndpoint.DoesNotExist:
|
|
messages.error(request, 'Integration endpoint not found.')
|
|
|
|
return redirect('integration:integration_endpoint_detail', pk=endpoint_id)
|
|
|
|
|
|
@login_required
|
|
def test_data_mapping(request, mapping_id):
|
|
"""
|
|
Test a data mapping.
|
|
"""
|
|
try:
|
|
data_mapping = DataMapping.objects.get(
|
|
id=mapping_id,
|
|
tenant=request.user.tenant
|
|
)
|
|
|
|
# Simulate mapping test (implement actual logic)
|
|
# This would involve testing the transformation logic
|
|
|
|
messages.success(request, f'Data mapping {data_mapping.name} tested successfully.')
|
|
|
|
except DataMapping.DoesNotExist:
|
|
messages.error(request, 'Data mapping not found.')
|
|
|
|
return redirect('integration:data_mapping_detail', pk=mapping_id)
|
|
|
|
|
|
@login_required
|
|
def bulk_execute_endpoints(request):
|
|
"""
|
|
Execute multiple endpoints in bulk.
|
|
"""
|
|
endpoint_ids = request.POST.getlist('endpoint_ids')
|
|
|
|
if not endpoint_ids:
|
|
messages.error(request, 'No endpoints selected for execution.')
|
|
return redirect('integration:integration_endpoint_list')
|
|
|
|
executed_count = 0
|
|
failed_count = 0
|
|
|
|
for endpoint_id in endpoint_ids:
|
|
try:
|
|
endpoint = IntegrationEndpoint.objects.get(
|
|
id=endpoint_id,
|
|
tenant=request.user.tenant,
|
|
is_active=True
|
|
)
|
|
|
|
# Create execution record
|
|
execution = IntegrationExecution.objects.create(
|
|
tenant=request.user.tenant,
|
|
endpoint=endpoint,
|
|
execution_time=timezone.now(),
|
|
status='SUCCESS', # Simulate success
|
|
completion_time=timezone.now(),
|
|
triggered_by=request.user,
|
|
response_data='{"status": "success", "bulk_execution": true}'
|
|
)
|
|
|
|
executed_count += 1
|
|
|
|
except IntegrationEndpoint.DoesNotExist:
|
|
failed_count += 1
|
|
continue
|
|
except Exception:
|
|
failed_count += 1
|
|
continue
|
|
|
|
if executed_count > 0:
|
|
messages.success(request, f'Successfully executed {executed_count} endpoints.')
|
|
|
|
if failed_count > 0:
|
|
messages.warning(request, f'{failed_count} endpoints failed to execute.')
|
|
|
|
return redirect('integration:integration_endpoint_list')
|
|
|
|
|
|
#
|
|
#
|
|
# """
|
|
# Views for the integration app.
|
|
# """
|
|
# import json
|
|
# import logging
|
|
# import uuid
|
|
# from datetime import datetime, timedelta
|
|
#
|
|
# from django.shortcuts import render, get_object_or_404, redirect
|
|
# from django.http import JsonResponse, HttpResponse
|
|
# from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
|
|
# from django.views.generic.edit import FormView
|
|
# from django.views.decorators.csrf import csrf_exempt
|
|
# from django.views.decorators.http import require_POST
|
|
# from django.utils.decorators import method_decorator
|
|
# from django.contrib.auth.decorators import login_required, permission_required
|
|
# from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
|
# from django.urls import reverse, reverse_lazy
|
|
# from django.utils.translation import gettext_lazy as _
|
|
# from django.contrib import messages
|
|
# from django.db.models import Q, Count, Avg, Max, Min, Sum
|
|
# from django.db import transaction
|
|
# from django.utils import timezone
|
|
# from django.contrib.contenttypes.models import ContentType
|
|
#
|
|
# from .models import (
|
|
# ExternalSystem, IntegrationEndpoint, DataMapping,
|
|
# IntegrationExecution, WebhookEndpoint, WebhookExecution,
|
|
# IntegrationLog
|
|
# )
|
|
# from .forms import (
|
|
# ExternalSystemForm, IntegrationEndpointForm, DataMappingForm,
|
|
# WebhookEndpointForm, ManualIntegrationExecutionForm, IntegrationLogFilterForm
|
|
# )
|
|
#
|
|
# logger = logging.getLogger(__name__)
|
|
#
|
|
#
|
|
# class DashboardView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# Integration dashboard view showing an overview of integration status.
|
|
# """
|
|
# model = ExternalSystem
|
|
# template_name = 'integration/dashboard.html'
|
|
# context_object_name = 'external_systems'
|
|
# permission_required = 'integration.view_externalsystem'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return ExternalSystem.objects.filter(
|
|
# tenant=self.request.user.tenant
|
|
# ).prefetch_related('endpoints')
|
|
# return ExternalSystem.objects.none()
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data for the dashboard."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add statistics for recent executions
|
|
# recent_executions = IntegrationExecution.objects.filter(
|
|
# endpoint__external_system__tenant=self.request.user.tenant,
|
|
# started_at__gte=timezone.now() - timedelta(days=7)
|
|
# )
|
|
#
|
|
# # Execution stats by status
|
|
# execution_stats = {
|
|
# 'total': recent_executions.count(),
|
|
# 'success': recent_executions.filter(status='SUCCESS').count(),
|
|
# 'error': recent_executions.filter(status='ERROR').count(),
|
|
# 'warning': recent_executions.filter(status='WARNING').count(),
|
|
# 'pending': recent_executions.filter(status__in=['PENDING', 'IN_PROGRESS']).count(),
|
|
# }
|
|
# context['execution_stats'] = execution_stats
|
|
#
|
|
# # Calculate success rate
|
|
# if execution_stats['total'] > 0:
|
|
# success_rate = (execution_stats['success'] / execution_stats['total']) * 100
|
|
# context['success_rate'] = round(success_rate, 1)
|
|
# else:
|
|
# context['success_rate'] = 0
|
|
#
|
|
# # Get recent logs
|
|
# context['recent_logs'] = IntegrationLog.objects.filter(
|
|
# tenant=self.request.user.tenant
|
|
# ).order_by('-timestamp')[:10]
|
|
#
|
|
# # Count active webhooks
|
|
# context['active_webhooks'] = WebhookEndpoint.objects.filter(
|
|
# tenant=self.request.user.tenant,
|
|
# is_active=True
|
|
# ).count()
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class ExternalSystemListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# List view for external systems.
|
|
# """
|
|
# model = ExternalSystem
|
|
# template_name = 'integration/external_system/list.html'
|
|
# context_object_name = 'external_systems'
|
|
# permission_required = 'integration.view_externalsystem'
|
|
# paginate_by = 15
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant and apply search parameters."""
|
|
# queryset = ExternalSystem.objects.all()
|
|
#
|
|
# # Filter by tenant
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# queryset = queryset.filter(tenant=self.request.user.tenant)
|
|
#
|
|
# # Apply search filter if provided
|
|
# search_query = self.request.GET.get('q')
|
|
# if search_query:
|
|
# queryset = queryset.filter(
|
|
# Q(name__icontains=search_query) |
|
|
# Q(system_type__icontains=search_query) |
|
|
# Q(description__icontains=search_query)
|
|
# )
|
|
#
|
|
# # Apply status filter if provided
|
|
# status_filter = self.request.GET.get('status')
|
|
# if status_filter == 'active':
|
|
# queryset = queryset.filter(is_active=True)
|
|
# elif status_filter == 'inactive':
|
|
# queryset = queryset.filter(is_active=False)
|
|
#
|
|
# # Apply system type filter if provided
|
|
# system_type = self.request.GET.get('system_type')
|
|
# if system_type:
|
|
# queryset = queryset.filter(system_type=system_type)
|
|
#
|
|
# return queryset.select_related('tenant')
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add filters to context
|
|
# context['search_query'] = self.request.GET.get('q', '')
|
|
# context['status_filter'] = self.request.GET.get('status', '')
|
|
# context['system_type'] = self.request.GET.get('system_type', '')
|
|
#
|
|
# # Add system type choices
|
|
# context['system_type_choices'] = ExternalSystem.SYSTEM_TYPE_CHOICES
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class ExternalSystemDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
# """
|
|
# Detail view for an external system.
|
|
# """
|
|
# model = ExternalSystem
|
|
# template_name = 'integration/external_system/detail.html'
|
|
# context_object_name = 'external_system'
|
|
# permission_required = 'integration.view_externalsystem'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
# return ExternalSystem.objects.none()
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add endpoints for this system
|
|
# context['endpoints'] = self.object.endpoints.all()
|
|
#
|
|
# # Add recent executions
|
|
# context['recent_executions'] = IntegrationExecution.objects.filter(
|
|
# endpoint__external_system=self.object
|
|
# ).order_by('-started_at')[:10]
|
|
#
|
|
# # Add health check timestamp
|
|
# if self.object.last_connected_at:
|
|
# last_check = timezone.now() - self.object.last_connected_at
|
|
# context['last_check_minutes'] = int(last_check.total_seconds() // 60)
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class ExternalSystemCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
|
# """
|
|
# Create view for an external system.
|
|
# """
|
|
# model = ExternalSystem
|
|
# form_class = ExternalSystemForm
|
|
# template_name = 'integration/external_system/form.html'
|
|
# permission_required = 'integration.add_externalsystem'
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Add External System')
|
|
# context['submit_text'] = _('Create System')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('External system created successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:external_system_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class ExternalSystemUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
|
# """
|
|
# Update view for an external system.
|
|
# """
|
|
# model = ExternalSystem
|
|
# form_class = ExternalSystemForm
|
|
# template_name = 'integration/external_system/form.html'
|
|
# permission_required = 'integration.change_externalsystem'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
# return ExternalSystem.objects.none()
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Edit External System')
|
|
# context['submit_text'] = _('Update System')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('External system updated successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:external_system_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class ExternalSystemDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
|
|
# """
|
|
# Delete view for an external system.
|
|
# """
|
|
# model = ExternalSystem
|
|
# template_name = 'integration/external_system/confirm_delete.html'
|
|
# permission_required = 'integration.delete_externalsystem'
|
|
# success_url = reverse_lazy('integration:external_system_list')
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return ExternalSystem.objects.filter(tenant=self.request.user.tenant)
|
|
# return ExternalSystem.objects.none()
|
|
#
|
|
# def delete(self, request, *args, **kwargs):
|
|
# """Handle the delete action."""
|
|
# messages.success(request, _('External system deleted successfully.'))
|
|
# return super().delete(request, *args, **kwargs)
|
|
#
|
|
#
|
|
# class IntegrationEndpointListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# List view for integration endpoints.
|
|
# """
|
|
# model = IntegrationEndpoint
|
|
# template_name = 'integration/endpoint/list.html'
|
|
# context_object_name = 'endpoints'
|
|
# permission_required = 'integration.view_integrationendpoint'
|
|
# paginate_by = 15
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant and apply search parameters."""
|
|
# queryset = IntegrationEndpoint.objects.all()
|
|
#
|
|
# # Filter by tenant
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# queryset = queryset.filter(external_system__tenant=self.request.user.tenant)
|
|
#
|
|
# # Filter by external system if provided
|
|
# system_id = self.request.GET.get('system')
|
|
# if system_id:
|
|
# queryset = queryset.filter(external_system_id=system_id)
|
|
#
|
|
# # Apply search filter if provided
|
|
# search_query = self.request.GET.get('q')
|
|
# if search_query:
|
|
# queryset = queryset.filter(
|
|
# Q(name__icontains=search_query) |
|
|
# Q(description__icontains=search_query) |
|
|
# Q(endpoint_path__icontains=search_query)
|
|
# )
|
|
#
|
|
# # Apply direction filter if provided
|
|
# direction = self.request.GET.get('direction')
|
|
# if direction:
|
|
# queryset = queryset.filter(direction=direction)
|
|
#
|
|
# return queryset.select_related('external_system', 'external_system__tenant')
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add filters to context
|
|
# context['search_query'] = self.request.GET.get('q', '')
|
|
# context['direction'] = self.request.GET.get('direction', '')
|
|
# context['system_id'] = self.request.GET.get('system', '')
|
|
#
|
|
# # Add external systems for filter dropdown
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# context['external_systems'] = ExternalSystem.objects.filter(
|
|
# tenant=self.request.user.tenant
|
|
# )
|
|
#
|
|
# # Add direction choices
|
|
# context['direction_choices'] = IntegrationEndpoint.DIRECTION_CHOICES
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class IntegrationEndpointDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
# """
|
|
# Detail view for an integration endpoint.
|
|
# """
|
|
# model = IntegrationEndpoint
|
|
# template_name = 'integration/endpoint/detail.html'
|
|
# context_object_name = 'endpoint'
|
|
# permission_required = 'integration.view_integrationendpoint'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return IntegrationEndpoint.objects.filter(
|
|
# external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return IntegrationEndpoint.objects.none()
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add data mappings
|
|
# context['data_mappings'] = self.object.data_mappings.all().order_by('priority')
|
|
#
|
|
# # Add recent executions
|
|
# context['recent_executions'] = self.object.executions.order_by('-started_at')[:10]
|
|
#
|
|
# # Add manual execution form
|
|
# context['execution_form'] = ManualIntegrationExecutionForm(
|
|
# user=self.request.user,
|
|
# initial={'endpoint': self.object.pk}
|
|
# )
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class IntegrationEndpointCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
|
# """
|
|
# Create view for an integration endpoint.
|
|
# """
|
|
# model = IntegrationEndpoint
|
|
# form_class = IntegrationEndpointForm
|
|
# template_name = 'integration/endpoint/form.html'
|
|
# permission_required = 'integration.add_integrationendpoint'
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_initial(self):
|
|
# """Set initial values for the form."""
|
|
# initial = super().get_initial()
|
|
#
|
|
# # Set external system if provided in URL
|
|
# system_id = self.request.GET.get('system')
|
|
# if system_id:
|
|
# initial['external_system'] = system_id
|
|
#
|
|
# return initial
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Add Integration Endpoint')
|
|
# context['submit_text'] = _('Create Endpoint')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('Integration endpoint created successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:endpoint_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class IntegrationEndpointUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
|
# """
|
|
# Update view for an integration endpoint.
|
|
# """
|
|
# model = IntegrationEndpoint
|
|
# form_class = IntegrationEndpointForm
|
|
# template_name = 'integration/endpoint/form.html'
|
|
# permission_required = 'integration.change_integrationendpoint'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return IntegrationEndpoint.objects.filter(
|
|
# external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return IntegrationEndpoint.objects.none()
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Edit Integration Endpoint')
|
|
# context['submit_text'] = _('Update Endpoint')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('Integration endpoint updated successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:endpoint_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class IntegrationEndpointDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
|
|
# """
|
|
# Delete view for an integration endpoint.
|
|
# """
|
|
# model = IntegrationEndpoint
|
|
# template_name = 'integration/endpoint/confirm_delete.html'
|
|
# permission_required = 'integration.delete_integrationendpoint'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return IntegrationEndpoint.objects.filter(
|
|
# external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return IntegrationEndpoint.objects.none()
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:endpoint_list')
|
|
#
|
|
# def delete(self, request, *args, **kwargs):
|
|
# """Handle the delete action."""
|
|
# messages.success(request, _('Integration endpoint deleted successfully.'))
|
|
# return super().delete(request, *args, **kwargs)
|
|
#
|
|
#
|
|
# class DataMappingListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# List view for data mappings.
|
|
# """
|
|
# model = DataMapping
|
|
# template_name = 'integration/mapping/list.html'
|
|
# context_object_name = 'mappings'
|
|
# permission_required = 'integration.view_datamapping'
|
|
# paginate_by = 20
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant and apply search parameters."""
|
|
# queryset = DataMapping.objects.all()
|
|
#
|
|
# # Filter by tenant
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# queryset = queryset.filter(
|
|
# endpoint__external_system__tenant=self.request.user.tenant
|
|
# )
|
|
#
|
|
# # Filter by endpoint if provided
|
|
# endpoint_id = self.request.GET.get('endpoint')
|
|
# if endpoint_id:
|
|
# queryset = queryset.filter(endpoint_id=endpoint_id)
|
|
#
|
|
# # Apply search filter if provided
|
|
# search_query = self.request.GET.get('q')
|
|
# if search_query:
|
|
# queryset = queryset.filter(
|
|
# Q(name__icontains=search_query) |
|
|
# Q(description__icontains=search_query) |
|
|
# Q(source_field__icontains=search_query) |
|
|
# Q(target_field__icontains=search_query)
|
|
# )
|
|
#
|
|
# # Apply mapping type filter if provided
|
|
# mapping_type = self.request.GET.get('mapping_type')
|
|
# if mapping_type:
|
|
# queryset = queryset.filter(mapping_type=mapping_type)
|
|
#
|
|
# return queryset.select_related(
|
|
# 'endpoint', 'endpoint__external_system', 'created_by'
|
|
# ).order_by('endpoint__name', 'priority')
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add filters to context
|
|
# context['search_query'] = self.request.GET.get('q', '')
|
|
# context['mapping_type'] = self.request.GET.get('mapping_type', '')
|
|
# context['endpoint_id'] = self.request.GET.get('endpoint', '')
|
|
#
|
|
# # Add endpoints for filter dropdown
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# context['endpoints'] = IntegrationEndpoint.objects.filter(
|
|
# external_system__tenant=self.request.user.tenant
|
|
# ).select_related('external_system')
|
|
#
|
|
# # Add mapping type choices
|
|
# context['mapping_type_choices'] = DataMapping.MAPPING_TYPE_CHOICES
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class DataMappingDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
# """
|
|
# Detail view for a data mapping.
|
|
# """
|
|
# model = DataMapping
|
|
# template_name = 'integration/mapping/detail.html'
|
|
# context_object_name = 'mapping'
|
|
# permission_required = 'integration.view_datamapping'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return DataMapping.objects.filter(
|
|
# endpoint__external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return DataMapping.objects.none()
|
|
#
|
|
#
|
|
# class DataMappingCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
|
# """
|
|
# Create view for a data mapping.
|
|
# """
|
|
# model = DataMapping
|
|
# form_class = DataMappingForm
|
|
# template_name = 'integration/mapping/form.html'
|
|
# permission_required = 'integration.add_datamapping'
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_initial(self):
|
|
# """Set initial values for the form."""
|
|
# initial = super().get_initial()
|
|
#
|
|
# # Set endpoint if provided in URL
|
|
# endpoint_id = self.request.GET.get('endpoint')
|
|
# if endpoint_id:
|
|
# initial['endpoint'] = endpoint_id
|
|
#
|
|
# return initial
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Add Data Mapping')
|
|
# context['submit_text'] = _('Create Mapping')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('Data mapping created successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# if 'endpoint' in self.request.GET:
|
|
# return reverse('integration:endpoint_detail',
|
|
# kwargs={'pk': self.request.GET.get('endpoint')})
|
|
# return reverse('integration:mapping_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class DataMappingUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
|
# """
|
|
# Update view for a data mapping.
|
|
# """
|
|
# model = DataMapping
|
|
# form_class = DataMappingForm
|
|
# template_name = 'integration/mapping/form.html'
|
|
# permission_required = 'integration.change_datamapping'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return DataMapping.objects.filter(
|
|
# endpoint__external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return DataMapping.objects.none()
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Edit Data Mapping')
|
|
# context['submit_text'] = _('Update Mapping')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('Data mapping updated successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:mapping_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class DataMappingDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
|
|
# """
|
|
# Delete view for a data mapping.
|
|
# """
|
|
# model = DataMapping
|
|
# template_name = 'integration/mapping/confirm_delete.html'
|
|
# permission_required = 'integration.delete_datamapping'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return DataMapping.objects.filter(
|
|
# endpoint__external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return DataMapping.objects.none()
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# if self.object.endpoint:
|
|
# return reverse('integration:endpoint_detail',
|
|
# kwargs={'pk': self.object.endpoint.pk})
|
|
# return reverse('integration:mapping_list')
|
|
#
|
|
# def delete(self, request, *args, **kwargs):
|
|
# """Handle the delete action."""
|
|
# messages.success(request, _('Data mapping deleted successfully.'))
|
|
# return super().delete(request, *args, **kwargs)
|
|
#
|
|
#
|
|
# class WebhookEndpointListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# List view for webhook endpoints.
|
|
# """
|
|
# model = WebhookEndpoint
|
|
# template_name = 'integration/webhook/list.html'
|
|
# context_object_name = 'webhooks'
|
|
# permission_required = 'integration.view_webhookendpoint'
|
|
# paginate_by = 15
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant and apply search parameters."""
|
|
# queryset = WebhookEndpoint.objects.all()
|
|
#
|
|
# # Filter by tenant
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# queryset = queryset.filter(tenant=self.request.user.tenant)
|
|
#
|
|
# # Apply search filter if provided
|
|
# search_query = self.request.GET.get('q')
|
|
# if search_query:
|
|
# queryset = queryset.filter(
|
|
# Q(name__icontains=search_query) |
|
|
# Q(description__icontains=search_query) |
|
|
# Q(path__icontains=search_query)
|
|
# )
|
|
#
|
|
# # Apply security level filter if provided
|
|
# security_level = self.request.GET.get('security_level')
|
|
# if security_level:
|
|
# queryset = queryset.filter(security_level=security_level)
|
|
#
|
|
# # Apply status filter
|
|
# status_filter = self.request.GET.get('status')
|
|
# if status_filter == 'active':
|
|
# queryset = queryset.filter(is_active=True)
|
|
# elif status_filter == 'inactive':
|
|
# queryset = queryset.filter(is_active=False)
|
|
#
|
|
# return queryset.select_related('tenant')
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add filters to context
|
|
# context['search_query'] = self.request.GET.get('q', '')
|
|
# context['security_level'] = self.request.GET.get('security_level', '')
|
|
# context['status_filter'] = self.request.GET.get('status', '')
|
|
#
|
|
# # Add security level choices
|
|
# context['security_level_choices'] = WebhookEndpoint.SECURITY_LEVEL_CHOICES
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class WebhookEndpointDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
# """
|
|
# Detail view for a webhook endpoint.
|
|
# """
|
|
# model = WebhookEndpoint
|
|
# template_name = 'integration/webhook/detail.html'
|
|
# context_object_name = 'webhook'
|
|
# permission_required = 'integration.view_webhookendpoint'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
# return WebhookEndpoint.objects.none()
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add recent executions
|
|
# context['recent_executions'] = WebhookExecution.objects.filter(
|
|
# webhook=self.object
|
|
# ).order_by('-timestamp')[:10]
|
|
#
|
|
# # Add webhook URL
|
|
# context['webhook_url'] = self.object.get_full_url()
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class WebhookEndpointCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
|
# """
|
|
# Create view for a webhook endpoint.
|
|
# """
|
|
# model = WebhookEndpoint
|
|
# form_class = WebhookEndpointForm
|
|
# template_name = 'integration/webhook/form.html'
|
|
# permission_required = 'integration.add_webhookendpoint'
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Add Webhook Endpoint')
|
|
# context['submit_text'] = _('Create Webhook')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('Webhook endpoint created successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:webhook_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class WebhookEndpointUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
|
# """
|
|
# Update view for a webhook endpoint.
|
|
# """
|
|
# model = WebhookEndpoint
|
|
# form_class = WebhookEndpointForm
|
|
# template_name = 'integration/webhook/form.html'
|
|
# permission_required = 'integration.change_webhookendpoint'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
# return WebhookEndpoint.objects.none()
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add context for the template."""
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['title'] = _('Edit Webhook Endpoint')
|
|
# context['submit_text'] = _('Update Webhook')
|
|
# return context
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Handle valid form."""
|
|
# messages.success(self.request, _('Webhook endpoint updated successfully.'))
|
|
# return super().form_valid(form)
|
|
#
|
|
# def get_success_url(self):
|
|
# """Return URL to redirect to on success."""
|
|
# return reverse('integration:webhook_detail', kwargs={'pk': self.object.pk})
|
|
#
|
|
#
|
|
# class WebhookEndpointDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
|
|
# """
|
|
# Delete view for a webhook endpoint.
|
|
# """
|
|
# model = WebhookEndpoint
|
|
# template_name = 'integration/webhook/confirm_delete.html'
|
|
# permission_required = 'integration.delete_webhookendpoint'
|
|
# success_url = reverse_lazy('integration:webhook_list')
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return WebhookEndpoint.objects.filter(tenant=self.request.user.tenant)
|
|
# return WebhookEndpoint.objects.none()
|
|
#
|
|
# def delete(self, request, *args, **kwargs):
|
|
# """Handle the delete action."""
|
|
# messages.success(request, _('Webhook endpoint deleted successfully.'))
|
|
# return super().delete(request, *args, **kwargs)
|
|
#
|
|
#
|
|
# class IntegrationLogListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# List view for integration logs.
|
|
# """
|
|
# model = IntegrationLog
|
|
# template_name = 'integration/log/list.html'
|
|
# context_object_name = 'logs'
|
|
# permission_required = 'integration.view_integrationlog'
|
|
# paginate_by = 50
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant and apply search parameters."""
|
|
# queryset = IntegrationLog.objects.all()
|
|
#
|
|
# # Filter by tenant
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# queryset = queryset.filter(tenant=self.request.user.tenant)
|
|
#
|
|
# # Get filter form
|
|
# form = IntegrationLogFilterForm(self.request.GET)
|
|
# if form.is_valid():
|
|
# # Apply integration name filter
|
|
# if form.cleaned_data.get('integration_name'):
|
|
# queryset = queryset.filter(
|
|
# integration_name__icontains=form.cleaned_data['integration_name']
|
|
# )
|
|
#
|
|
# # Apply event type filter
|
|
# if form.cleaned_data.get('event_type'):
|
|
# queryset = queryset.filter(
|
|
# event_type__icontains=form.cleaned_data['event_type']
|
|
# )
|
|
#
|
|
# # Apply status filter
|
|
# if form.cleaned_data.get('status'):
|
|
# queryset = queryset.filter(status=form.cleaned_data['status'])
|
|
#
|
|
# # Apply direction filter
|
|
# if form.cleaned_data.get('direction'):
|
|
# queryset = queryset.filter(direction=form.cleaned_data['direction'])
|
|
#
|
|
# # Apply date range filter
|
|
# if form.cleaned_data.get('date_from'):
|
|
# queryset = queryset.filter(
|
|
# timestamp__gte=form.cleaned_data['date_from']
|
|
# )
|
|
# if form.cleaned_data.get('date_to'):
|
|
# queryset = queryset.filter(
|
|
# timestamp__lte=form.cleaned_data['date_to']
|
|
# )
|
|
#
|
|
# # Apply related object filters
|
|
# if form.cleaned_data.get('related_object_type'):
|
|
# queryset = queryset.filter(
|
|
# related_object_type=form.cleaned_data['related_object_type']
|
|
# )
|
|
# if form.cleaned_data.get('related_object_id'):
|
|
# queryset = queryset.filter(
|
|
# related_object_id=form.cleaned_data['related_object_id']
|
|
# )
|
|
#
|
|
# return queryset.select_related('tenant', 'user', 'related_object_type').order_by('-timestamp')
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add filter form
|
|
# context['filter_form'] = IntegrationLogFilterForm(self.request.GET)
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class IntegrationLogDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
# """
|
|
# Detail view for an integration log.
|
|
# """
|
|
# model = IntegrationLog
|
|
# template_name = 'integration/log/detail.html'
|
|
# context_object_name = 'log'
|
|
# permission_required = 'integration.view_integrationlog'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return IntegrationLog.objects.filter(tenant=self.request.user.tenant)
|
|
# return IntegrationLog.objects.none()
|
|
#
|
|
#
|
|
# class IntegrationExecutionListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
# """
|
|
# List view for integration executions.
|
|
# """
|
|
# model = IntegrationExecution
|
|
# template_name = 'integration/execution/list.html'
|
|
# context_object_name = 'executions'
|
|
# permission_required = 'integration.view_integrationexecution'
|
|
# paginate_by = 30
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant and apply search parameters."""
|
|
# queryset = IntegrationExecution.objects.all()
|
|
#
|
|
# # Filter by tenant
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# queryset = queryset.filter(endpoint__external_system__tenant=self.request.user.tenant)
|
|
#
|
|
# # Apply endpoint filter if provided
|
|
# endpoint_id = self.request.GET.get('endpoint')
|
|
# if endpoint_id:
|
|
# queryset = queryset.filter(endpoint_id=endpoint_id)
|
|
#
|
|
# # Apply status filter if provided
|
|
# status = self.request.GET.get('status')
|
|
# if status:
|
|
# queryset = queryset.filter(status=status)
|
|
#
|
|
# # Apply date range filter
|
|
# date_from = self.request.GET.get('date_from')
|
|
# if date_from:
|
|
# try:
|
|
# date_from = datetime.strptime(date_from, '%Y-%m-%d')
|
|
# queryset = queryset.filter(started_at__gte=date_from)
|
|
# except (ValueError, TypeError):
|
|
# pass
|
|
#
|
|
# date_to = self.request.GET.get('date_to')
|
|
# if date_to:
|
|
# try:
|
|
# date_to = datetime.strptime(date_to, '%Y-%m-%d')
|
|
# date_to = date_to.replace(hour=23, minute=59, second=59)
|
|
# queryset = queryset.filter(started_at__lte=date_to)
|
|
# except (ValueError, TypeError):
|
|
# pass
|
|
#
|
|
# return queryset.select_related(
|
|
# 'endpoint', 'endpoint__external_system', 'triggered_by'
|
|
# ).order_by('-started_at')
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# """Add additional context data."""
|
|
# context = super().get_context_data(**kwargs)
|
|
#
|
|
# # Add filters to context
|
|
# context['endpoint_id'] = self.request.GET.get('endpoint', '')
|
|
# context['status'] = self.request.GET.get('status', '')
|
|
# context['date_from'] = self.request.GET.get('date_from', '')
|
|
# context['date_to'] = self.request.GET.get('date_to', '')
|
|
#
|
|
# # Add status choices
|
|
# context['status_choices'] = IntegrationExecution.STATUS_CHOICES
|
|
#
|
|
# # Add endpoints for filter dropdown
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# context['endpoints'] = IntegrationEndpoint.objects.filter(
|
|
# external_system__tenant=self.request.user.tenant
|
|
# ).select_related('external_system')
|
|
#
|
|
# return context
|
|
#
|
|
#
|
|
# class IntegrationExecutionDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|
# """
|
|
# Detail view for an integration execution.
|
|
# """
|
|
# model = IntegrationExecution
|
|
# template_name = 'integration/execution/detail.html'
|
|
# context_object_name = 'execution'
|
|
# permission_required = 'integration.view_integrationexecution'
|
|
#
|
|
# def get_queryset(self):
|
|
# """Filter by user's tenant."""
|
|
# if hasattr(self.request.user, 'tenant'):
|
|
# return IntegrationExecution.objects.filter(
|
|
# endpoint__external_system__tenant=self.request.user.tenant
|
|
# )
|
|
# return IntegrationExecution.objects.none()
|
|
|
|
|
|
# class ManualExecutionView(LoginRequiredMixin, PermissionRequiredMixin, FormView):
|
|
# """
|
|
# View for manually executing an integration endpoint.
|
|
# """
|
|
# form_class = ManualIntegrationExecutionForm
|
|
# template_name = 'integration/executions/manual_execution.html'
|
|
# permission_required = 'integration.add_integrationexecution'
|
|
#
|
|
# def get_form_kwargs(self):
|
|
# """Add user to form kwargs."""
|
|
# kwargs = super().get_form_kwargs()
|
|
# kwargs['user'] = self.request.user
|
|
# return kwargs
|
|
#
|
|
# def get_initial(self):
|
|
# """Set initial values for the form."""
|
|
# initial = super().get_initial()
|
|
#
|
|
# # Set endpoint if provided in URL
|
|
# endpoint_id = self.request.GET.get('endpoint')
|
|
# if endpoint_id:
|
|
# initial['endpoint'] = endpoint_id
|
|
#
|
|
# return initial
|
|
#
|
|
# def form_valid(self, form):
|
|
# """Execute the integration when the form is valid."""
|
|
# try:
|
|
# execution = form.execute()
|
|
# messages.success(
|
|
# self.request,
|
|
# _('Integration executed successfully. Status: {}').format(
|
|
# execution.get_status_display()
|
|
# )
|
|
# )
|
|
# return redirect('integration:execution_detail', pk=execution.pk)
|
|
# except Exception as e:
|
|
# messages.error(
|
|
# self.request,
|
|
# _('Error executing integration: {}').format(str(e))
|
|
# )
|
|
# return self.form_invalid(form)
|
|
|
|
|
|
@login_required
|
|
@permission_required('integration.change_integrationexecution')
|
|
def retry_execution(request, pk):
|
|
"""
|
|
View for retrying a failed integration execution.
|
|
"""
|
|
execution = get_object_or_404(IntegrationExecution, pk=pk)
|
|
|
|
# Check tenant access
|
|
if hasattr(request.user, 'tenant') and execution.endpoint.external_system.tenant != request.user.tenant:
|
|
messages.error(request, _('You do not have permission to retry this execution.'))
|
|
return redirect('integration:execution_list')
|
|
|
|
# Check if execution can be retried
|
|
if execution.status not in ['ERROR', 'WARNING']:
|
|
messages.error(request, _('Only failed executions can be retried.'))
|
|
return redirect('integration:execution_detail', pk=execution.pk)
|
|
|
|
# Retry the execution
|
|
new_execution = execution.retry(user=request.user)
|
|
if new_execution:
|
|
messages.success(request, _('Integration execution retried.'))
|
|
return redirect('integration:execution_detail', pk=new_execution.pk)
|
|
else:
|
|
messages.error(request, _('Failed to retry execution.'))
|
|
return redirect('integration:execution_detail', pk=execution.pk)
|
|
|
|
|
|
@login_required
|
|
@permission_required('integration.view_externalsystem')
|
|
def check_system_health(request, pk):
|
|
"""
|
|
View for checking the health of an external system.
|
|
"""
|
|
tenant = request.user.tenant
|
|
system = get_object_or_404(ExternalSystem, pk=pk)
|
|
|
|
# Check tenant access
|
|
if not tenant:
|
|
messages.error(request, _('You do not have permission to check this system.'))
|
|
return redirect('integration:external_system_list')
|
|
|
|
# Check the health
|
|
if system.check_health():
|
|
messages.success(request, _('Connection to {} is healthy.').format(system.name))
|
|
else:
|
|
messages.error(
|
|
request,
|
|
_('Connection to {} failed: {}').format(system.name, system.health_status_message)
|
|
)
|
|
|
|
return redirect('integration:external_system_detail', pk=system.pk)
|
|
|
|
|
|
@method_decorator(csrf_exempt, name='dispatch')
|
|
@require_POST
|
|
def webhook_receiver(request, path):
|
|
"""
|
|
View for receiving webhook calls from external systems.
|
|
This is a public endpoint that doesn't require authentication directly,
|
|
but validates the request using the webhook's security configuration.
|
|
"""
|
|
# Find the webhook by path
|
|
webhook = get_object_or_404(WebhookEndpoint, path=path, is_active=True)
|
|
|
|
# Create execution record
|
|
execution = WebhookExecution(
|
|
webhook=webhook,
|
|
client_ip=request.META.get('REMOTE_ADDR', '')
|
|
)
|
|
|
|
# Store headers
|
|
execution.headers = {key: value for key, value in request.headers.items()}
|
|
|
|
# Parse payload based on content type
|
|
try:
|
|
if request.content_type == 'application/json':
|
|
execution.payload = json.loads(request.body)
|
|
elif request.content_type == 'application/x-www-form-urlencoded':
|
|
execution.payload = dict(request.POST)
|
|
else:
|
|
execution.payload = {'raw': request.body.decode('utf-8', errors='replace')}
|
|
except Exception as e:
|
|
execution.status = 'REJECTED'
|
|
execution.error_message = f"Failed to parse payload: {str(e)}"
|
|
execution.response_code = 400
|
|
execution.save()
|
|
return JsonResponse(
|
|
{'error': 'Invalid payload format'},
|
|
status=400
|
|
)
|
|
|
|
# Validate security
|
|
if webhook.security_level != 'NONE':
|
|
security_valid = False
|
|
error_message = ''
|
|
|
|
if webhook.security_level == 'TOKEN':
|
|
# Check for token in Authorization header or query parameter
|
|
auth_header = request.headers.get('Authorization', '')
|
|
query_token = request.GET.get('token', '')
|
|
|
|
if auth_header.startswith('Bearer ') and auth_header[7:] == webhook.secret_token:
|
|
security_valid = True
|
|
elif query_token and query_token == webhook.secret_token:
|
|
security_valid = True
|
|
else:
|
|
error_message = 'Invalid or missing authentication token'
|
|
|
|
elif webhook.security_level == 'HMAC':
|
|
# Implement HMAC signature validation
|
|
signature = request.headers.get('X-Signature', '')
|
|
if not signature:
|
|
error_message = 'Missing signature header'
|
|
else:
|
|
# HMAC validation would go here
|
|
security_valid = True # Placeholder
|
|
|
|
elif webhook.security_level == 'IP':
|
|
# Check if client IP is in allowed list
|
|
client_ip = request.META.get('REMOTE_ADDR', '')
|
|
allowed_ips = [ip.strip() for ip in webhook.allowed_ips.split(',') if ip.strip()]
|
|
|
|
if not allowed_ips or client_ip in allowed_ips:
|
|
security_valid = True
|
|
else:
|
|
error_message = f'IP address {client_ip} not in allowed list'
|
|
|
|
if not security_valid:
|
|
execution.status = 'REJECTED'
|
|
execution.error_message = f"Security validation failed: {error_message}"
|
|
execution.response_code = 403
|
|
execution.save()
|
|
return JsonResponse(
|
|
{'error': 'Authentication failed'},
|
|
status=403
|
|
)
|
|
|
|
# Process the webhook
|
|
try:
|
|
# Import and call the handler function
|
|
module_path, function_name = webhook.handler_function.rsplit('.', 1)
|
|
module = __import__(module_path, fromlist=[function_name])
|
|
handler = getattr(module, function_name)
|
|
|
|
# Call the handler with the execution record
|
|
start_time = timezone.now()
|
|
result = handler(execution.payload, webhook=webhook, execution=execution)
|
|
processing_time = (timezone.now() - start_time).total_seconds() * 1000
|
|
|
|
# Update execution record
|
|
execution.status = 'SUCCESS'
|
|
execution.response_data = result
|
|
execution.response_code = 200
|
|
execution.processing_time_ms = int(processing_time)
|
|
execution.save()
|
|
|
|
# Return the result
|
|
return JsonResponse(result, status=200)
|
|
|
|
except Exception as e:
|
|
logger.exception(f"Error processing webhook {webhook.name}: {str(e)}")
|
|
|
|
# Update execution record
|
|
execution.status = 'ERROR'
|
|
execution.error_message = str(e)
|
|
execution.response_code = 500
|
|
execution.response_data = {'error': 'Internal server error'}
|
|
execution.save()
|
|
|
|
# Return error response
|
|
return JsonResponse(
|
|
{'error': 'Internal server error'},
|
|
status=500
|
|
)
|
|
|
|
|
|
@login_required
|
|
@permission_required('integration.change_webhookendpoint')
|
|
def regenerate_webhook_token(request, pk):
|
|
"""
|
|
View for regenerating a webhook's secret token.
|
|
"""
|
|
tenant = request.user.tenant
|
|
webhook = get_object_or_404(WebhookEndpoint, pk=pk)
|
|
|
|
# Check tenant access
|
|
if not tenant:
|
|
messages.error(request, _('You do not have permission to modify this webhook.'))
|
|
return redirect('integration:webhook_list')
|
|
|
|
# Regenerate the token
|
|
webhook.regenerate_token()
|
|
messages.success(request, _('Webhook token regenerated successfully.'))
|
|
|
|
return redirect('integration:webhook_detail', pk=webhook.pk)
|
|
|
|
|
|
@login_required
|
|
@permission_required('integration.view_integrationlog')
|
|
def integration_stats(request):
|
|
"""
|
|
View for displaying integration statistics.
|
|
"""
|
|
if hasattr(request.user, 'tenant'):
|
|
tenant = request.user.tenant
|
|
|
|
# Date range for stats
|
|
days = int(request.GET.get('days', 30))
|
|
end_date = timezone.now()
|
|
start_date = end_date - timedelta(days=days)
|
|
|
|
# Get logs for period
|
|
logs = IntegrationLog.objects.filter(
|
|
external_system__tenant=tenant,
|
|
timestamp__gte=start_date,
|
|
timestamp__lte=end_date
|
|
)
|
|
|
|
# Calculate statistics
|
|
stats = {
|
|
'total_count': logs.count(),
|
|
'success_count': logs.filter(status='SUCCESS').count(),
|
|
'error_count': logs.filter(status='ERROR').count(),
|
|
'warning_count': logs.filter(status='WARNING').count(),
|
|
'inbound_count': logs.filter(direction='INBOUND').count(),
|
|
'outbound_count': logs.filter(direction='OUTBOUND').count(),
|
|
}
|
|
|
|
# Calculate success rate
|
|
if stats['total_count'] > 0:
|
|
stats['success_rate'] = (stats['success_count'] / stats['total_count']) * 100
|
|
else:
|
|
stats['success_rate'] = 0
|
|
|
|
# Get top integration names
|
|
top_integrations = logs.values('integration_name') \
|
|
.annotate(count=Count('integration_name')) \
|
|
.order_by('-count')[:10]
|
|
|
|
# Get top error types
|
|
top_errors = logs.filter(status='ERROR') \
|
|
.values('error_message') \
|
|
.annotate(count=Count('error_message')) \
|
|
.order_by('-count')[:10]
|
|
|
|
# Get average response times
|
|
avg_duration = logs.aggregate(avg_duration=Avg('duration_ms'))
|
|
stats['avg_duration_ms'] = avg_duration['avg_duration'] or 0
|
|
|
|
context = {
|
|
'stats': stats,
|
|
'top_integrations': top_integrations,
|
|
'top_errors': top_errors,
|
|
'start_date': start_date,
|
|
'end_date': end_date,
|
|
'days': days,
|
|
}
|
|
|
|
return render(request, 'integration/partials/integration_stats.html', context)
|
|
|
|
messages.error(request, _('You do not have permission to view integration statistics.'))
|
|
return redirect('integration:dashboard')
|
|
|
|
|