netcop-ai/workflows/views.py
thecyberlearn 060c3a9c78 Initial commit: Django web app with user auth, Stripe payments, and n8n workflow integration
Features:
- Email-based user authentication with token auth
- Stripe Checkout integration for wallet top-ups
- n8n workflow triggering with automatic fee deduction ($0.10)
- Comprehensive transaction and usage logging
- Django Admin interface for monitoring
- Rate limiting and security middleware
- Production-ready deployment configuration
- Modular settings (dev/prod environments)
- UUID primary keys for enhanced security
- Comprehensive test coverage

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 13:34:19 +05:30

103 lines
3.7 KiB
Python

import requests
from django.conf import settings
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from decimal import Decimal
from django.db import transaction
from django_ratelimit.decorators import ratelimit
from .models import WorkflowUsage
from .serializers import WorkflowUsageSerializer, TriggerWorkflowSerializer
from wallet.models import WalletTransaction
@api_view(['POST'])
@ratelimit(key='user', rate='10/m', method='POST', block=True)
def trigger_workflow(request, workflow_name):
serializer = TriggerWorkflowSerializer(data=request.data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
workflow_data = serializer.validated_data.get('data', {})
workflow_fee = Decimal(str(settings.WORKFLOW_FEE))
if not request.user.has_sufficient_balance(workflow_fee):
return Response({
'error': 'Insufficient wallet balance',
'required': str(workflow_fee),
'current_balance': str(request.user.wallet_balance)
}, status=status.HTTP_402_PAYMENT_REQUIRED)
workflow_url = f"{settings.N8N_WEBHOOK_URL.rstrip('/')}/{workflow_name}"
with transaction.atomic():
workflow_usage = WorkflowUsage.objects.create(
user=request.user,
workflow_name=workflow_name,
workflow_url=workflow_url,
fee_charged=workflow_fee,
request_data=workflow_data,
status='pending'
)
if not request.user.deduct_balance(workflow_fee):
return Response({
'error': 'Failed to deduct balance'
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
WalletTransaction.objects.create(
user=request.user,
transaction_type='fee',
amount=workflow_fee,
status='completed',
description=f'Workflow fee for {workflow_name}'
)
try:
headers = {}
if settings.N8N_API_KEY:
headers['Authorization'] = f'Bearer {settings.N8N_API_KEY}'
response = requests.post(
workflow_url,
json=workflow_data,
headers=headers,
timeout=30
)
workflow_usage.response_data = response.json() if response.content else {}
workflow_usage.status = 'success' if response.status_code == 200 else 'failed'
if response.status_code != 200:
workflow_usage.error_message = f"HTTP {response.status_code}: {response.text}"
workflow_usage.save()
return Response({
'success': workflow_usage.status == 'success',
'workflow_usage_id': workflow_usage.id,
'fee_charged': workflow_fee,
'response_data': workflow_usage.response_data,
'remaining_balance': request.user.wallet_balance
})
except requests.RequestException as e:
workflow_usage.status = 'failed'
workflow_usage.error_message = str(e)
workflow_usage.save()
return Response({
'success': False,
'workflow_usage_id': workflow_usage.id,
'error': str(e),
'fee_charged': workflow_fee,
'remaining_balance': request.user.wallet_balance
})
@api_view(['GET'])
def workflow_history(request):
usage_history = WorkflowUsage.objects.filter(user=request.user)
serializer = WorkflowUsageSerializer(usage_history, many=True)
return Response(serializer.data)