Skip to content

Commit b640b84

Browse files
committed
feat: update existing risks and assessments with info from excel import.
1 parent fb8f572 commit b640b84

File tree

2 files changed

+52
-21
lines changed

2 files changed

+52
-21
lines changed

src/riskmatrix/scripts/seantis_import_risk_excel.py

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""
77
import argparse
88
import sys
9+
import traceback
910
from datetime import datetime
1011
from typing import TYPE_CHECKING
1112
from typing import Iterator
@@ -23,11 +24,11 @@
2324
from pyramid.paster import get_appsettings
2425
from sqlalchemy import select
2526

27+
from riskmatrix.models import Asset
2628
from riskmatrix.models import Organization
2729
from riskmatrix.models import Risk
2830
from riskmatrix.models import RiskAssessment
2931
from riskmatrix.models import RiskCatalog
30-
from riskmatrix.models.asset import Asset
3132
from riskmatrix.orm import Base
3233
from riskmatrix.orm import get_engine
3334
from riskmatrix.scripts.util import select_existing_organization
@@ -72,9 +73,7 @@ def get_or_create_asset(
7273
Asset.name == asset_name
7374
)
7475

75-
asset = session.scalars(q).one_or_none()
76-
77-
if asset:
76+
if asset := session.scalars(q).one_or_none():
7877
return asset
7978

8079
asset = Asset(asset_name, organization)
@@ -83,6 +82,44 @@ def get_or_create_asset(
8382
return asset
8483

8584

85+
def get_or_create_risk(
86+
risk_name: str,
87+
catalog: RiskCatalog,
88+
session: 'Session'
89+
) -> Risk:
90+
91+
q = select(Risk).where(
92+
Risk.organization_id == catalog.organization.id,
93+
Risk.name == risk_name
94+
)
95+
96+
if risk := session.scalars(q).one_or_none():
97+
return risk
98+
99+
risk = Risk(risk_name, catalog)
100+
session.add(risk)
101+
return risk
102+
103+
104+
def get_or_create_risk_assessment(
105+
risk: Risk,
106+
asset: Asset,
107+
session: 'Session'
108+
) -> RiskAssessment:
109+
110+
q = select(RiskAssessment).where(
111+
RiskAssessment.risk_id == risk.id,
112+
RiskAssessment.asset_id == asset.id,
113+
)
114+
115+
if assessment := session.scalars(q).one_or_none():
116+
return assessment
117+
118+
assessment = RiskAssessment(risk=risk, asset=asset)
119+
session.add(assessment)
120+
return assessment
121+
122+
86123
def populate_catalog(
87124
catalog: RiskCatalog,
88125
risks: 'Iterator[RiskDetails]',
@@ -94,17 +131,15 @@ def populate_catalog(
94131
risk_details['asset_name'], catalog.organization, session
95132
)
96133

97-
risk = Risk(
98-
name=risk_details['name'],
99-
catalog=catalog,
100-
description=risk_details['desc'],
101-
category=risk_details['category']
134+
risk = get_or_create_risk(
135+
risk_details['name'], catalog, session
102136
)
137+
risk.category = risk_details['category']
138+
risk.description = risk_details['desc']
103139

104-
assessment = RiskAssessment(risk=risk, asset=asset)
140+
assessment = get_or_create_risk_assessment(risk, asset, session)
105141
assessment.likelihood = risk_details['likelihood']
106142
assessment.impact = risk_details['impact']
107-
session.add(assessment)
108143

109144

110145
def risks_from_excel(
@@ -126,7 +161,7 @@ def risks_from_excel(
126161
# Anyway, actual riks rows will start after row #2.
127162
start_after_row = 2
128163

129-
iterator = sheet.iter_rows( # type: ignore[union-attr,misc]
164+
iterator = sheet.iter_rows(
130165
values_only=True,
131166
min_row=start_after_row
132167
)
@@ -194,14 +229,10 @@ def main(argv: list[str] = sys.argv) -> None:
194229
dbsession
195230
)
196231
except sqlalchemy.exc.IntegrityError:
197-
# TODO: Risks and assets (and therefore also assessments) are
198-
# unique per organization, not catalog. Adding a risk from the
199-
# excel that is already present in this organization will fail.
200-
print(
201-
'Organization already contains some risks from the Excel. '
202-
'Abort!'
203-
)
232+
print('Failed to import excel, aborting.')
233+
print(traceback.format_exc())
204234
dbsession.rollback()
235+
sys.exit(1)
205236
else:
206237
print(
207238
f'Successfully populated risk catalog "{catalog.name}" '

test_requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ types-setuptools==69.0.0.0
3232
types-translationstring==1.4.0.1
3333
types-WebOb==1.8.0.5
3434
types-WTForms==3.1.0.2
35-
types-openpyxl==3.1.0.20240408
35+
types-openpyxl==3.1.0.20240428
3636
virtualenv==20.24.4
37-
WebTest==3.0.0
37+
WebTest==3.0.0

0 commit comments

Comments
 (0)