Resolve "Sve tabele i grafove u projektu staviti da budu 5 sa 5" #70

Merged
amirsabani303 merged 2 commits from 18-sve-tabele-i-grafove-u-projektu-staviti-da-budu-5-sa-5 into master 2025-05-12 23:50:24 +02:00
5 changed files with 68 additions and 77 deletions

View File

@@ -4,56 +4,48 @@ from backend.core.utils import calculate_aggregate_likelihood, calculate_aggrega
def risk_matrix_table():
likelihood_labels = [
"Certain (90-100%)",
"Almost Certain (80-89%)",
"Very Probable (70-79%)",
"Probable (60-69%)",
"Highly Likely (50-59%)",
"Likely (40-49%)",
"Occasional (30-39%)",
"Possible (20-29%)",
"Unlikely (10-19%)",
"Rare (0-9%)"
"Almost Certain (90-100%) (5)",
"Probable (51-89%) (4)",
"Possible (25-50%) (3)",
"Unlikely (11-24%) (2)",
"Rare (0-10%) (1)"
]
impact_labels = [
"Insignificant",
"Minor",
"Moderate",
"Major",
"Severe",
"Catastrophic",
"Critical",
"Extreme",
"Disastrous",
"Unrecoverable"
"Insignificant (1)",
"Significant (2)",
"Severe (3)",
"Material (4)",
"Major (5)"
]
color_mapping = {
"Very Low": "green",
"Low": "lightgreen",
"Very Low": "lightgreen",
"Low": "green",
"Medium": "yellow",
"High": "orange",
"Critical": "red"
}
table_matrix_risk = [["Impact ↓ / Likelihood →"] + impact_labels]
def get_label(score):
if score <= 2:
return "Very Low"
elif score <= 4:
return "Low"
elif score <= 10:
return "Medium"
elif score <= 16:
return "High"
else:
return "Critical"
for likelihood_index, likelihood_label in enumerate(likelihood_labels, start=1):
reversed_index = 11 - likelihood_index
row = [likelihood_label]
for impact_index in range(1, 11):
score = reversed_index * impact_index
if score <= 20:
label = "Very Low"
elif score <= 40:
label = "Low"
elif score <= 60:
label = "Medium"
elif score <= 80:
label = "High"
else:
label = "Critical"
table_matrix_risk = [["Likelihood ↓ / Impact →"] + impact_labels]
for likelihood in range(5, 0, -1):
row = [likelihood_labels[5 - likelihood]]
for impact in range(1, 6):
score = likelihood * impact
label = get_label(score)
color_class = color_mapping[label]
row.append((score, label, color_class))
table_matrix_risk.append(row)
@@ -82,7 +74,7 @@ def get_risk_table(document):
.values('control', 'control__name', 'weight', 'likelihood')
.distinct()
)
max_weight = 10*10
max_weight = 10*5
total_weight = calculate_aggregate_weight(controls)
total_likelihood = calculate_aggregate_likelihood(controls)
impact, likelihood = map_weight_to_impact_likelihood(total_weight, total_likelihood, max_weight)

View File

@@ -71,7 +71,7 @@ class UtilsTests(TestCase):
mock_openai.return_value = mock_client
mock_response = MagicMock()
control_lines = [f"{i} : 8 : 5" for i in range(1, 11)]
control_lines = [f"{i} : 4 : 3" for i in range(1, 11)]
mock_response.choices[0].message.content = "\n".join(control_lines)
mock_client.chat.completions.create.return_value = mock_response
@@ -100,7 +100,7 @@ class UtilsTests(TestCase):
self.assertEqual(calculate_aggregate_likelihood(controls), 6)
def test_map_weight_to_impact_likelihood(self):
impact, likelihood = map_weight_to_impact_likelihood(50, 30, 100)
impact, likelihood = map_weight_to_impact_likelihood(50, 30, 50)
self.assertAlmostEqual(impact, 5.0)
self.assertAlmostEqual(likelihood, 3.0)
@@ -123,7 +123,7 @@ class UtilsTests(TestCase):
def test_generate_risk_graph(self):
risks_with_controls = [
{'risk': {'id': 1}, 'impact': 5.0, 'likelihood': 3.0},
{'risk': {'id': 2}, 'impact': 7.0, 'likelihood': 4.0}
{'risk': {'id': 2}, 'impact': 4.0, 'likelihood': 4.0}
]
graph_data = generate_risk_graph(risks_with_controls)

