From 6ed98bc601e9c949d5b31ad08020ec05779fed2a Mon Sep 17 00:00:00 2001 From: Greg Elin Date: Sun, 10 Dec 2023 14:59:32 -0500 Subject: [PATCH 1/3] Rendered Jinja parameters for system properties in control implementation statements --- CHANGELOG.md | 18 +++++++++++++++--- controls/models.py | 9 ++++++++- controls/views.py | 11 +++++++++++ templates/controls/editor.html | 2 +- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ead0a3e4..7dc8833ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,21 @@ GovReady-Q Release Notes ======================== +v0.xx.xx (December 10, 2023) +--------------------------- + +**Feature changes** + +* Support dynamically rendered Jinja parameters for system properties in control implementation statements. + +**UI changes** + +* Display rendered parameters for system properties in system control implementation statements. + +**Developer changes** + +* Add statement.body_rendered property containing jinja rendered content in system control implementation statements. + v0.11.8 (June 11, 2023) --------------------------- @@ -24,9 +39,6 @@ v0.11.6 (March 14, 2023) **Developer changes** * Upgrade Python libraries. - -**Developer changes** - * Add siteapp.management_views as webhooks for calling Django management commands. diff --git a/controls/models.py b/controls/models.py index 6043831fd..36852ed43 100644 --- a/controls/models.py +++ b/controls/models.py @@ -30,6 +30,7 @@ from django.db import transaction from django.core.validators import RegexValidator from django.core.validators import validate_email +from jinja2 import Environment, DictLoader import structlog from structlog import get_logger @@ -881,7 +882,13 @@ def combined_smt_partial(smt): # print(f"self.pid_current: {self.pid_current} XXXXXXXXXXXXX") # DEBUG # self.pid_current = smt.pid if smt.producer_element: - smt_formatted = smt.body.replace('\n','
') + # Add 'body_rendered' property to smt containing rendered version of smt.body in case we have embedded parameters + # System is available here as self + smt_env = Environment(loader=DictLoader({'smt_body_template': smt.body})) + template = smt_env.get_template('smt_body_template') + smt.body_rendered = template.render(system=self) + smt_formatted = smt.body_rendered.replace('\n','
') + # smt_formatted = smt.body.replace('\n','
') # TODO: Clean up special characters smt_formatted = smt_formatted.replace(u"\u2019", "'").replace(u"\u2022", "
  • ") # Poor performance, at least in some instances, appears to being caused by `smt.producer_element.name` diff --git a/controls/views.py b/controls/views.py index 23b198f5a..9f7b94781 100644 --- a/controls/views.py +++ b/controls/views.py @@ -26,6 +26,7 @@ from django.db.models.functions import Lower from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse, \ HttpResponseNotAllowed +from jinja2 import Environment, DictLoader from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.text import slugify @@ -2285,6 +2286,16 @@ def editor(request, system_id, catalog_key, cl_id): # need parties and roles to not be empty # Build OSCAL SSP # Example: https://github.com/usnistgov/oscal-content/tree/master/examples/ssp/json/ssp-example.json + + # Add 'body_rendered' property to smt containing rendered version of smt.body in case we have embedded parameters + # Get the system + system = System.objects.get(pk=system_id) + for smt in impl_smts: + smt_env = Environment(loader=DictLoader({'smt_body_template': smt.body})) + template = smt_env.get_template('smt_body_template') + smt.body_rendered = template.render(system=system) + #rendered = template.render(project=project, system=system) + # oscalize key cl_id = oscalize_control_id(cl_id) diff --git a/templates/controls/editor.html b/templates/controls/editor.html index 4f27c615c..2743b692a 100644 --- a/templates/controls/editor.html +++ b/templates/controls/editor.html @@ -305,7 +305,7 @@

    {{ smt.producer_element.component_state }} -
    {% if smt.pid is not None and smt.pid != "" %}
    {{ smt.pid }}.
    {% endif %}{{ smt.body }}
    +
    {% if smt.pid is not None and smt.pid != "" %}
    {{ smt.pid }}.
    {% endif %}{{ smt.body_rendered }}
    {% spaceless %} Status: {% if smt.status != "" and smt.status is not None %}{{ smt.status }}{% else %}TBD{% endif %} From 644eea6451caa04a95ab980c018b902594195761 Mon Sep 17 00:00:00 2001 From: Greg Elin Date: Tue, 19 Dec 2023 08:25:59 -0500 Subject: [PATCH 2/3] Add conditional tests; function for easy access to export_json --- controls/models.py | 19 ++++++++++++++++--- controls/views.py | 5 ++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/controls/models.py b/controls/models.py index 36852ed43..a2dc5f0c5 100644 --- a/controls/models.py +++ b/controls/models.py @@ -882,13 +882,16 @@ def combined_smt_partial(smt): # print(f"self.pid_current: {self.pid_current} XXXXXXXXXXXXX") # DEBUG # self.pid_current = smt.pid if smt.producer_element: + #smt_formatted = smt.body.replace('\n','
    ') # Add 'body_rendered' property to smt containing rendered version of smt.body in case we have embedded parameters - # System is available here as self + # System is available here as `self` smt_env = Environment(loader=DictLoader({'smt_body_template': smt.body})) template = smt_env.get_template('smt_body_template') - smt.body_rendered = template.render(system=self) + try: + smt.body_rendered = template.render(system=self) + except: + smt.body_rendered = "\n" + smt.body smt_formatted = smt.body_rendered.replace('\n','
    ') - # smt_formatted = smt.body.replace('\n','
    ') # TODO: Clean up special characters smt_formatted = smt_formatted.replace(u"\u2019", "'").replace(u"\u2022", "
  • ") # Poor performance, at least in some instances, appears to being caused by `smt.producer_element.name` @@ -1018,6 +1021,16 @@ def add_event(self, event_type, description, info={}): return se + def answer(self, module='speedy_ssp_basic_info',answer='internal_customer'): + # To Do: + try: + module_question_answer = self.projects.all()[0].export_json()['project']['answers'][module]['value']['answers'][answer]['text'] + return module_question_answer + except: + return f"" + + + class SystemEvent(auto_prefetch.Model, TagModelMixin, BaseModel): system = auto_prefetch.ForeignKey('System', related_name='events', on_delete=models.CASCADE, blank=True, null=True, help_text="Events related to the system") diff --git a/controls/views.py b/controls/views.py index 9f7b94781..bcdc168f2 100644 --- a/controls/views.py +++ b/controls/views.py @@ -2293,7 +2293,10 @@ def editor(request, system_id, catalog_key, cl_id): for smt in impl_smts: smt_env = Environment(loader=DictLoader({'smt_body_template': smt.body})) template = smt_env.get_template('smt_body_template') - smt.body_rendered = template.render(system=system) + try: + smt.body_rendered = template.render(system=system) + except: + smt.body_rendered = "\n" + smt.body #rendered = template.render(project=project, system=system) # oscalize key From 99aa6aaa4bc0ab525a38582110dd2b202ca291ac Mon Sep 17 00:00:00 2001 From: Greg Elin Date: Mon, 25 Dec 2023 19:06:03 -0600 Subject: [PATCH 3/3] Remove unneeded URL route --- siteapp/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siteapp/urls.py b/siteapp/urls.py index 478e08a88..a838d1217 100644 --- a/siteapp/urls.py +++ b/siteapp/urls.py @@ -104,7 +104,7 @@ url(r"^systems/", include("controls.urls")), url(r"^api/v1/systems/", include("controls.urls_api")), - url(r"^controls$", include("controls.urls")), + # url(r"^controls$", include("controls.urls")), url(r"^controls/", include("controls.urls")), # portfolios