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
« 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
8from .models import *
10# fixtures
11class AssetAdmin(admin.ModelAdmin):
12 list_display = ["name"]
14class OriginAdmin(admin.ModelAdmin):
15 list_display = ["name"]
17class LifeCycleAdmin(admin.ModelAdmin):
18 list_display = ["name"]
20class SecurityRequirementAdmin(admin.ModelAdmin):
21 list_display = ["norm", "short", "description"]
22 prepopulated_fields = {"slug": ("norm_short", "description_short")}
24 formfield_overrides = {
25 models.TextField: { 'widget': SummernoteWidget()}
26 }
28 @admin.display(description='Norm')
29 def norm(self, obj):
30 return obj.norm_short
32 @admin.display(description='Short')
33 def short(self, obj):
34 return obj.description_short
36 @admin.display(description='Description')
37 def description(self, obj):
38 return obj.description_long
40admin.site.register(Asset, AssetAdmin)
41admin.site.register(Origin, OriginAdmin)
42admin.site.register(LifeCycle, LifeCycleAdmin)
43admin.site.register(SecurityRequirement, SecurityRequirementAdmin)
46# risks
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 )
59 class Meta:
60 model = Risk
61 fields = '__all__'
64_FIELDSETS_CREATE = [
65 (None, {
66 'fields': [
67 'custom_id', 'asset', 'origin', 'life_cycle', 'stride',
68 'title', 'description', 'suggested_mitigation_validation',
69 ],
70 }),
71]
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]
87class RiskAdmin(admin.ModelAdmin):
88 form = RiskAdminForm
89 formfield_overrides = {
90 models.TextField: {'widget': SummernoteWidget()}
91 }
92 readonly_fields = ['version', 'is_current']
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"]
98 def get_fieldsets(self, request, obj=None):
99 if obj is None:
100 return _FIELDSETS_CREATE
101 return _FIELDSETS_EDIT
103 @admin.display(description='Threat (Stride)')
104 def stride_str(self, obj):
105 return obj.stride_str
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)
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)
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)
151class RiskMitigationAdmin(admin.ModelAdmin):
152 filter_horizontal = ['security_requirements']
153 formfield_overrides = {
154 models.TextField: { 'widget': SummernoteWidget()}
155 }
157 list_display = ["title", "mitigation", "rational"]
159class RiskRatingAdmin(admin.ModelAdmin):
160 list_display = ["risk_str"]
161 ordering = ['likelihood_of_occurrence', 'severity_of_impact']
163 def risk_str(self, obj):
164 return str(obj)
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))
170update_evidences.short_description = "Update Evidences"
173class EvidenceAdmin(admin.ModelAdmin):
174 list_display = ["product", "status", "responsible", "evidence", "evidence_link"]
175 ordering = ['status','evidence']
176 actions = [update_evidences]
178admin.site.register(Risk, RiskAdmin)
179admin.site.register(RiskMitigation, RiskMitigationAdmin)
180admin.site.register(RiskRating, RiskRatingAdmin)
181admin.site.register(Evidence, EvidenceAdmin)
183# examples
184class SeverityExampleAdmin(admin.ModelAdmin):
185 formfield_overrides = {
186 models.TextField: { 'widget': SummernoteWidget()}
187 }
188 ordering = ['severity_of_impact']
190class LikelihoodExampleAdmin(admin.ModelAdmin):
191 formfield_overrides = {
192 models.TextField: { 'widget': SummernoteWidget()}
193 }
194 ordering = ['likelihood_of_occurrence']
196admin.site.register(SeverityExample, SeverityExampleAdmin)
197admin.site.register(LikelihoodExample, LikelihoodExampleAdmin)
199class SuggestedMitigationValidationAdmin(admin.ModelAdmin):
200 formfield_overrides = {
201 models.TextField: { 'widget': SummernoteWidget(attrs={'summernote': {'height': '200px'}})}
202 }
203 ordering = ['suggested_mitigation']
205admin.site.register(SuggestedMitigationValidation, SuggestedMitigationValidationAdmin)