Coverage for product_risk_suite / product / admin.py: 56%

80 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-05-13 23:42 +0000

1from django.contrib import admin 

2from django.forms import SelectMultiple 

3from django.db import models 

4 

5from .models import Product, ProductRiskAnalysis, ProductRiskEntry 

6from threat_model.shared_models import ThreatModelConnectionName 

7from guardian.admin import GuardedModelAdmin 

8 

9class ProductAdmin(GuardedModelAdmin): 

10 list_display = ["title", "description"] 

11 prepopulated_fields = {"slug": ("title",)} 

12 

13class ProductRiskAnalysisAdmin(admin.ModelAdmin): 

14 filter_horizontal = ['risk_entries'] 

15 

16 list_display = ["name", "n_entries"] 

17 prepopulated_fields = {"slug": ("name",)} 

18 

19 @admin.display(description='N Entries') 

20 def n_entries(self, obj): 

21 return len(obj.risk_entries.all()) 

22 

23class ProductRiskEntryAdmin(admin.ModelAdmin): 

24 ordering = ['risk__custom_id'] 

25 def get_form(self, request, obj=None, **kwargs): 

26 form = super().get_form(request, obj, **kwargs) 

27 if obj is None: 

28 form.base_fields['svg_id'].help_text = "Here all available IDs are listed, if you do not know which matches, assign this entry to a product analysis and that to a product, then this list is reduced." 

29 else: 

30 form.base_fields['svg_id'].help_text = "Select one or more threat model connections this risk applies to." + "<br>" + form.base_fields['svg_id'].help_text 

31 return form 

32 

33 def formfield_for_manytomany(self, db_field, request, **kwargs): 

34 if db_field.name == "svg_id": 

35 # Get the current ProductRiskEntry instance (if editing) 

36 obj = request.resolver_match.kwargs.get('object_id') 

37 if obj: 

38 try: 

39 instance = ProductRiskEntry.objects.get(pk=obj) 

40 ras = ProductRiskAnalysis.objects.get(risk_entries=instance) 

41 products = Product.objects.get(analyzes=ras) 

42 connection_names = ThreatModelConnectionName.objects.filter( 

43 threatmodel__product=products 

44 ).distinct().order_by("name") 

45 kwargs['queryset'] = connection_names 

46 except (ProductRiskEntry.DoesNotExist, AttributeError): 

47 pass 

48 except (ProductRiskAnalysis.DoesNotExist, AttributeError): 

49 pass 

50 except (Product.DoesNotExist, AttributeError): 

51 pass 

52 else: 

53 # for a new instance ALL available tm link names are listed 

54 pass 

55 return super().formfield_for_manytomany(db_field, request, **kwargs) 

56 

57 filter_horizontal = ['evidences','svg_id'] 

58 

59 list_display = [ 

60 "risk_Id", 

61 "risk_title", 

62 "risk_asset", 

63 "risk_origin", 

64 "risk_stride", 

65 "tm_linked", 

66 "risk_initial", 

67 "risk_accepted", 

68 "risk_mitigated", 

69 "risk_after_mitigation", 

70 ] 

71 

72 @admin.display(description='Risk Id') 

73 def risk_Id(self, obj): 

74 return obj.risk.custom_id 

75 

76 @admin.display(description='risk title') 

77 def risk_title(self, obj): 

78 return obj.risk.title 

79 

80 @admin.display(description='Asset') 

81 def risk_asset(self, obj): 

82 return obj.risk.asset 

83 

84 @admin.display(description='Origin') 

85 def risk_origin(self, obj): 

86 return obj.risk.origin 

87 

88 @admin.display(description='Stride') 

89 def risk_stride(self, obj): 

90 return obj.risk.stride_str 

91 

92 @admin.display(description='Risk Accepted') 

93 def risk_accepted(self, obj): 

94 return obj.risk_accepted 

95 

96 @admin.display(description='TM Linked') 

97 def tm_linked(self, obj): 

98 return len(obj.svg_id.all()) > 0 

99 tm_linked.boolean = True 

100 

101 @admin.display(description='Risk Initial') 

102 def risk_initial(self, obj): 

103 return obj.risk_rating_initial.risk 

104 

105 @admin.display(description='Mitigated') 

106 def risk_mitigated(self, obj): 

107 return obj.risk_mitigation != None 

108 

109 @admin.display(description='Risk after Mitigation') 

110 def risk_after_mitigation(self, obj): 

111 if obj.risk_rating_after_mitigation: 

112 return obj.risk_rating_after_mitigation.risk 

113 return None 

114 

115admin.site.register(Product, ProductAdmin) 

116admin.site.register(ProductRiskAnalysis, ProductRiskAnalysisAdmin) 

117admin.site.register(ProductRiskEntry, ProductRiskEntryAdmin)