diff --git a/backend/app_tests/api/test_api_requirement_assessments.py b/backend/app_tests/api/test_api_requirement_assessments.py index ef49c83e1..12dad4661 100644 --- a/backend/app_tests/api/test_api_requirement_assessments.py +++ b/backend/app_tests/api/test_api_requirement_assessments.py @@ -124,7 +124,48 @@ def test_get_requirement_assessments(self, test): "id": str(compliance_assessment.id), "str": compliance_assessment.name, }, - "requirement": str(RequirementNode.objects.all()[0].id), + "requirement": { + "str": str(RequirementNode.objects.all()[0]), + "id": str(RequirementNode.objects.all()[0].id), + "urn": RequirementNode.objects.all()[0].urn, + "annotation": RequirementNode.objects.all()[0].annotation, + "name": RequirementNode.objects.all()[0].name, + "description": RequirementNode.objects.all()[0].description, + "typical_evidence": RequirementNode.objects.all()[ + 0 + ].typical_evidence, + "ref_id": RequirementNode.objects.all()[0].ref_id, + "associated_reference_controls": RequirementNode.objects.all()[ + 0 + ].associated_reference_controls, + "associated_threats": RequirementNode.objects.all()[ + 0 + ].associated_threats, + "parent_requirement": { + "str": RequirementNode.objects.all()[0].parent_requirement.get( + "str" + ), + "urn": RequirementNode.objects.all()[0].parent_requirement.get( + "urn" + ), + "id": str( + RequirementNode.objects.all()[0].parent_requirement.get( + "id" + ) + ), + "ref_id": RequirementNode.objects.all()[ + 0 + ].parent_requirement.get("ref_id"), + "name": RequirementNode.objects.all()[0].parent_requirement.get( + "name" + ), + "description": RequirementNode.objects.all()[ + 0 + ].parent_requirement.get("description"), + } + if RequirementNode.objects.all()[0].parent_requirement + else None, + }, }, base_count=-1, user_group=test.user_group, @@ -210,7 +251,48 @@ def test_update_requirement_assessments(self, test): "id": str(compliance_assessment.id), "str": compliance_assessment.name, }, - "requirement": str(RequirementNode.objects.all()[0].id), + "requirement": { + "str": str(RequirementNode.objects.all()[0]), + "id": str(RequirementNode.objects.all()[0].id), + "urn": RequirementNode.objects.all()[0].urn, + "annotation": RequirementNode.objects.all()[0].annotation, + "name": RequirementNode.objects.all()[0].name, + "description": RequirementNode.objects.all()[0].description, + "typical_evidence": RequirementNode.objects.all()[ + 0 + ].typical_evidence, + "ref_id": RequirementNode.objects.all()[0].ref_id, + "associated_reference_controls": RequirementNode.objects.all()[ + 0 + ].associated_reference_controls, + "associated_threats": RequirementNode.objects.all()[ + 0 + ].associated_threats, + "parent_requirement": { + "str": RequirementNode.objects.all()[0].parent_requirement.get( + "str" + ), + "urn": RequirementNode.objects.all()[0].parent_requirement.get( + "urn" + ), + "id": str( + RequirementNode.objects.all()[0].parent_requirement.get( + "id" + ) + ), + "ref_id": RequirementNode.objects.all()[ + 0 + ].parent_requirement.get("ref_id"), + "name": RequirementNode.objects.all()[0].parent_requirement.get( + "name" + ), + "description": RequirementNode.objects.all()[ + 0 + ].parent_requirement.get("description"), + } + if RequirementNode.objects.all()[0].parent_requirement + else None, + }, }, user_group=test.user_group, ) diff --git a/backend/core/management/commands/status.py b/backend/core/management/commands/status.py index bbee0ed8e..f8d345a8b 100644 --- a/backend/core/management/commands/status.py +++ b/backend/core/management/commands/status.py @@ -22,8 +22,9 @@ def handle(self, *args, **kwargs): nb_risk_assessments = RiskAssessment.objects.all().count() nb_risk_scenarios = RiskScenario.objects.all().count() nb_risk_acceptances = RiskAcceptance.objects.all().count() - nb_seats_available = getattr(settings, "LICENSE_SEATS", 0) - nb_expiry_date = getattr(settings, "LICENSE_EXPIRATION", "") + nb_seats = getattr(settings, "LICENSE_SEATS", 0) + nb_editors = len(User.get_editors()) + expiration = getattr(settings, "LICENSE_EXPIRATION", "") created_at = Folder.get_root_folder().created_at last_login = max( @@ -41,5 +42,5 @@ def handle(self, *args, **kwargs): + f"threats={nb_threats} functions={nb_functions} measures={nb_measures} " + f"evidences={nb_evidences} compliance={nb_compliance_assessments} risk={nb_risk_assessments} " + f"scenarios={nb_risk_scenarios} acceptances={nb_risk_acceptances} " - + f"number_of_seats={nb_seats_available} expiry_date={nb_expiry_date}" + + f"seats={nb_seats} editors={nb_editors} expiration={expiration}" ) diff --git a/backend/core/models.py b/backend/core/models.py index 93fc5bd45..fa0d57fb9 100644 --- a/backend/core/models.py +++ b/backend/core/models.py @@ -1049,6 +1049,40 @@ class RequirementNode(ReferentialObjectMixin, I18nObjectMixin): ) question = models.JSONField(blank=True, null=True, verbose_name=_("Question")) + @property + def associated_reference_controls(self): + _reference_controls = self.reference_controls.all() + reference_controls = [] + for control in _reference_controls: + reference_controls.append( + {"str": control.display_long, "urn": control.urn, "id": control.id} + ) + return reference_controls + + @property + def associated_threats(self): + _threats = self.threats.all() + threats = [] + for control in _threats: + threats.append( + {"str": control.display_long, "urn": control.urn, "id": control.id} + ) + return threats + + @property + def parent_requirement(self): + parent_requirement = RequirementNode.objects.filter(urn=self.parent_urn).first() + if not parent_requirement: + return None + return { + "str": parent_requirement.display_long, + "urn": parent_requirement.urn, + "id": parent_requirement.id, + "ref_id": parent_requirement.ref_id, + "name": parent_requirement.name, + "description": parent_requirement.description, + } + class Meta: verbose_name = _("RequirementNode") verbose_name_plural = _("RequirementNodes") diff --git a/backend/core/serializers.py b/backend/core/serializers.py index e42d8c9e2..1b2661a14 100644 --- a/backend/core/serializers.py +++ b/backend/core/serializers.py @@ -612,6 +612,20 @@ class RequirementAssessmentReadSerializer(BaseModelSerializer): compliance_assessment = FieldsRelatedField() folder = FieldsRelatedField() assessable = serializers.BooleanField(source="requirement.assessable") + requirement = FieldsRelatedField( + [ + "id", + "urn", + "annotation", + "name", + "description", + "typical_evidence", + "ref_id", + "associated_reference_controls", + "associated_threats", + "parent_requirement", + ] + ) class Meta: model = RequirementAssessment diff --git a/backend/core/startup.py b/backend/core/startup.py index 0b5294dc5..f3faad47d 100644 --- a/backend/core/startup.py +++ b/backend/core/startup.py @@ -345,7 +345,6 @@ "view_complianceassessment", "view_requirementassessment", "change_requirementassessment", - "view_requirementnode", "view_evidence", "add_evidence", "change_evidence", diff --git a/enterprise/frontend/src/routes/(authentication)/login/+page.svelte b/enterprise/frontend/src/routes/(authentication)/login/+page.svelte index f34fdac3d..b5269596d 100644 --- a/enterprise/frontend/src/routes/(authentication)/login/+page.svelte +++ b/enterprise/frontend/src/routes/(authentication)/login/+page.svelte @@ -8,18 +8,29 @@ export let form: ActionData; -