Coverage for product_risk_suite/product/views.py: 95%
61 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 12:45 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 12:45 +0000
1from django.shortcuts import get_object_or_404, render
2from django.views.decorators.csrf import csrf_protect
3from django.contrib.auth.decorators import login_required
4from django.core.exceptions import PermissionDenied
6from guardian.decorators import permission_required_or_403
7from guardian.shortcuts import get_objects_for_user
9from .models import Product, ProductRiskAnalysis, ProductRiskEntry
10from risk_assessment.models import Risk
11from threat_model.models import ThreatModel
13@csrf_protect
14@login_required
15def product_index(request):
16 products = get_objects_for_user(request.user, 'product.view_product')
18 context = {"product_list": products}
19 return render(request, "product_index.html", context)
21@csrf_protect
22@login_required
23@permission_required_or_403("product.view_product", (Product, "slug", "product_slug"))
24def product(request, product_slug):
25 product = get_object_or_404(Product, slug=product_slug)
27 all_analysis = ProductRiskAnalysis.objects.filter(id__in=product.analyzes.all())
28 all_threat_models = ThreatModel.objects.filter(product=product).order_by("title")
30 context = {"product": product, "all_analysis": all_analysis, "all_threat_models": all_threat_models}
31 return render(request, "product.html", context)
33@csrf_protect
34@login_required
35def risk_diff(request, product_slug, entry_id):
36 product = get_object_or_404(Product, slug=product_slug)
37 if not request.user.has_perm('product.view_product', product):
38 raise PermissionDenied
40 entry = get_object_or_404(ProductRiskEntry, pk=entry_id)
41 old_risk = entry.risk
43 try:
44 new_risk = Risk.objects.get(custom_id=old_risk.custom_id, is_current=True)
45 except Risk.DoesNotExist:
46 new_risk = None
48 def _stride_str(risk):
49 return ", ".join(sorted(s.name for s in risk.stride.all()))
51 def _smv_str(risk):
52 smv = risk.suggested_mitigation_validation
53 if not smv:
54 return ""
55 return f"{smv.suggested_mitigation or ''} / {smv.suggested_validation or ''}"
57 fields = [
58 {'label': 'Title',
59 'old': old_risk.title,
60 'new': new_risk.title if new_risk else None},
61 {'label': 'Description',
62 'old': old_risk.description,
63 'new': new_risk.description if new_risk else None,
64 'is_html': True},
65 {'label': 'Asset',
66 'old': str(old_risk.asset),
67 'new': str(new_risk.asset) if new_risk else None},
68 {'label': 'Origin',
69 'old': str(old_risk.origin),
70 'new': str(new_risk.origin) if new_risk else None},
71 {'label': 'Life Cycle',
72 'old': str(old_risk.life_cycle),
73 'new': str(new_risk.life_cycle) if new_risk else None},
74 {'label': 'Stride',
75 'old': _stride_str(old_risk),
76 'new': _stride_str(new_risk) if new_risk else None},
77 {'label': 'Suggested Mitigation / Validation',
78 'old': _smv_str(old_risk),
79 'new': _smv_str(new_risk) if new_risk else None},
80 ]
82 for f in fields:
83 f['changed'] = f['old'] != f['new']
85 context = {
86 'product': product,
87 'entry': entry,
88 'old_risk': old_risk,
89 'new_risk': new_risk,
90 'fields': fields,
91 }
92 return render(request, 'risk_diff.html', context)
95@csrf_protect
96@login_required
97@permission_required_or_403("product.view_product", (Product, "slug", "product_slug"))
98def product_analysis(request, product_slug, analysis_slug):
99 product = get_object_or_404(Product, slug=product_slug)
100 product_analysis = get_object_or_404(ProductRiskAnalysis, slug=analysis_slug)
101 product_analysis_entries = ProductRiskEntry.objects.filter(id__in=product_analysis.risk_entries.all()).order_by("risk__custom_id")
103 risk_summery = ProductRiskAnalysis.get_risk_summary(product_analysis_entries)
105 pr_edit_allowed = request.user.has_perm("product.change_product", product)
107 tm = ThreatModel.objects.filter(product=product).order_by('-id').first()
108 latest_threat_model = {
109 "slug": tm.slug if tm else "",
110 "svg": tm.get_clean_svg_content() if tm else "",
111 }
113 context = {"product_edit": pr_edit_allowed, "product": product, "product_analysis": product_analysis, "product_analysis_entries": product_analysis_entries, "risk_summery": risk_summery, "latest_threat_model": latest_threat_model}
114 return render(request, "product_analysis.html", context)