wbcompliance 2.2.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wbcompliance/__init__.py +1 -0
- wbcompliance/admin/__init__.py +16 -0
- wbcompliance/admin/compliance_form.py +56 -0
- wbcompliance/admin/compliance_task.py +135 -0
- wbcompliance/admin/compliance_type.py +8 -0
- wbcompliance/admin/risk_management/__init__.py +3 -0
- wbcompliance/admin/risk_management/checks.py +7 -0
- wbcompliance/admin/risk_management/incidents.py +50 -0
- wbcompliance/admin/risk_management/rules.py +63 -0
- wbcompliance/admin/utils.py +46 -0
- wbcompliance/apps.py +14 -0
- wbcompliance/factories/__init__.py +21 -0
- wbcompliance/factories/compliance.py +246 -0
- wbcompliance/factories/risk_management/__init__.py +12 -0
- wbcompliance/factories/risk_management/backends.py +42 -0
- wbcompliance/factories/risk_management/checks.py +12 -0
- wbcompliance/factories/risk_management/incidents.py +84 -0
- wbcompliance/factories/risk_management/rules.py +100 -0
- wbcompliance/filters/__init__.py +2 -0
- wbcompliance/filters/compliances.py +189 -0
- wbcompliance/filters/risk_management/__init__.py +3 -0
- wbcompliance/filters/risk_management/checks.py +22 -0
- wbcompliance/filters/risk_management/incidents.py +113 -0
- wbcompliance/filters/risk_management/rules.py +110 -0
- wbcompliance/filters/risk_management/tables.py +112 -0
- wbcompliance/filters/risk_management/utils.py +3 -0
- wbcompliance/management/__init__.py +10 -0
- wbcompliance/migrations/0001_initial_squashed_squashed_0010_alter_checkedobjectincidentrelationship_resolved_by_and_more.py +1744 -0
- wbcompliance/migrations/0011_alter_riskrule_parameters.py +21 -0
- wbcompliance/migrations/0012_alter_compliancetype_options.py +20 -0
- wbcompliance/migrations/0013_alter_riskrule_unique_together.py +16 -0
- wbcompliance/migrations/0014_alter_reviewcompliancetask_year.py +27 -0
- wbcompliance/migrations/0015_auto_20240103_0957.py +43 -0
- wbcompliance/migrations/0016_checkedobjectincidentrelationship_report_details_and_more.py +37 -0
- wbcompliance/migrations/0017_alter_rulebackend_incident_report_template.py +20 -0
- wbcompliance/migrations/0018_alter_rulecheckedobjectrelationship_unique_together.py +39 -0
- wbcompliance/migrations/0019_rulegroup_riskrule_activation_date_and_more.py +60 -0
- wbcompliance/migrations/__init__.py +0 -0
- wbcompliance/models/__init__.py +20 -0
- wbcompliance/models/compliance_form.py +626 -0
- wbcompliance/models/compliance_task.py +800 -0
- wbcompliance/models/compliance_type.py +133 -0
- wbcompliance/models/enums.py +13 -0
- wbcompliance/models/risk_management/__init__.py +4 -0
- wbcompliance/models/risk_management/backend.py +139 -0
- wbcompliance/models/risk_management/checks.py +194 -0
- wbcompliance/models/risk_management/dispatch.py +41 -0
- wbcompliance/models/risk_management/incidents.py +619 -0
- wbcompliance/models/risk_management/mixins.py +115 -0
- wbcompliance/models/risk_management/rules.py +654 -0
- wbcompliance/permissions.py +32 -0
- wbcompliance/serializers/__init__.py +30 -0
- wbcompliance/serializers/compliance_form.py +320 -0
- wbcompliance/serializers/compliance_task.py +463 -0
- wbcompliance/serializers/compliance_type.py +26 -0
- wbcompliance/serializers/risk_management/__init__.py +19 -0
- wbcompliance/serializers/risk_management/checks.py +53 -0
- wbcompliance/serializers/risk_management/incidents.py +227 -0
- wbcompliance/serializers/risk_management/rules.py +158 -0
- wbcompliance/tasks.py +112 -0
- wbcompliance/tests/__init__.py +0 -0
- wbcompliance/tests/conftest.py +63 -0
- wbcompliance/tests/disable_signals.py +82 -0
- wbcompliance/tests/mixins.py +17 -0
- wbcompliance/tests/risk_management/__init__.py +0 -0
- wbcompliance/tests/risk_management/models/__init__.py +0 -0
- wbcompliance/tests/risk_management/models/test_backends.py +0 -0
- wbcompliance/tests/risk_management/models/test_checks.py +55 -0
- wbcompliance/tests/risk_management/models/test_incidents.py +327 -0
- wbcompliance/tests/risk_management/models/test_rules.py +255 -0
- wbcompliance/tests/signals.py +89 -0
- wbcompliance/tests/test_filters.py +23 -0
- wbcompliance/tests/test_models.py +57 -0
- wbcompliance/tests/test_serializers.py +48 -0
- wbcompliance/tests/test_views.py +377 -0
- wbcompliance/tests/tests.py +21 -0
- wbcompliance/urls.py +238 -0
- wbcompliance/viewsets/__init__.py +40 -0
- wbcompliance/viewsets/buttons/__init__.py +9 -0
- wbcompliance/viewsets/buttons/compliance_form.py +78 -0
- wbcompliance/viewsets/buttons/compliance_task.py +149 -0
- wbcompliance/viewsets/buttons/risk_managment/__init__.py +3 -0
- wbcompliance/viewsets/buttons/risk_managment/checks.py +11 -0
- wbcompliance/viewsets/buttons/risk_managment/incidents.py +51 -0
- wbcompliance/viewsets/buttons/risk_managment/rules.py +35 -0
- wbcompliance/viewsets/compliance_form.py +425 -0
- wbcompliance/viewsets/compliance_task.py +513 -0
- wbcompliance/viewsets/compliance_type.py +38 -0
- wbcompliance/viewsets/display/__init__.py +22 -0
- wbcompliance/viewsets/display/compliance_form.py +317 -0
- wbcompliance/viewsets/display/compliance_task.py +453 -0
- wbcompliance/viewsets/display/compliance_type.py +22 -0
- wbcompliance/viewsets/display/risk_managment/__init__.py +11 -0
- wbcompliance/viewsets/display/risk_managment/checks.py +46 -0
- wbcompliance/viewsets/display/risk_managment/incidents.py +155 -0
- wbcompliance/viewsets/display/risk_managment/rules.py +146 -0
- wbcompliance/viewsets/display/risk_managment/tables.py +51 -0
- wbcompliance/viewsets/endpoints/__init__.py +27 -0
- wbcompliance/viewsets/endpoints/compliance_form.py +207 -0
- wbcompliance/viewsets/endpoints/compliance_task.py +193 -0
- wbcompliance/viewsets/endpoints/compliance_type.py +9 -0
- wbcompliance/viewsets/endpoints/risk_managment/__init__.py +12 -0
- wbcompliance/viewsets/endpoints/risk_managment/checks.py +16 -0
- wbcompliance/viewsets/endpoints/risk_managment/incidents.py +36 -0
- wbcompliance/viewsets/endpoints/risk_managment/rules.py +32 -0
- wbcompliance/viewsets/endpoints/risk_managment/tables.py +14 -0
- wbcompliance/viewsets/menu/__init__.py +17 -0
- wbcompliance/viewsets/menu/compliance_form.py +49 -0
- wbcompliance/viewsets/menu/compliance_task.py +130 -0
- wbcompliance/viewsets/menu/compliance_type.py +17 -0
- wbcompliance/viewsets/menu/risk_management.py +56 -0
- wbcompliance/viewsets/risk_management/__init__.py +21 -0
- wbcompliance/viewsets/risk_management/checks.py +49 -0
- wbcompliance/viewsets/risk_management/incidents.py +204 -0
- wbcompliance/viewsets/risk_management/mixins.py +52 -0
- wbcompliance/viewsets/risk_management/rules.py +179 -0
- wbcompliance/viewsets/risk_management/tables.py +96 -0
- wbcompliance/viewsets/titles/__init__.py +17 -0
- wbcompliance/viewsets/titles/compliance_form.py +101 -0
- wbcompliance/viewsets/titles/compliance_task.py +60 -0
- wbcompliance/viewsets/titles/compliance_type.py +13 -0
- wbcompliance/viewsets/titles/risk_managment/__init__.py +1 -0
- wbcompliance/viewsets/titles/risk_managment/checks.py +0 -0
- wbcompliance/viewsets/titles/risk_managment/incidents.py +0 -0
- wbcompliance/viewsets/titles/risk_managment/rules.py +0 -0
- wbcompliance/viewsets/titles/risk_managment/tables.py +7 -0
- wbcompliance-2.2.1.dist-info/METADATA +7 -0
- wbcompliance-2.2.1.dist-info/RECORD +129 -0
- wbcompliance-2.2.1.dist-info/WHEEL +5 -0
wbcompliance/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .compliance_form import (
|
|
2
|
+
ComplianceFormAdmin,
|
|
3
|
+
ComplianceFormRuleAdmin,
|
|
4
|
+
ComplianceFormSectionAdmin,
|
|
5
|
+
ComplianceFormSignatureAdmin,
|
|
6
|
+
ComplianceFormSignatureRuleAdmin,
|
|
7
|
+
ComplianceFormSignatureSectionAdmin,
|
|
8
|
+
ComplianceFormTypeAdmin,
|
|
9
|
+
)
|
|
10
|
+
from .compliance_task import (
|
|
11
|
+
ComplianceActionAdmin,
|
|
12
|
+
ComplianceEventAdmin,
|
|
13
|
+
ReviewComplianceTaskAdmin,
|
|
14
|
+
)
|
|
15
|
+
from .compliance_type import ComplianceTypeAdmin
|
|
16
|
+
from .risk_management import *
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from reversion_compare.admin import CompareVersionAdmin
|
|
3
|
+
from wbcompliance.models import (
|
|
4
|
+
ComplianceForm,
|
|
5
|
+
ComplianceFormRule,
|
|
6
|
+
ComplianceFormSection,
|
|
7
|
+
ComplianceFormSignature,
|
|
8
|
+
ComplianceFormSignatureRule,
|
|
9
|
+
ComplianceFormSignatureSection,
|
|
10
|
+
ComplianceFormType,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@admin.register(ComplianceFormType)
|
|
15
|
+
class ComplianceFormTypeAdmin(CompareVersionAdmin):
|
|
16
|
+
list_display = ["name", "type"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@admin.register(ComplianceForm)
|
|
20
|
+
class ComplianceFormAdmin(CompareVersionAdmin):
|
|
21
|
+
list_display = ["status", "creator", "created", "title"]
|
|
22
|
+
|
|
23
|
+
autocomplete_fields = ["creator"]
|
|
24
|
+
|
|
25
|
+
def reversion_register(self, model, **options):
|
|
26
|
+
options = {
|
|
27
|
+
"ignore_duplicates": True,
|
|
28
|
+
}
|
|
29
|
+
super().reversion_register(model, **options)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@admin.register(ComplianceFormSignature)
|
|
33
|
+
class ComplianceFormSignatureAdmin(CompareVersionAdmin):
|
|
34
|
+
list_display = ["compliance_form", "version", "signed", "person"]
|
|
35
|
+
|
|
36
|
+
autocomplete_fields = ["person"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@admin.register(ComplianceFormSection)
|
|
40
|
+
class ComplianceFormSectionAdmin(CompareVersionAdmin):
|
|
41
|
+
list_display = ["compliance_form", "name"]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@admin.register(ComplianceFormRule)
|
|
45
|
+
class ComplianceFormRuleAdmin(CompareVersionAdmin):
|
|
46
|
+
list_display = ["section", "text", "ticked"]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@admin.register(ComplianceFormSignatureSection)
|
|
50
|
+
class ComplianceFormSignatureSectionAdmin(CompareVersionAdmin):
|
|
51
|
+
list_display = ["compliance_form_signature", "name"]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@admin.register(ComplianceFormSignatureRule)
|
|
55
|
+
class ComplianceFormSignatureRuleAdmin(CompareVersionAdmin):
|
|
56
|
+
list_display = ["section", "text", "ticked", "comments"]
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from django.contrib import admin
|
|
3
|
+
from reversion_compare.admin import CompareVersionAdmin
|
|
4
|
+
from wbcompliance.models import (
|
|
5
|
+
ComplianceAction,
|
|
6
|
+
ComplianceEvent,
|
|
7
|
+
ComplianceTask,
|
|
8
|
+
ComplianceTaskGroup,
|
|
9
|
+
ComplianceTaskInstance,
|
|
10
|
+
ComplianceType,
|
|
11
|
+
ReviewComplianceTask,
|
|
12
|
+
)
|
|
13
|
+
from wbcore.admin import ExportCsvMixin
|
|
14
|
+
|
|
15
|
+
from .utils import CustomImportCsvMixin
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@admin.register(ComplianceTaskGroup)
|
|
19
|
+
class ComplianceTaskGroupAdmin(ExportCsvMixin, CustomImportCsvMixin, CompareVersionAdmin):
|
|
20
|
+
list_display = ["name", "order"]
|
|
21
|
+
|
|
22
|
+
def manipulate_df(self, df):
|
|
23
|
+
df["name"] = df["name"].fillna("")
|
|
24
|
+
return df
|
|
25
|
+
|
|
26
|
+
def get_import_fields(self):
|
|
27
|
+
return [
|
|
28
|
+
"name",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
def process_model(self, model):
|
|
32
|
+
if model.get("name"):
|
|
33
|
+
_, created = self.model.objects.get_or_create(name=model.get("name"))
|
|
34
|
+
return 1 if created else 0
|
|
35
|
+
return 0
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@admin.register(ComplianceTask)
|
|
39
|
+
class ComplianceTaskAdmin(ExportCsvMixin, CustomImportCsvMixin, CompareVersionAdmin):
|
|
40
|
+
list_display = ["title", "occurrence", "active", "risk_level", "group", "type"]
|
|
41
|
+
|
|
42
|
+
def manipulate_df(self, df):
|
|
43
|
+
df["type"] = df["type_name"].apply(lambda x: ComplianceType.objects.filter(name__exact=x).first())
|
|
44
|
+
df["group"] = df.apply(
|
|
45
|
+
lambda x: ComplianceTaskGroup.objects.filter(name__exact=x["group_name"]).first(), axis=1
|
|
46
|
+
)
|
|
47
|
+
return df
|
|
48
|
+
|
|
49
|
+
def get_import_fields(self):
|
|
50
|
+
return ["type_name", "group_name", "occurrence", "title", "description"]
|
|
51
|
+
|
|
52
|
+
def process_model(self, model):
|
|
53
|
+
if model.get("title"):
|
|
54
|
+
_, created = self.model.objects.update_or_create(
|
|
55
|
+
title=model.get("title"),
|
|
56
|
+
defaults={
|
|
57
|
+
"type": model.get("type"),
|
|
58
|
+
"group": model.get("group"),
|
|
59
|
+
"occurrence": model.get("occurrence"),
|
|
60
|
+
# 'description': model.get('description')
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
return 1 if created else 0
|
|
64
|
+
return 0
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@admin.register(ComplianceTaskInstance)
|
|
68
|
+
class ComplianceTaskInstanceAdmin(ExportCsvMixin, CustomImportCsvMixin, CompareVersionAdmin):
|
|
69
|
+
list_display = ["task", "occured", "status"]
|
|
70
|
+
|
|
71
|
+
def manipulate_df(self, df):
|
|
72
|
+
df["task"] = df.apply(lambda x: ComplianceTask.objects.filter(title__exact=x["task_name"]).first(), axis=1)
|
|
73
|
+
df["occured"] = pd.to_datetime(df["occured"])
|
|
74
|
+
return df
|
|
75
|
+
|
|
76
|
+
def get_import_fields(self):
|
|
77
|
+
return ["task_name", "occured", "status", "text"]
|
|
78
|
+
|
|
79
|
+
def process_model(self, model):
|
|
80
|
+
if (task := model.get("task")) and (occured := model.get("occured")):
|
|
81
|
+
obj, created = self.model.objects.update_or_create(
|
|
82
|
+
task=task,
|
|
83
|
+
occured=occured,
|
|
84
|
+
defaults={
|
|
85
|
+
"status": model.get("status"),
|
|
86
|
+
"text": model.get("text"),
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
if created:
|
|
90
|
+
obj.occured = occured
|
|
91
|
+
obj.save()
|
|
92
|
+
|
|
93
|
+
return 1 if created else 0
|
|
94
|
+
return 0
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@admin.register(ComplianceAction)
|
|
98
|
+
class ComplianceActionAdmin(CompareVersionAdmin):
|
|
99
|
+
search_fields = ["title"]
|
|
100
|
+
list_display = [
|
|
101
|
+
"title",
|
|
102
|
+
"deadline",
|
|
103
|
+
"progress",
|
|
104
|
+
"status",
|
|
105
|
+
"type",
|
|
106
|
+
"creator",
|
|
107
|
+
"created",
|
|
108
|
+
"changer",
|
|
109
|
+
"last_modified",
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@admin.register(ComplianceEvent)
|
|
114
|
+
class ComplianceEventAdmin(CompareVersionAdmin):
|
|
115
|
+
search_fields = ["title"]
|
|
116
|
+
list_display = ["title", "type", "level", "type", "confidential", "creator", "created", "changer", "last_modified"]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@admin.register(ReviewComplianceTask)
|
|
120
|
+
class ReviewComplianceTaskAdmin(CompareVersionAdmin):
|
|
121
|
+
list_display = [
|
|
122
|
+
"id",
|
|
123
|
+
"year",
|
|
124
|
+
"title",
|
|
125
|
+
"from_date",
|
|
126
|
+
"to_date",
|
|
127
|
+
"status",
|
|
128
|
+
"occurrence",
|
|
129
|
+
"is_instance",
|
|
130
|
+
"changer",
|
|
131
|
+
"changed",
|
|
132
|
+
"review_task",
|
|
133
|
+
"occured",
|
|
134
|
+
]
|
|
135
|
+
search_fields = ["title"]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from wbcompliance.models.risk_management.checks import RiskCheck
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@admin.register(RiskCheck)
|
|
6
|
+
class RiskCheckModelAdmin(admin.ModelAdmin):
|
|
7
|
+
list_display = ["rule_checked_object_relationship", "creation_datetime", "evaluation_date"]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from wbcompliance.models.risk_management.incidents import (
|
|
3
|
+
CheckedObjectIncidentRelationship,
|
|
4
|
+
RiskIncident,
|
|
5
|
+
RiskIncidentType,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CheckedObjectIncidentRelationshipInLine(admin.TabularInline):
|
|
10
|
+
model = CheckedObjectIncidentRelationship
|
|
11
|
+
fields = ["status", "severity", "incident", "rule_check", "breached_value", "report_details", "report"]
|
|
12
|
+
extra = 0
|
|
13
|
+
raw_id_fields = ["incident", "rule_check"]
|
|
14
|
+
readonly_fields = ["status", "severity", "incident", "rule_check"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class IncidentInLine(admin.TabularInline):
|
|
18
|
+
show_change_link = True
|
|
19
|
+
model = RiskIncident
|
|
20
|
+
fields = ["status", "severity", "date_range", "breached_content_type", "breached_object_id"]
|
|
21
|
+
extra = 0
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@admin.register(RiskIncidentType)
|
|
25
|
+
class RiskIncidentTypeModelAdmin(admin.ModelAdmin):
|
|
26
|
+
list_display = [
|
|
27
|
+
"name",
|
|
28
|
+
"severity_order",
|
|
29
|
+
"color",
|
|
30
|
+
"is_ignorable",
|
|
31
|
+
"is_automatically_closed",
|
|
32
|
+
"is_informational",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@admin.register(RiskIncident)
|
|
37
|
+
class RiskIncidentModelAdmin(admin.ModelAdmin):
|
|
38
|
+
list_display = [
|
|
39
|
+
"status",
|
|
40
|
+
"severity",
|
|
41
|
+
"date_range",
|
|
42
|
+
"rule",
|
|
43
|
+
"breached_content_type",
|
|
44
|
+
"breached_object_id",
|
|
45
|
+
"resolved_by",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
inlines = [
|
|
49
|
+
CheckedObjectIncidentRelationshipInLine,
|
|
50
|
+
]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from guardian.admin import GuardedModelAdmin
|
|
3
|
+
from wbcompliance.models.risk_management.rules import (
|
|
4
|
+
RiskRule,
|
|
5
|
+
RuleBackend,
|
|
6
|
+
RuleCheckedObjectRelationship,
|
|
7
|
+
RuleGroup,
|
|
8
|
+
RuleThreshold,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from .incidents import IncidentInLine
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RuleThresholdInLine(admin.TabularInline):
|
|
15
|
+
model = RuleThreshold
|
|
16
|
+
fields = ["range", "severity", "notifiable_users", "notifiable_groups"]
|
|
17
|
+
extra = 0
|
|
18
|
+
autocomplete_fields = ["notifiable_users"]
|
|
19
|
+
raw_id_fields = ["notifiable_users", "notifiable_groups", "rule"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RuleCheckedObjectRelationshipInLine(admin.TabularInline):
|
|
23
|
+
model = RuleCheckedObjectRelationship
|
|
24
|
+
fields = [
|
|
25
|
+
"checked_object_content_type",
|
|
26
|
+
"checked_object_id",
|
|
27
|
+
]
|
|
28
|
+
extra = 0
|
|
29
|
+
raw_id_fields = ["checked_object_content_type", "rule"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@admin.register(RuleGroup)
|
|
33
|
+
class RuleGroupModelAdmin(admin.ModelAdmin):
|
|
34
|
+
list_display = [
|
|
35
|
+
"key",
|
|
36
|
+
"name",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@admin.register(RuleBackend)
|
|
41
|
+
class RuleBackendModelAdmin(admin.ModelAdmin):
|
|
42
|
+
list_display = [
|
|
43
|
+
"name",
|
|
44
|
+
"rule_group",
|
|
45
|
+
"backend_class_path",
|
|
46
|
+
"backend_class_name",
|
|
47
|
+
"allowed_checked_object_content_type",
|
|
48
|
+
]
|
|
49
|
+
raw_id_fields = ["allowed_checked_object_content_type"]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@admin.register(RiskRule)
|
|
53
|
+
class RiskRuleModelAdmin(GuardedModelAdmin):
|
|
54
|
+
list_display = [
|
|
55
|
+
"name",
|
|
56
|
+
"rule_backend",
|
|
57
|
+
"is_enable",
|
|
58
|
+
"only_passive_check_allowed",
|
|
59
|
+
"is_silent",
|
|
60
|
+
"is_mandatory",
|
|
61
|
+
"parameters",
|
|
62
|
+
]
|
|
63
|
+
inlines = [RuleThresholdInLine, IncidentInLine, RuleCheckedObjectRelationshipInLine]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from io import StringIO
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from django.shortcuts import redirect, render
|
|
5
|
+
from reversion.errors import RevertError
|
|
6
|
+
from wbcore.admin import CsvImportForm, ImportCsvMixin
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CustomImportCsvMixin(ImportCsvMixin):
|
|
10
|
+
def _import_csv(self, request, _sep=";"):
|
|
11
|
+
if request.method == "POST":
|
|
12
|
+
csv_file = request.FILES["csv_file"]
|
|
13
|
+
|
|
14
|
+
str_text = ""
|
|
15
|
+
for line in csv_file:
|
|
16
|
+
str_text = str_text + line.decode()
|
|
17
|
+
# Import csv as df
|
|
18
|
+
df = pd.read_csv(StringIO(str_text), sep=_sep)
|
|
19
|
+
# Sanitize dataframe
|
|
20
|
+
df = df.where(pd.notnull(df), None)
|
|
21
|
+
df = df.drop(df.columns.difference(self.get_import_fields()), axis=1)
|
|
22
|
+
|
|
23
|
+
# Overide this function if there is foreign key ids in the dataframe
|
|
24
|
+
df = self.manipulate_df(df)
|
|
25
|
+
errors = 0
|
|
26
|
+
revert_errors = 0
|
|
27
|
+
nb_added = 0
|
|
28
|
+
for model in df.to_dict("records"):
|
|
29
|
+
# by default, process the modela as a create request. Can be override to change the behavior
|
|
30
|
+
try:
|
|
31
|
+
nb_added += self.process_model(model)
|
|
32
|
+
# https://django-reversion.readthedocs.io/en/stable/common-problems.html
|
|
33
|
+
except RevertError:
|
|
34
|
+
revert_errors += 1
|
|
35
|
+
except Exception as e:
|
|
36
|
+
print(e) # noqa: T201
|
|
37
|
+
errors += 1
|
|
38
|
+
msg = f"""Your csv file has been imported : {df.shape[0] - errors - revert_errors} imported
|
|
39
|
+
({nb_added} added, {df.shape[0] - errors - revert_errors - nb_added} updated), {errors} errors,
|
|
40
|
+
{revert_errors} revert errors found due to failure to restore old versions
|
|
41
|
+
"""
|
|
42
|
+
self.message_user(request, msg)
|
|
43
|
+
return redirect("..")
|
|
44
|
+
form = CsvImportForm()
|
|
45
|
+
payload = {"form": form}
|
|
46
|
+
return render(request, "wbcore/admin/csv_form.html", payload)
|
wbcompliance/apps.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
from django.db.models.signals import post_migrate
|
|
3
|
+
from wbcompliance.management import autodiscover_riskmanagement_backends
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WbcomplianceConfig(AppConfig):
|
|
7
|
+
name = "wbcompliance"
|
|
8
|
+
|
|
9
|
+
#
|
|
10
|
+
def ready(self) -> None:
|
|
11
|
+
post_migrate.connect(
|
|
12
|
+
autodiscover_riskmanagement_backends,
|
|
13
|
+
dispatch_uid="wbcrm.synchronization.initialize_task",
|
|
14
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .compliance import (
|
|
2
|
+
ComplianceActionFactory,
|
|
3
|
+
ComplianceEventFactory,
|
|
4
|
+
ComplianceFormFactory,
|
|
5
|
+
ComplianceFormRuleFactory,
|
|
6
|
+
ComplianceFormSectionFactory,
|
|
7
|
+
ComplianceFormSignatureFactory,
|
|
8
|
+
ComplianceFormSignatureRuleFactory,
|
|
9
|
+
ComplianceFormSignatureSectionFactory,
|
|
10
|
+
ComplianceFormTypeFactory,
|
|
11
|
+
ComplianceTaskFactory,
|
|
12
|
+
ComplianceTaskGroupFactory,
|
|
13
|
+
ComplianceTaskInstanceFactory,
|
|
14
|
+
ComplianceTaskInstanceReviewFactory,
|
|
15
|
+
ComplianceTaskInstanceReviewNoGroupFactory,
|
|
16
|
+
ComplianceTaskReviewFactory,
|
|
17
|
+
ComplianceTaskReviewNoGroupFactory,
|
|
18
|
+
ComplianceTypeFactory,
|
|
19
|
+
UnsignedComplianceFormSignatureFactory,
|
|
20
|
+
)
|
|
21
|
+
from .risk_management import *
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import factory
|
|
2
|
+
import pytz
|
|
3
|
+
from wbcompliance.models import (
|
|
4
|
+
ComplianceAction,
|
|
5
|
+
ComplianceEvent,
|
|
6
|
+
ComplianceForm,
|
|
7
|
+
ComplianceFormRule,
|
|
8
|
+
ComplianceFormSection,
|
|
9
|
+
ComplianceFormSignature,
|
|
10
|
+
ComplianceFormSignatureRule,
|
|
11
|
+
ComplianceFormSignatureSection,
|
|
12
|
+
ComplianceFormType,
|
|
13
|
+
ComplianceTask,
|
|
14
|
+
ComplianceTaskGroup,
|
|
15
|
+
ComplianceTaskInstance,
|
|
16
|
+
ComplianceType,
|
|
17
|
+
ReviewComplianceTask,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ComplianceFormTypeFactory(factory.django.DjangoModelFactory):
|
|
22
|
+
class Meta:
|
|
23
|
+
model = ComplianceFormType
|
|
24
|
+
|
|
25
|
+
name = factory.Faker("text", max_nb_chars=32)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ComplianceFormFactory(factory.django.DjangoModelFactory):
|
|
29
|
+
class Meta:
|
|
30
|
+
model = ComplianceForm
|
|
31
|
+
|
|
32
|
+
form_type = factory.SubFactory(ComplianceFormTypeFactory)
|
|
33
|
+
creator = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
34
|
+
created = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
35
|
+
changer = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
36
|
+
changed = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
37
|
+
title = factory.Faker("text", max_nb_chars=64)
|
|
38
|
+
policy = factory.Faker("paragraph", nb_sentences=5)
|
|
39
|
+
only_internal = factory.Faker("pybool")
|
|
40
|
+
start = factory.Faker("date_between", start_date="+2d", end_date="+3d")
|
|
41
|
+
end = factory.Faker("date_between", start_date="+4d", end_date="+5d")
|
|
42
|
+
compliance_type = factory.SubFactory("wbcompliance.factories.ComplianceTypeFactory")
|
|
43
|
+
|
|
44
|
+
@factory.post_generation
|
|
45
|
+
def assigned_to(self, create, extracted, **kwargs):
|
|
46
|
+
if not create:
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
if extracted:
|
|
50
|
+
for group in extracted:
|
|
51
|
+
self.assigned_to.add(group)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class UnsignedComplianceFormSignatureFactory(factory.django.DjangoModelFactory):
|
|
55
|
+
class Meta:
|
|
56
|
+
model = ComplianceFormSignature
|
|
57
|
+
|
|
58
|
+
compliance_form = factory.SubFactory(ComplianceFormFactory)
|
|
59
|
+
policy = factory.Faker("paragraph", nb_sentences=5)
|
|
60
|
+
person = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
61
|
+
remark = factory.Faker("paragraph", nb_sentences=5)
|
|
62
|
+
start = factory.Faker("date_between", start_date="+2d", end_date="+3d")
|
|
63
|
+
end = factory.Faker("date_between", start_date="+4d", end_date="+5d")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ComplianceFormSignatureFactory(UnsignedComplianceFormSignatureFactory):
|
|
67
|
+
signed = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ComplianceFormSectionFactory(factory.django.DjangoModelFactory):
|
|
71
|
+
class Meta:
|
|
72
|
+
model = ComplianceFormSection
|
|
73
|
+
|
|
74
|
+
compliance_form = factory.SubFactory(ComplianceFormFactory)
|
|
75
|
+
name = factory.Faker("text", max_nb_chars=32)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class ComplianceFormRuleFactory(factory.django.DjangoModelFactory):
|
|
79
|
+
class Meta:
|
|
80
|
+
model = ComplianceFormRule
|
|
81
|
+
|
|
82
|
+
section = factory.SubFactory(ComplianceFormSectionFactory)
|
|
83
|
+
text = factory.Faker("text", max_nb_chars=255)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class ComplianceFormSignatureSectionFactory(factory.django.DjangoModelFactory):
|
|
87
|
+
class Meta:
|
|
88
|
+
model = ComplianceFormSignatureSection
|
|
89
|
+
|
|
90
|
+
compliance_form_signature = factory.SubFactory(UnsignedComplianceFormSignatureFactory)
|
|
91
|
+
name = factory.Faker("text", max_nb_chars=32)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ComplianceFormSignatureRuleFactory(factory.django.DjangoModelFactory):
|
|
95
|
+
class Meta:
|
|
96
|
+
model = ComplianceFormSignatureRule
|
|
97
|
+
|
|
98
|
+
section = factory.SubFactory(ComplianceFormSignatureSectionFactory)
|
|
99
|
+
text = factory.Faker("text", max_nb_chars=255)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class ComplianceTypeFactory(factory.django.DjangoModelFactory):
|
|
103
|
+
class Meta:
|
|
104
|
+
model = ComplianceType
|
|
105
|
+
|
|
106
|
+
name = factory.Faker("text", max_nb_chars=32)
|
|
107
|
+
description = factory.Faker("text", max_nb_chars=255)
|
|
108
|
+
|
|
109
|
+
@factory.post_generation
|
|
110
|
+
def in_charge(self, create, extracted, **kwargs):
|
|
111
|
+
if not create:
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
if extracted:
|
|
115
|
+
for group in extracted:
|
|
116
|
+
self.in_charge.add(group)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ComplianceTaskGroupFactory(factory.django.DjangoModelFactory):
|
|
120
|
+
class Meta:
|
|
121
|
+
model = ComplianceTaskGroup
|
|
122
|
+
|
|
123
|
+
name = factory.Faker("text", max_nb_chars=32)
|
|
124
|
+
order = factory.Faker("pyint", min_value=0, max_value=9999)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class ParentReviewComplianceTaskFactory(factory.django.DjangoModelFactory):
|
|
128
|
+
class Meta:
|
|
129
|
+
model = ReviewComplianceTask
|
|
130
|
+
|
|
131
|
+
title = factory.Faker("text", max_nb_chars=32)
|
|
132
|
+
from_date = factory.Faker("date_between", start_date="+2d", end_date="+3d")
|
|
133
|
+
to_date = factory.Faker("date_between", start_date="+4d", end_date="+5d")
|
|
134
|
+
description = factory.Faker("text", max_nb_chars=255)
|
|
135
|
+
year = factory.Faker("year")
|
|
136
|
+
creator = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
137
|
+
created = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
138
|
+
changer = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
139
|
+
changed = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
140
|
+
review_task = None
|
|
141
|
+
occured = factory.Faker("date")
|
|
142
|
+
type = factory.SubFactory("wbcompliance.factories.ComplianceTypeFactory")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class ReviewComplianceTaskFactory(ParentReviewComplianceTaskFactory):
|
|
146
|
+
class Meta:
|
|
147
|
+
model = ReviewComplianceTask
|
|
148
|
+
|
|
149
|
+
review_task = factory.SubFactory(ParentReviewComplianceTaskFactory)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class ComplianceTaskFactory(factory.django.DjangoModelFactory):
|
|
153
|
+
class Meta:
|
|
154
|
+
model = ComplianceTask
|
|
155
|
+
|
|
156
|
+
title = factory.Faker("text", max_nb_chars=32)
|
|
157
|
+
description = factory.Faker("text", max_nb_chars=255)
|
|
158
|
+
group = factory.SubFactory(ComplianceTaskGroupFactory)
|
|
159
|
+
type = factory.SubFactory(ComplianceTypeFactory)
|
|
160
|
+
risk_level = "LOW"
|
|
161
|
+
remarks = factory.Faker("text", max_nb_chars=255)
|
|
162
|
+
|
|
163
|
+
@factory.post_generation
|
|
164
|
+
def review(self, create, extracted, **kwargs):
|
|
165
|
+
if not create:
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
if extracted:
|
|
169
|
+
for item in extracted:
|
|
170
|
+
self.review.add(item)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class ComplianceTaskReviewFactory(ComplianceTaskFactory):
|
|
174
|
+
@factory.post_generation
|
|
175
|
+
def review(self, create, extracted, **kwargs):
|
|
176
|
+
review = ReviewComplianceTaskFactory()
|
|
177
|
+
self.review.add(review)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class ComplianceTaskReviewNoGroupFactory(ComplianceTaskReviewFactory):
|
|
181
|
+
group = None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class ComplianceTaskInstanceFactory(factory.django.DjangoModelFactory):
|
|
185
|
+
class Meta:
|
|
186
|
+
model = ComplianceTaskInstance
|
|
187
|
+
|
|
188
|
+
text = factory.Faker("text", max_nb_chars=255)
|
|
189
|
+
summary_text = factory.Faker("text", max_nb_chars=255)
|
|
190
|
+
task = factory.SubFactory(ComplianceTaskFactory)
|
|
191
|
+
|
|
192
|
+
@factory.post_generation
|
|
193
|
+
def review(self, create, extracted, **kwargs):
|
|
194
|
+
if not create:
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
if extracted:
|
|
198
|
+
for item in extracted:
|
|
199
|
+
self.review.add(item)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class ComplianceTaskInstanceReviewFactory(ComplianceTaskInstanceFactory):
|
|
203
|
+
@factory.post_generation
|
|
204
|
+
def review(self, create, extracted, **kwargs):
|
|
205
|
+
review = ReviewComplianceTaskFactory()
|
|
206
|
+
self.review.add(review)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class ComplianceTaskInstanceReviewNoGroupFactory(ComplianceTaskInstanceFactory):
|
|
210
|
+
@factory.post_generation
|
|
211
|
+
def review(self, create, extracted, **kwargs):
|
|
212
|
+
self.task.group = None
|
|
213
|
+
review = ReviewComplianceTaskFactory()
|
|
214
|
+
self.review.add(review)
|
|
215
|
+
self.task.save()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class ComplianceActionFactory(factory.django.DjangoModelFactory):
|
|
219
|
+
class Meta:
|
|
220
|
+
model = ComplianceAction
|
|
221
|
+
|
|
222
|
+
title = factory.Faker("text", max_nb_chars=32)
|
|
223
|
+
description = factory.Faker("text", max_nb_chars=255)
|
|
224
|
+
summary_description = factory.Faker("text", max_nb_chars=255)
|
|
225
|
+
deadline = factory.Faker("date_between", start_date="+2d", end_date="+3d")
|
|
226
|
+
type = factory.SubFactory(ComplianceTypeFactory)
|
|
227
|
+
creator = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
228
|
+
created = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
229
|
+
changer = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class ComplianceEventFactory(factory.django.DjangoModelFactory):
|
|
233
|
+
class Meta:
|
|
234
|
+
model = ComplianceEvent
|
|
235
|
+
|
|
236
|
+
title = factory.Faker("text", max_nb_chars=32)
|
|
237
|
+
exec_summary = factory.Faker("text", max_nb_chars=255)
|
|
238
|
+
exec_summary_board = factory.Faker("text", max_nb_chars=255)
|
|
239
|
+
description = factory.Faker("text", max_nb_chars=255)
|
|
240
|
+
actions_taken = factory.Faker("text", max_nb_chars=255)
|
|
241
|
+
consequences = factory.Faker("text", max_nb_chars=255)
|
|
242
|
+
future_suggestions = factory.Faker("text", max_nb_chars=255)
|
|
243
|
+
type = factory.SubFactory(ComplianceTypeFactory)
|
|
244
|
+
creator = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|
|
245
|
+
created = factory.Faker("date_time", tzinfo=pytz.utc)
|
|
246
|
+
changer = factory.SubFactory("wbcore.contrib.authentication.factories.AuthenticatedPersonFactory")
|