Skip to content

Commit

Permalink
feat: add gravity to operational scenario view
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohamed-Hacene committed Dec 13, 2024
1 parent a627d67 commit 13c5146
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 41 deletions.
29 changes: 29 additions & 0 deletions backend/ebios_rm/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ def get_pertinence(self):
PERTINENCE_MATRIX[self.motivation - 1][self.resources - 1]
).label

@property
def gravity(self):
gravity = -1
for feared_event in self.feared_events.all():
if feared_event.gravity > gravity:
gravity = feared_event.gravity
return gravity


class Stakeholder(AbstractBaseModel, FolderMixin):
class Category(models.TextChoices):
Expand Down Expand Up @@ -398,6 +406,9 @@ def save(self, *args, **kwargs):
self.folder = self.ebios_rm_study.folder
super().save(*args, **kwargs)

def get_gravity(self):
return self.ro_to_couple.gravity


class OperationalScenario(AbstractBaseModel, FolderMixin):
ebios_rm_study = models.ForeignKey(
Expand Down Expand Up @@ -455,3 +466,21 @@ def get_likelihood_display(self):
**risk_matrix["probability"][self.likelihood],
"value": self.likelihood,
}

def get_gravity_display(self):
gravity = -1
for attack_path in self.attack_paths.all():
if attack_path.get_gravity() > gravity:
gravity = attack_path.get_gravity()
if gravity < 0:
return {
"abbreviation": "--",
"name": "--",
"description": "not rated",
"value": -1,
}
risk_matrix = self.parsed_matrix
return {
**risk_matrix["impact"][gravity],
"value": gravity,
}
1 change: 1 addition & 0 deletions backend/ebios_rm/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class OperationalScenarioReadSerializer(BaseModelSerializer):
attack_paths = FieldsRelatedField(many=True)
threats = FieldsRelatedField(many=True)
likelihood = serializers.JSONField(source="get_likelihood_display")
gravity = serializers.JSONField(source="get_gravity_display")