View File

@@ -90,14 +90,14 @@ def get_controls_for_risk(risk, organization):
prompt = f"""
You are an expert in cybersecurity risk management. Given the risk "{risk.risk_name}" and its associated organization details "{organization_details}",
your task is to select **exactly 10 unique controls** from the provided list that best mitigate this risk. Each control should be assigned:
- A weight between **1 and 10** (1 = low impact, 10 = high impact).
- A likelihood score between **1 and 10** (1 = rare occurrence, 10 = highly likely).
- A weight between **1 and 5** (1 = low impact, 5 = high impact).
- A likelihood score between **1 and 5** (1 = rare occurrence, 5 = highly likely).
### Rules:
1. **Each control ID must be unique** (no duplicates).
2. **Only return control IDs, weights, and likelihood scores** in the exact format below.
3. **Weights must be between 1 and 10** (1 = low impact, 10 = high impact).
4. **Likelihood scores must be between 1 and 10** (1 = rare occurrence, 10 = highly likely).
3. **Weights must be between 1 and 5** (1 = low impact, 5 = high impact).
4. **Likelihood scores must be between 1 and 5** (1 = rare occurrence, 5 = highly likely).
5. **Do NOT add explanations, descriptions, or extra text.**
6. **Ensure that control IDs are randomly distributed and diverse across different categories.**
### Available Controls:
@@ -108,8 +108,8 @@ def get_controls_for_risk(risk, organization):
<control_id> : <weight> : <likelihood>
### Example Correct Response (NO DUPLICATES):
12 : 8 : 90
45 : 7 : 60
12 : 5 : 2
45 : 4 : 1
⚠️ **If you provide duplicate control IDs, your response will be rejected. Ensure all control IDs are unique.**
⚠️ **Follow the response format exactly. Any deviation will be considered invalid.**
@@ -138,7 +138,7 @@ def get_controls_for_risk(risk, organization):
weight = int(weight_str)
likelihood = int(likelihood_str)
if control_id in valid_control_ids and 1 <= weight <= 10 and 1 <= likelihood <= 10 and control_id not in control_ids_seen:
if control_id in valid_control_ids and 1 <= weight <= 5 and 1 <= likelihood <= 5 and control_id not in control_ids_seen:
selected_controls.append((control_id, weight, likelihood))
control_ids_seen.add(control_id)
except ValueError:
@@ -155,14 +155,14 @@ def get_controls_for_risk(risk, organization):
retry_prompt = f"""
You are an expert in cybersecurity risk management. Given the risk "{risk.risk_name}" and the organization's details "{organization_details}",
your task is to select **exactly {missing_count} unique controls** from the provided list that best mitigate this risk. Each control should be assigned:
- A **weight** between **1 and 10** based on its effectiveness in reducing the risk.
- A likelihood score between **1 and 10** (1 = rare occurrence, 10 = highly likely).
- A **weight** between **1 and 5** based on its effectiveness in reducing the risk.
- A likelihood score between **1 and 5** (1 = rare occurrence, 5 = highly likely).
### Rules:
1. **Each control ID must be unique** (no duplicates).
2. **Only return control IDs, weights, and likelihood scores** in the exact format below.
3. **Weights must be between 1 and 10** (1 = low impact, 10 = high impact).
4. **Likelihood scores must be between 1 and 10** (1 = rare occurrence, 10 = highly likely).
3. **Weights must be between 1 and 5** (1 = low impact, 5 = high impact).
4. **Likelihood scores must be between 1 and 5** (1 = rare occurrence, 5 = highly likely).
5. **Do NOT add explanations, descriptions, or extra text.**
6. **Ensure that control IDs are diverse and well-distributed across different categories.**
@@ -174,8 +174,8 @@ def get_controls_for_risk(risk, organization):
<control_id> : <weight> : <likelihood>
### Example Correct Response (NO DUPLICATES):
12 : 8 : 85
45 : 7 : 60
12 : 4 : 5
45 : 5 : 3
⚠️ **If you provide duplicate control IDs, your response will be rejected. Ensure all control IDs are unique.**
⚠️ **Follow the response format exactly. Any deviation will be considered invalid.**
@@ -201,7 +201,7 @@ def get_controls_for_risk(risk, organization):
weight = int(weight_str)
likelihood = int(likelihood_str)
if control_id in valid_control_ids and 1 <= weight <= 10 and 1 <= likelihood <= 10 and control_id not in control_ids_seen:
if control_id in valid_control_ids and 1 <= weight <= 5 and 1 <= likelihood <= 5 and control_id not in control_ids_seen:
selected_controls.append((control_id, weight, likelihood))
control_ids_seen.add(control_id)
except ValueError:
@@ -243,10 +243,8 @@ def calculate_aggregate_likelihood(controls):
return total_likelihood
def map_weight_to_impact_likelihood(total_weight, total_likelihood, max_weight):
normalized_weight = total_weight / max_weight
impact = min(10.0, max(1.0, normalized_weight * 10.0))
likelihood = min(10.0, max(1.0, total_likelihood / 10.0))
impact = min(5.0, max(1.0, total_weight / 10.0))
likelihood = min(5.0, max(1.0, total_likelihood / 10.0))
return impact, likelihood
@@ -256,12 +254,12 @@ def generate_risk_graph(risks_with_controls):
likelihoods = [risk['likelihood'] for risk in risks_with_controls]
risk_ids = [risk['risk']['id'] for risk in risks_with_controls]
bg_img_path = find('img/graph_matrix (3).png')
bg_img_path = find('img/graph_matrix.png')
bg_img = mpimg.imread(bg_img_path)
fig, ax = plt.subplots(figsize=(10, 8))
ax.imshow(bg_img, extent=[0, 11.2, 0, 11.2], aspect='auto')
ax.imshow(bg_img, extent=[0.0, 5.4, 0.0, 5.4], aspect='auto')
scatter = ax.scatter(
likelihoods, impacts,

View File

@@ -38,6 +38,7 @@ DEBUG = config('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[], cast=Csv())
SITE_DOMAIN = "http://64.226.105.114"
#SITE_DOMAIN = "http://127.0.0.1:8000"
# Application definition

View File

@@ -148,26 +148,26 @@
Impact is aslo defined with the following table:
headers: ["Level", "Financial Cost", "Reputational Impact", "Management Effort", "Operational Resources", "RPO", "RTO"]
rows:
- ["Insignificant (1-2)", "< 0.05% Material", "Normal", "Normal", "Normal", "16 hr", "64 hr"]
- ["Significant (3-4)", "> 0.5% Material", "Minor", "Minor", "Minor", "8 hr", "32 hr"]
- ["Severe (5-6)", "> 10% Material", "Moderate", "Moderate", "Moderate", "4 hr", "16 hr"]
- ["Material (7-8)", "> 50% Material", "Critical", "Critical", "Critical", "2 hr", "8 hr"]
- ["Major (9-10)", "> Material", "Precarious", "Precarious", "Precarious", "1 hr", "4 hr"]
- ["Insignificant (1)", "< 0.05% Material", "Normal", "Normal", "Normal", "16 hr", "64 hr"]
- ["Significant (2)", "> 0.5% Material", "Minor", "Minor", "Minor", "8 hr", "32 hr"]
- ["Severe (3)", "> 10% Material", "Moderate", "Moderate", "Moderate", "4 hr", "16 hr"]
- ["Material (4)", "> 50% Material", "Critical", "Critical", "Critical", "2 hr", "8 hr"]
- ["Major (5)", "> Material", "Precarious", "Precarious", "Precarious", "1 hr", "4 hr"]
- segment_type: "list_stack_sights"
content:
- description: |
For determining likelihood, we use StackSight's commonly referenced scale:
- level: 1-2
description: "0-3% chance of happening in a year"
- level: 3-4
description: "4-10% chance of happening in a year"
- level: 5-6
description: "11-50% chance of happening in a year"
- level: 7-8
description: "51-90% chance of happening in a year"
- level: 9-10
description: "91-100% chance of happening in a year"
- level: 1
description: 1. "0-3% chance of happening in a year"
- level: 2
description: 2. "4-10% chance of happening in a year"
- level: 3
description: 3. "11-50% chance of happening in a year"
- level: 4
description: 4. "51-90% chance of happening in a year"
- level: 5
description: 5. "91-100% chance of happening in a year"
- segment_type: "likelihood_table"
content: