Coverage for product_risk_suite/risk_assessment/admin.py: 97%

106 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-07 12:45 +0000

1from django.contrib import admin, messages 

2from django import forms 

3from django.db import models 

4from django_summernote.widgets import SummernoteWidget 

5from django.http import HttpResponseRedirect 

6from django.urls import reverse 

7 

8from .models import * 

9 

10# fixtures 

11class AssetAdmin(admin.ModelAdmin): 

12 list_display = ["name"] 

13 

14class OriginAdmin(admin.ModelAdmin): 

15 list_display = ["name"] 

16 

17class LifeCycleAdmin(admin.ModelAdmin): 

18 list_display = ["name"] 

19 

20class SecurityRequirementAdmin(admin.ModelAdmin): 

21 list_display = ["norm", "short", "description"] 

22 prepopulated_fields = {"slug": ("norm_short", "description_short")} 

23 

24 formfield_overrides = { 

25 models.TextField: { 'widget': SummernoteWidget()} 

26 } 

27 

28 @admin.display(description='Norm') 

29 def norm(self, obj): 

30 return obj.norm_short 

31 

32 @admin.display(description='Short') 

33 def short(self, obj): 

34 return obj.description_short 

35 

36 @admin.display(description='Description') 

37 def description(self, obj): 

38 return obj.description_long 

39 

40admin.site.register(Asset, AssetAdmin) 

41admin.site.register(Origin, OriginAdmin) 

42admin.site.register(LifeCycle, LifeCycleAdmin) 

43admin.site.register(SecurityRequirement, SecurityRequirementAdmin) 

44 

45 

46# risks 

47 

48class RiskAdminForm(forms.ModelForm): 

49 create_new_version = forms.BooleanField( 

50 required=False, 

51 label="Save as new version", 

52 help_text=( 

53 "Leave unchecked for minor in-place fixes (typos, wording). " 

54 "Check to preserve the current version and save your changes as a new one — " 

55 "product entries pointing to this risk will show an outdated indicator until upgraded." 

56 ), 

57 ) 

58 

59 class Meta: 

60 model = Risk 

61 fields = '__all__' 

62 

63 

64_FIELDSETS_CREATE = [ 

65 (None, { 

66 'fields': [ 

67 'custom_id', 'asset', 'origin', 'life_cycle', 'stride', 

68 'title', 'description', 'suggested_mitigation_validation', 

69 ], 

70 }), 

71] 

72 

73_FIELDSETS_EDIT = [ 

74 (None, { 

75 'fields': [ 

76 ('custom_id', 'version', 'is_current'), 

77 'asset', 'origin', 'life_cycle', 'stride', 

78 'title', 'description', 'suggested_mitigation_validation', 

79 ], 

80 }), 

81 ('Version control', { 

82 'fields': ['create_new_version'], 

83 }), 

84] 

85 

86 

87class RiskAdmin(admin.ModelAdmin): 

88 form = RiskAdminForm 

89 formfield_overrides = { 

90 models.TextField: {'widget': SummernoteWidget()} 

91 } 

92 readonly_fields = ['version', 'is_current'] 

93 

94 list_display = ["custom_id", "version", "is_current", "asset", "life_cycle", "origin", "stride_str", "title"] 

95 list_filter = ["is_current"] 

96 ordering = ["custom_id", "-version"] 

97 

98 def get_fieldsets(self, request, obj=None): 

99 if obj is None: 

100 return _FIELDSETS_CREATE 

101 return _FIELDSETS_EDIT 

102 

103 @admin.display(description='Threat (Stride)') 

104 def stride_str(self, obj): 

105 return obj.stride_str 

106 

107 def save_model(self, request, obj, form, change): 

108 if change and form.cleaned_data.get('create_new_version'): 

109 original = Risk.objects.get(pk=obj.pk) 