class Meta:
model = OperationalScenario
Expand Down
3 changes: 2 additions & 1 deletion frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1000,5 +1000,6 @@
"likely": "Likely",
"unlikely": "Unlikely",
"veryLikely": "Very likely",
"certain": "Certain"
"certain": "Certain",
"minor": "Minor"
}
2 changes: 1 addition & 1 deletion frontend/src/lib/components/Forms/ModelForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
{:else if URLModel === 'attack-paths'}
<AttackPathForm {form} {model} {cacheLocks} {formDataCache} {initialData} />
{:else if URLModel === 'operational-scenarios'}
<OperationalScenarioForm {form} {model} {cacheLocks} {formDataCache} {initialData} {context}/>
<OperationalScenarioForm {form} {model} {cacheLocks} {formDataCache} {initialData} {context} />
{/if}
<div class="flex flex-row justify-between space-x-4">
{#if closeModal}
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/lib/utils/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,13 @@ export const URL_MODEL_MAP: ModelMap = {
foreignKeyFields: [
{ field: 'ebios_rm_study', urlModel: 'ebios-rm' },
{ field: 'threats', urlModel: 'threats' },
{ field: 'attack_paths', urlModel: 'attack-paths', endpointUrl: 'ebios-rm/attack-paths', urlParams: 'ebios_rm_study=', detail: true },
{
field: 'attack_paths',
urlModel: 'attack-paths',
endpointUrl: 'ebios-rm/attack-paths',
urlParams: 'ebios_rm_study=',
detail: true
}
],
selectFields: [{ field: 'likelihood', valueType: 'number', detail: true }]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ export const load: LayoutServerLoad = async (event) => {
let url = keyModel.endpointUrl
? `${BASE_API_URL}/${keyModel.endpointUrl}/${queryParams}`
: `${BASE_API_URL}/${keyModel.urlModel}/${queryParams}`;
if (['assets', 'attack-paths'].includes(keyModel.urlModel) && ['feared-events', 'operational-scenarios'].includes(event.params.model)) {
if (
['assets', 'attack-paths'].includes(keyModel.urlModel) &&
['feared-events', 'operational-scenarios'].includes(event.params.model)
) {
url = `${BASE_API_URL}/${keyModel.endpointUrl || keyModel.urlModel}/${queryParams}${object.ebios_rm_study}`;
}
const response = await event.fetch(url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
selectOptions={data.selectOptions}
foreignKeys={data.foreignKeys}
model={data.model}
customNameDescription={customNameDescription}
{customNameDescription}
context="edit"
/>
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ export const load: PageServerLoad = async ({ params, fetch }) => {

for (const keyField of foreignKeyFields) {
const keyModel = getModelInfo(keyField.urlModel);
const queryParams = keyField.urlParams ? `?${keyField.urlParams}${keyField.detail ? params.id : ''}` : '';
const queryParams = keyField.urlParams
? `?${keyField.urlParams}${keyField.detail ? params.id : ''}`
: '';
const url = keyModel.endpointUrl
? `${BASE_API_URL}/${keyModel.endpointUrl}/${queryParams}`
: `${BASE_API_URL}/${keyModel.urlModel}/${queryParams}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
ref: CreateModal,
props: {
form: data.createForm,
model: data.model
model: data.model,
customNameDescription: true
}
};
let modal: ModalSettings = {
Expand Down Expand Up @@ -64,7 +65,12 @@
});
</script>

<ModelTable source={data.table} deleteForm={data.deleteForm} {URLModel} detailQueryParameter={`activity=${activeActivity}`}>
<ModelTable
source={data.table}
deleteForm={data.deleteForm}
{URLModel}
detailQueryParameter={`activity=${activeActivity}`}
>
<div slot="addButton">
<span class="inline-flex overflow-hidden rounded-md border bg-white shadow-sm">
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ export const load: PageServerLoad = async (event) => {
};

return { data, table };
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@
}
});
const likelihoodChoices = [
{ label: m.unlikely(), value: 0 },
{ label: m.likely(), value: 1 },
{ label: m.veryLikely(), value: 2 },
{ label: m.certain(), value: 3 },
];
const likelihoodChoices = [
{ label: m.unlikely(), value: 0 },
{ label: m.likely(), value: 1 },
{ label: m.veryLikely(), value: 2 },
{ label: m.certain(), value: 3 }
];
const gravityChoices = [
{ label: m.minor(), value: 0 },
{ label: m.significant(), value: 1 },
{ label: m.important(), value: 2 },
{ label: m.critical(), value: 3 }
];
</script>

<div class="card p-4 bg-white shadow-lg">
Expand Down Expand Up @@ -55,12 +61,12 @@
<i class="fa-solid fa-pen-to-square mr-2" data-testid="edit-button" />
{m.edit()}
</a>
{#if operationalScenario.description}
{#if operationalScenario.description}
<p class="text-gray-600">{operationalScenario.description}</p>
{:else}
<p class="text-gray-600">{m.noDescription()}</p>
{/if}
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<h3 class="font-semibold text-lg text-gray-700 flex items-center space-x-2">
<i class="fa-solid fa-table text-gray-500 opacity-75"></i>
<span>{m.attackPaths()}</span>
Expand All @@ -73,7 +79,7 @@
URLModel="attack-paths"
></ModelTable>
</div>
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<h3 class="font-semibold text-lg text-gray-700 flex items-center space-x-2">
<i class="fa-solid fa-biohazard text-red-500"></i>
<span>{m.threats()}</span>
Expand Down Expand Up @@ -102,11 +108,9 @@
: 'text-gray-500'}">{m.activityTwo()}</span
>
<h1
class="font-bold text-xl {activeActivity === 'two'
? 'text-primary-500'
: 'text-gray-500'}"
class="font-bold text-xl {activeActivity === 'two' ? 'text-primary-500' : 'text-gray-500'}"
>
{m.ebiosWs4_2()}
{m.ebiosWs4_2()}
</h1>
<p>
{#if operationalScenario.is_selected}
Expand All @@ -115,27 +119,58 @@
<span class="badge bg-red-200 text-red-700">{m.notSelected()}</span>
{/if}
</p>
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<h3 class="font-semibold text-lg text-gray-700 flex items-center space-x-2">
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<h3 class="font-semibold text-lg text-gray-700 flex items-center space-x-2">
<i class="fa-solid fa-dice text-black opacity-75"></i>
<span>{m.likelihood()}</span>
</h3>
<div class="grid grid-cols-4 gap-2 p-2">
{#each likelihoodChoices as choice}
{#if operationalScenario.likelihood.value === choice.value}
<div style="background-color: {operationalScenario.likelihood.hexcolor}" class="flex flex-col items-center justify-center border rounded-md p-4 font-semibold">
<span>{choice.label}</span>
<span>({choice.value})</span>
</div>
{:else}
<div class="flex flex-col items-center justify-center border rounded-md bg-gray-200 p-4 text-gray-500">
<span>{choice.label}</span>
<span>({choice.value})</span>
</div>
{/if}
{/each}
</div>
</div>
<div class="grid grid-cols-4 gap-2 p-2">
{#each likelihoodChoices as choice}
{#if operationalScenario.likelihood.value === choice.value}
<div
style="background-color: {operationalScenario.likelihood.hexcolor}"
class="flex flex-col items-center justify-center border rounded-md p-4 font-semibold"
>
<span>{choice.label}</span>
<span>({choice.value})</span>
</div>
{:else}
<div
class="flex flex-col items-center justify-center border rounded-md bg-gray-200 p-4 text-gray-500"
>
<span>{choice.label}</span>
<span>({choice.value})</span>
</div>
{/if}
{/each}
</div>
</div>
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<h3 class="font-semibold text-lg text-gray-700 flex items-center space-x-2">
<i class="fa-solid fa-bomb text-black opacity-75"></i>
<span>{m.gravity()}</span>
</h3>
<div class="grid grid-cols-4 gap-2 p-2">
{#each gravityChoices as choice}
{#if operationalScenario.gravity.value === choice.value}
<div
style="background-color: {operationalScenario.gravity.hexcolor}"
class="flex flex-col items-center justify-center border rounded-md p-4 font-semibold"
>
<span>{choice.label}</span>
<span>({choice.value})</span>
</div>
{:else}
<div
class="flex flex-col items-center justify-center border rounded-md bg-gray-200 p-4 text-gray-500"
>
<span>{choice.label}</span>
<span>({choice.value})</span>
</div>
{/if}
{/each}
</div>
</div>
<div class="w-full p-4 bg-gray-50 border rounded-md shadow-sm">
<h3 class="font-semibold text-lg text-gray-700 flex items-center space-x-2">
<i class="fa-solid fa-eye text-gray-500 opacity-75"></i>
Expand All @@ -149,4 +184,4 @@
</div>
</div>
</div>
</div>
</div>

0 comments on commit 13c5146

Please sign in to comment.