Files
old-riskletpy/backend/core/views.py
2025-10-20 19:50:39 +02:00

308 lines
12 KiB
Python

import logging
import yaml
import os
import json
import time
from django.shortcuts import render, redirect , get_object_or_404
from .forms import OrganizationForm, ContactForm
from .models import Organization,Document, DocumentTemplate, DemoCode, PaymentRecord, DocumentRiskControl, Risk, Control
from backend.accounts.utils import send_confirmation_email, send_document_email, send_documet_to_expert, send_document_to_reviewer
from django.contrib.admin.views.decorators import staff_member_required
from .utils import generate_pdf, generate_risk_graph, generate_residual_risk_graph
from .tables import risk_matrix_table ,get_risk_table, get_safeguard_summary_table
from django.conf import settings
from .processors import render_template
from django.http import JsonResponse, FileResponse, Http404, HttpResponse
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils import timezone
from weasyprint import HTML
from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt
from backend.accounts.models import ExpertAnalysisEmails
from django.core.mail import send_mail
from django.views import View
import re
from decimal import Decimal
from django.urls import reverse
from urllib.parse import urlencode
# @login_required
# def index(request):
# return HttpResponse('<h1>Django</h1><p>Página simples.</p>')
logger = logging.getLogger(__name__)
site_domain = settings.SITE_DOMAIN
# @login_required
def index(request):
template_name = 'index.html'
return render(request, template_name)
def signup(request):
if request.method == 'POST':
form = OrganizationForm(request.POST)
if form.is_valid():
form.save()
send_confirmation_email(form.data['email'])
return render(request, 'thankyou.html', {
'email': form.data['email'],
})
else:
logging.error(form.errors)
return render(request, 'signup.html', {'form': form})
else:
form = OrganizationForm()
return render(request, 'signup.html', {'form': form})
def validate_form_fields(request):
name = request.GET.get('name', '').strip()
email = request.GET.get('email', '').strip()
errors = {}
if name and Organization.objects.filter(name__iexact=name).exists():
errors['name'] = 'Organization with this name already exists.'
if email:
try:
validate_email(email)
except ValidationError:
errors['email'] = 'Please enter a valid email address.'
else:
if Organization.objects.filter(email__iexact=email).exists():
errors['email'] = 'This email is already registered.'
return JsonResponse({'errors': errors})
def thankyou(request):
return render(request, 'thankyou.html')
def document(request, document_id):
document = get_object_or_404(Document, id=document_id)
risks_with_controls = get_risk_table(document)
table_risk_matrix = risk_matrix_table()
safeguard_summary_table = get_safeguard_summary_table(risks_with_controls)
graph_base64 = generate_risk_graph(risks_with_controls)
residual_graph_base64 = generate_residual_risk_graph(risks_with_controls)
template_obj = get_object_or_404(DocumentTemplate, name="Default Template")
template_content = template_obj.content
try:
template_segments = yaml.safe_load(template_content)
except yaml.YAMLError as e:
return render(request, 'error.html', {'error_message': 'Error parsing template.'})
context = {
'document': document,
'risks_with_controls': risks_with_controls,
'graph': graph_base64,
'table_risk_matrix': table_risk_matrix,
'residual_graph': residual_graph_base64,
'safeguard_summary_table': safeguard_summary_table,
'table_risk_matrix_header' : table_risk_matrix[0],
'table_risk_matrix_rows': table_risk_matrix[1:],
}
rendered_content = render_template(template_segments, context)
return render(request, 'document.html',
{'rendered_html': rendered_content,
'document': document,})
@staff_member_required
def template_preview(request, name):
template = get_object_or_404(DocumentTemplate, name=name)
parsed_template = template.to_dict()
return render(request, 'template_preview.html', {'template': parsed_template})
def pdf_view(request, document_id):
document = get_object_or_404(Document, id=document_id)
return generate_pdf(document)
class PaymentView(View):
template_name = 'payment.html'
def get(self,request):
email = request.GET.get('email','').strip()
status_view = request.GET.get('status')
pdl_client = settings.PADDLE_CLIENT_ID
pdl_price = settings.PADDLE_PRICE_ID
if status_view == 'review':
document = Document.objects.filter(organization__email__iexact=email).first()
return render(request, 'payment_review.html', {'email': email, 'document': document})
if status_view == 'expert':
document = Document.objects.filter(organization__email__iexact=email).first()
return render(request, 'payment_expert_analysis.html', {'email': email, 'document': document})
return render(request, self.template_name, {
'email': email,
'pdl_client': pdl_client,
'pdl_price': pdl_price})
def post(self, request):
content_type = request.META.get('CONTENT_TYPE', '')
if 'application/json' in content_type:
try:
payload = json.loads(request.body)
return self._handle_paddle_payment(payload)
except json.JSONDecodeError:
return JsonResponse({'status': 'error', 'message': 'Invalid JSON'}, status=400)
else:
return self._handle_demo_code(request)
def _handle_demo_code(self, request):
email = request.GET.get('email', '').strip()
error = None
code = re.sub(r'\s+', '', request.POST.get('code', '')).upper()[:10]
try:
payment_code = DemoCode.objects.get(code=code)
if payment_code.used:
error = "Invalid demo code"
return render(request, self.template_name, {'email': email, 'error': error})
org = Organization.objects.filter(email__iexact=email).first()
payment_code.used = True
payment_code.used_at = timezone.now()
payment_code.company = org
payment_code.save()
print(org, email)
document = Document.objects.get(organization=org)
return self._handle_document_flow(org, document, email)
except DemoCode.DoesNotExist:
error = "Invalid demo code"
return render(request, self.template_name, {'email': email, 'error': error})
def _handle_paddle_payment(self, data):
try:
customer_email = data.get('customer_email')
transaction_id = data.get('transaction_id')
amount = Decimal(data.get('amount', 0))
currency = data.get('currency', 'EUR')
org = Organization.objects.filter(email__iexact=customer_email).first()
if not org:
return JsonResponse({'status': 'error', 'message': 'Organization not found'}, status=404)
PaymentRecord.objects.create(
company=org,
amount=amount,
currency=currency,
transaction_id=transaction_id,
payment_date=timezone.now()
)
document = Document.objects.get(organization=org)
return self._handle_document_flow(org, document, customer_email, json_response=True)
except Exception as e:
logger.exception("Error saving Paddle payment: %s", e)
return JsonResponse({'status': 'error', 'message': str(e)}, status=500)
def validate_code(request):
if request.method == "POST":
try:
data = json.loads(request.body)
code = data.get("code", "").strip().upper()
valid = DemoCode.objects.filter(code=code, used=False).exists()
time.sleep(1)
return JsonResponse({"valid": valid})
except Exception:
return JsonResponse({"valid": False})
return JsonResponse({"valid": False})
def _handle_document_flow(self, org, document, email, json_response=False):
site_domain = settings.SITE_DOMAIN
url = f"{site_domain}/pdf/{document.id}/"
expert_emails_qs = ExpertAnalysisEmails.objects.values_list('email', flat=True).distinct()
if document.status == Document.STATUS_INCOMPLETE:
review_url = f"{reverse('core:payment_page')}?{urlencode({'email': email, 'status': 'review'})}"
for email_addr in expert_emails_qs:
try:
send_document_to_reviewer(email_addr, document)
except Exception:
logger.exception("Failed to send incomplete document email to %s", email_addr)
if json_response:
return JsonResponse({'status': 'review', 'redirect_url': review_url})
return render(self.request, 'payment_review.html', {'email': email, 'document': document})
if org.expert_analysis:
document.status = Document.STATUS_WAITING
document.save(update_fields=['status', 'modified_at'])
expert_url = f"{reverse('core:payment_page')}?{urlencode({'email': email, 'status': 'expert'})}"
expert_emails = [e for e in expert_emails_qs if e]
for email_addr in expert_emails:
try:
send_documet_to_expert(email_addr, document)
except Exception:
logger.exception("Failed to send expert analysis email to %s", email_addr)
if json_response:
return JsonResponse({'status': 'expert', 'redirect_url': expert_url})
return render(self.request, 'payment_expert_analysis.html', {'email': email, 'document': document})
send_document_email(email, url, document)
document.status = Document.STATUS_DONE
document.save(update_fields=['status', 'modified_at'])
if json_response:
return JsonResponse({'status': 'ok', 'redirect_url': url})
return redirect(url)
def no_confidential_data(request):
return render(request, "no_confidential_data.html")
def terms_and_conditions(request):
return render(request, "terms_and_conditions.html")
def privacy_policy(request):
return render(request, "privacy_policy.html")
def refund_policy(request):
return render(request, "refund_policy.html")
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
subject = f"New contact message from {name}"
body = f"From: {name} <{email}>\n\n{message}"
try:
recipients = [e for _, e in settings.ADMINS] if getattr(settings, 'ADMINS', None) else [settings.DEFAULT_FROM_EMAIL]
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, recipients, fail_silently=False)
return render(request, 'contact-success.html', {"email": email})
except Exception:
logger.exception("Failed to send contact email")
form.add_error(None, "We couldn't send your message right now. Please try again later.")
else:
form = ContactForm()
return render(request, 'contact.html', {"form": form})
@staff_member_required
def demo_codes_pdf_view(request):
filter_by = request.GET.get('filter_by', 'all')
if filter_by == 'used':
codes = DemoCode.objects.filter(used=True)
elif filter_by == 'available':
codes = DemoCode.objects.filter(used=False)
else:
codes = DemoCode.objects.all()
html_string = render_to_string('demo_code_report.html', {'codes': codes})
pdf_content = HTML(string=html_string, base_url=request.build_absolute_uri('/')).write_pdf()
response = HttpResponse(pdf_content, content_type='application/pdf')
response['Content-Disposition'] = f'inline; filename=demo_codes_{timezone.now().strftime("%Y%m%d_%H%M%S")}.pdf'
return response