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

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 

5 

6from guardian.decorators import permission_required_or_403 

7from guardian.shortcuts import get_objects_for_user 

8 

9from .models import Product, ProductRiskAnalysis, ProductRiskEntry 

10from risk_assessment.models import Risk 

11from threat_model.models import ThreatModel 

12 

13@csrf_protect 

14@login_required 

15def product_index(request): 

16 products = get_objects_for_user(request.user, 'product.view_product') 

17 

18 context = {"product_list": products} 

19 return render(request, "product_index.html", context) 

20 

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) 

26 

27 all_analysis = ProductRiskAnalysis.objects.filter(id__in=product.analyzes.all()) 

28 all_threat_models = ThreatModel.objects.filter(product=product).order_by("title") 

29 

30 context = {"product": product, "all_analysis": all_analysis, "all_threat_models": all_threat_models} 

31 return render(request, "product.html", context) 

32 

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 

39 

40 entry = get_object_or_404(ProductRiskEntry, pk=entry_id) 

41 old_risk = entry.risk 

42 

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 

47 

48 def _stride_str(risk): 

49 return ", ".join(sorted(s.name for s in risk.stride.all())) 

50 

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 ''}" 

56 

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 ] 

81 

82 for f in fields: 

83 f['changed'] = f['old'] != f['new'] 

84 

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) 

93 

94 

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") 

102 

103 risk_summery = ProductRiskAnalysis.get_risk_summary(product_analysis_entries) 

104 

105 pr_edit_allowed = request.user.has_perm("product.change_product", product) 

106 

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 } 

112 

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)