110 new_risk = Risk( 

111 custom_id=original.custom_id, 

112 version=original.version + 1, 

113 is_current=True, 

114 asset=obj.asset, 

115 origin=obj.origin, 

116 life_cycle=obj.life_cycle, 

117 title=obj.title, 

118 description=obj.description, 

119 suggested_mitigation_validation=obj.suggested_mitigation_validation, 

120 ) 

121 new_risk.save() 

122 original.is_current = False 

123 original.save() 

124 request._new_version_pk = new_risk.pk 

125 else: 

126 super().save_model(request, obj, form, change) 

127 

128 def save_related(self, request, form, formsets, change): 

129 if hasattr(request, '_new_version_pk'): 

130 new_risk = Risk.objects.get(pk=request._new_version_pk) 

131 new_risk.stride.set(form.cleaned_data.get('stride', [])) 

132 else: 

133 super().save_related(request, form, formsets, change) 

134 

135 def response_change(self, request, obj): 

136 if hasattr(request, '_new_version_pk'): 

137 pk = request._new_version_pk 

138 new_risk = Risk.objects.get(pk=pk) 

139 del request._new_version_pk 

140 self.message_user( 

141 request, 

142 f"New version {new_risk.custom_id} v{new_risk.version} created.", 

143 messages.SUCCESS, 

144 ) 

145 return HttpResponseRedirect( 

146 reverse('admin:risk_assessment_risk_change', args=[pk]) 

147 ) 

148 return super().response_change(request, obj) 

149 

150 

151class RiskMitigationAdmin(admin.ModelAdmin): 

152 filter_horizontal = ['security_requirements'] 

153 formfield_overrides = { 

154 models.TextField: { 'widget': SummernoteWidget()} 

155 } 

156 

157 list_display = ["title", "mitigation", "rational"] 

158 

159class RiskRatingAdmin(admin.ModelAdmin): 

160 list_display = ["risk_str"] 

161 ordering = ['likelihood_of_occurrence', 'severity_of_impact'] 

162 

163 def risk_str(self, obj): 

164 return str(obj) 

165 

166def update_evidences(modeladmin, request, queryset): 

167 evidence_ids = queryset.values_list('id', flat=True) 

168 return HttpResponseRedirect(reverse('evidence_product_update') + '?ids=' + ','.join(str(p) for p in evidence_ids)) 

169 

170update_evidences.short_description = "Update Evidences" 

171 

172 

173class EvidenceAdmin(admin.ModelAdmin): 

174 list_display = ["product", "status", "responsible", "evidence", "evidence_link"] 

175 ordering = ['status','evidence'] 

176 actions = [update_evidences] 

177 

178admin.site.register(Risk, RiskAdmin) 

179admin.site.register(RiskMitigation, RiskMitigationAdmin) 

180admin.site.register(RiskRating, RiskRatingAdmin) 

181admin.site.register(Evidence, EvidenceAdmin) 

182 

183# examples 

184class SeverityExampleAdmin(admin.ModelAdmin): 

185 formfield_overrides = { 

186 models.TextField: { 'widget': SummernoteWidget()} 

187 } 

188 ordering = ['severity_of_impact'] 

189 

190class LikelihoodExampleAdmin(admin.ModelAdmin): 

191 formfield_overrides = { 

192 models.TextField: { 'widget': SummernoteWidget()} 

193 } 

194 ordering = ['likelihood_of_occurrence'] 

195 

196admin.site.register(SeverityExample, SeverityExampleAdmin) 

197admin.site.register(LikelihoodExample, LikelihoodExampleAdmin) 

198 

199class SuggestedMitigationValidationAdmin(admin.ModelAdmin): 

200 formfield_overrides = { 

201 models.TextField: { 'widget': SummernoteWidget(attrs={'summernote': {'height': '200px'}})} 

202 } 

203 ordering = ['suggested_mitigation'] 

204 

205admin.site.register(SuggestedMitigationValidation, SuggestedMitigationValidationAdmin)