From 7d0868855fd879de8af775097558a7352f87679b Mon Sep 17 00:00:00 2001 From: Jacob Woffenden Date: Mon, 18 Nov 2024 14:28:56 +0000 Subject: [PATCH 01/13] Add cross account statement Signed-off-by: Jacob Woffenden --- .../api/templates/assume_roles/cloud_platform_xacct.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 controlpanel/api/templates/assume_roles/cloud_platform_xacct.json diff --git a/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json b/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json new file mode 100644 index 000000000..fec74ff5f --- /dev/null +++ b/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json @@ -0,0 +1,8 @@ +{ + "Sid": "AllowCloudPlatformCrossAccountIAM", + "Effect": "Allow", + "Action": "sts:AssumeRole", + "Principal": { + "AWS": "{{ app_role }}" + } +} From 0fd10db8733a4bc2632f8b409d6a981894dd3630 Mon Sep 17 00:00:00 2001 From: Jacob Woffenden Date: Mon, 18 Nov 2024 14:49:14 +0000 Subject: [PATCH 02/13] Add xacct_trust_statement Signed-off-by: Jacob Woffenden --- controlpanel/api/cluster.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/controlpanel/api/cluster.py b/controlpanel/api/cluster.py index 5b4df3864..961d2c22e 100644 --- a/controlpanel/api/cluster.py +++ b/controlpanel/api/cluster.py @@ -501,6 +501,19 @@ def oidc_provider_statement(self): ) return json.loads(statement) + @property + def xacct_trust_statement(self): + """ + Builds an assume role statement for a Cloud Platform IAM role + """ + statement = render_to_string( + template_name="assume_roles/cloud_platform_xacct.json", + context={ + "app_role": self.app.role + }, + ) + return json.loads(statement) + def create_iam_role(self): assume_role_policy = deepcopy(BASE_ASSUME_ROLE_POLICY) assume_role_policy["Statement"].append(self.oidc_provider_statement) From 3b26ea8804359a1b0feed1cdf33510e553ca0ee2 Mon Sep 17 00:00:00 2001 From: Jacob Woffenden Date: Mon, 18 Nov 2024 14:51:40 +0000 Subject: [PATCH 03/13] the linters have spoken Signed-off-by: Jacob Woffenden --- controlpanel/api/cluster.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/controlpanel/api/cluster.py b/controlpanel/api/cluster.py index 961d2c22e..478798e1e 100644 --- a/controlpanel/api/cluster.py +++ b/controlpanel/api/cluster.py @@ -508,9 +508,7 @@ def xacct_trust_statement(self): """ statement = render_to_string( template_name="assume_roles/cloud_platform_xacct.json", - context={ - "app_role": self.app.role - }, + context={"app_role": self.app.role}, ) return json.loads(statement) From 99e0dff47dc662b5d3ca76a26525ad5d894f043e Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:07:07 +0000 Subject: [PATCH 04/13] Added option to add cloud platform arn role to allow CP role to assume AP role --- controlpanel/api/cluster.py | 11 ++++- .../0046_app_cloud_platform_role_arn.py | 24 +++++++++++ controlpanel/api/models/app.py | 7 ++++ .../assume_roles/cloud_platform_xacct.json | 3 +- controlpanel/api/validators.py | 5 +++ controlpanel/frontend/forms.py | 4 ++ .../frontend/jinja2/webapp-create.html | 40 ++++++++++++++++++- .../modules/toggle-checkbox-form.js | 5 +++ controlpanel/frontend/views/app.py | 9 +++++ controlpanel/frontend/views/apps_mng.py | 2 + tests/frontend/views/test_app.py | 20 ++++++++++ 11 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py diff --git a/controlpanel/api/cluster.py b/controlpanel/api/cluster.py index 478798e1e..3d57b5bdd 100644 --- a/controlpanel/api/cluster.py +++ b/controlpanel/api/cluster.py @@ -508,17 +508,24 @@ def xacct_trust_statement(self): """ statement = render_to_string( template_name="assume_roles/cloud_platform_xacct.json", - context={"app_role": self.app.role}, + context={"app_role": self.app.cloud_platform_role_arn}, ) return json.loads(statement) def create_iam_role(self): + statement = self._get_statement() assume_role_policy = deepcopy(BASE_ASSUME_ROLE_POLICY) - assume_role_policy["Statement"].append(self.oidc_provider_statement) + assume_role_policy["Statement"].append(statement) self.aws_role_service.create_role(self.iam_role_name, assume_role_policy) for env in self.get_deployment_envs(): self._create_secrets(env_name=env) + def _get_statement(self): + if self.app.cloud_platform_role_arn: + return self.xacct_trust_statement + + return self.oidc_provider_statement + def grant_bucket_access(self, bucket_arn, access_level, path_arns): self.aws_role_service.grant_bucket_access( self.iam_role_name, bucket_arn, access_level, path_arns diff --git a/controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py b/controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py new file mode 100644 index 000000000..e2536bfb6 --- /dev/null +++ b/controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.2 on 2024-11-19 13:22 + +# Third-party +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("api", "0045_task_retried_at"), + ] + + operations = [ + migrations.AddField( + model_name="app", + name="cloud_platform_role_arn", + field=models.CharField( + default=None, + help_text="The cloud platform arn for the app", + max_length=130, + null=True, + ), + ), + ] diff --git a/controlpanel/api/models/app.py b/controlpanel/api/models/app.py index 384ba5d91..7f5f8f06f 100644 --- a/controlpanel/api/models/app.py +++ b/controlpanel/api/models/app.py @@ -20,6 +20,7 @@ class App(TimeStampedModel): + name = models.CharField(max_length=100, blank=False) description = models.TextField(blank=True) slug = AutoSlugField(populate_from="_repo_name", slugify_function=s3_slugify) @@ -32,6 +33,12 @@ class App(TimeStampedModel): related_query_name="app", blank=True, ) + cloud_platform_role_arn = models.CharField( + help_text="The cloud platform arn for the app", + max_length=130, + null=True, + default=None, + ) res_id = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) is_bedrock_enabled = models.BooleanField(default=False) is_textract_enabled = models.BooleanField(default=False) diff --git a/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json b/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json index fec74ff5f..3389474cd 100644 --- a/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json +++ b/controlpanel/api/templates/assume_roles/cloud_platform_xacct.json @@ -4,5 +4,6 @@ "Action": "sts:AssumeRole", "Principal": { "AWS": "{{ app_role }}" - } + }, + "Condition": {} } diff --git a/controlpanel/api/validators.py b/controlpanel/api/validators.py index 659d5e2ee..706589893 100644 --- a/controlpanel/api/validators.py +++ b/controlpanel/api/validators.py @@ -67,6 +67,11 @@ def __call__(self, value): "can only contain alphanumeric, underscores and hyphens)", ) +validate_aws_role_arn = RegexValidator( + regex=r"^arn:aws:iam::[0-9]{12}:role/[a-zA-Z0-9-_]+$", + message="ARN is invalid. Check AWS ARN format (for example, 'arn:aws:iam::123456789012:role/role_name')", +) + def validate_github_repository_url(value): github_base_url = "https://github.com/" diff --git a/controlpanel/frontend/forms.py b/controlpanel/frontend/forms.py index 9761cda18..4bbad4019 100644 --- a/controlpanel/frontend/forms.py +++ b/controlpanel/frontend/forms.py @@ -139,6 +139,10 @@ class CreateAppForm(forms.Form): required=False, ) namespace = forms.CharField(required=True, max_length=63) + allow_cloud_platform_assume_role = forms.BooleanField(initial=False, required=False) + cloud_platform_role_arn = forms.CharField( + required=False, max_length=130, validators=[validators.validate_aws_role_arn] + ) def __init__(self, *args, **kwargs): self.request = kwargs.pop("request", None) diff --git a/controlpanel/frontend/jinja2/webapp-create.html b/controlpanel/frontend/jinja2/webapp-create.html index f02fa3c25..f46201dd9 100644 --- a/controlpanel/frontend/jinja2/webapp-create.html +++ b/controlpanel/frontend/jinja2/webapp-create.html @@ -73,7 +73,7 @@

{{ page_title }}

}) }} {% endif %} - +
@@ -90,7 +90,7 @@

{{ page_title }}

}) }} {% endif %} Enter namespace with the -env suffix removed - +
@@ -128,6 +128,42 @@

{{ page_title }}

] }) }} + {{ govukCheckboxes({ + "name": "allow_cloud_platform_assume_role", + "fieldset": { + "legend": { + "text": "Access via Cloud Platform", + "classes": "govuk-fieldset__legend--m", + }, + }, + "hint": { + "text": "Allows Cloud Platform role to assume role in the Analytical Platform" + }, + "items": [ + { + "value": "True", + "text": "Test", + "checked": form.allow_cloud_platform_assume_role.value() == True + } + ] + }) }} + +
+
+
+ {{ govukInput({ + "name": "cloud_platform_role_arn", + "classes": "govuk-!-width-one-half", + "label": { + "text": "Cloud Platform Role ARN", + "classes": "govuk-label--s", + }, + "errorMessage": {"text": form.errors.get("cloud_platform_role_arn")} if form.errors.get("cloud_platform_role_arn") else {}, + "value": form.cloud_platform_role_arn.value() + }) }} +
+
+
diff --git a/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js b/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js index c63410e6b..1b5bb8e7e 100644 --- a/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js +++ b/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js @@ -6,6 +6,7 @@ moj.Modules.toggleCheckboxForm = { init() { const panels = document.querySelectorAll(`.${this.subFormClass}`); if (panels) { + console.log(panels); this.bindEvents(panels); } }, @@ -13,8 +14,12 @@ moj.Modules.toggleCheckboxForm = { bindEvents(panels) { panels.forEach(panel => { + console.log(panel); + console.log(this.selector); const attribute = panel.getAttribute(this.selector); + console.log(attribute); var formItem = document.querySelector(`[value=${attribute}]`); + console.log(formItem); this.setVisibility(panel, formItem.checked); diff --git a/controlpanel/frontend/views/app.py b/controlpanel/frontend/views/app.py index 56ace1dab..7399c1689 100644 --- a/controlpanel/frontend/views/app.py +++ b/controlpanel/frontend/views/app.py @@ -200,6 +200,15 @@ def get_success_url(self): def form_valid(self, form): try: + assume_role = form.cleaned_data.get("allow_cloud_platform_assume_role") + role_arn = form.cleaned_data.get("cloud_platform_role_arn") + if assume_role and not role_arn: + form.add_error("cloud_platform_role_arn", "Role ARN is required") + return FormMixin.form_invalid(self, form) + + if not assume_role and role_arn: + form.cleaned_data.pop("cloud_platform_role_arn") + self.object = AppManager().register_app(self.request.user, form.cleaned_data) except Exception as ex: form.add_error("repo_url", str(ex)) diff --git a/controlpanel/frontend/views/apps_mng.py b/controlpanel/frontend/views/apps_mng.py index f103f52a6..4676150e0 100644 --- a/controlpanel/frontend/views/apps_mng.py +++ b/controlpanel/frontend/views/apps_mng.py @@ -25,6 +25,7 @@ class AppManager: def register_app(self, user, app_data): repo_url = app_data["repo_url"] _, name = repo_url.rsplit("/", 1) + cloud_platform_role_arn = app_data.get("cloud_platform_role_arn", None) # Create app and all the related sources new_app = self._create_app( @@ -32,6 +33,7 @@ def register_app(self, user, app_data): repo_url=repo_url, current_user=user, namespace=app_data["namespace"], + cloud_platform_role_arn=cloud_platform_role_arn, ) self._add_app_to_users(new_app, user) self._create_or_link_datasource(new_app, user, app_data) diff --git a/tests/frontend/views/test_app.py b/tests/frontend/views/test_app.py index 99a263cb7..ae1f4fefc 100644 --- a/tests/frontend/views/test_app.py +++ b/tests/frontend/views/test_app.py @@ -738,6 +738,26 @@ def test_app_settings_permission(client, app, users, repos_with_auth, user, can_ assert "Edit" not in auth_item_ui.text +def test_register_app_with_xacct_policy(client, users): + test_app_name = "test_app_with_xacct_policy" + assert App.objects.filter(name=test_app_name).count() == 0 + client.force_login(users["superuser"]) + data = dict( + repo_url=f"https://github.com/ministryofjustice/{test_app_name}", + namespace="test-app-namespace", + connect_bucket="later", + allow_cloud_platform_assume_role=True, + cloud_platform_role_arn="arn:aws:iam::123456789012:role/test_role", + ) + response = client.post(reverse("create-app"), data) + + assert response.status_code == 302 + assert App.objects.filter(name=test_app_name).count() == 1 + created_app = App.objects.filter(name=test_app_name).first() + assert created_app.cloud_platform_role_arn == "arn:aws:iam::123456789012:role/test_role" + assert response.url == reverse("manage-app", kwargs={"pk": created_app.pk}) + + def test_register_app_with_creating_datasource(client, users): test_app_name = "test_app_with_creating_datasource" test_bucket_name = "test-bucket" From 04177e0e8cc9999e17368c3d7af22a95244d6684 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:18:43 +0000 Subject: [PATCH 05/13] Hidden additional form through feature flag --- controlpanel/frontend/jinja2/webapp-create.html | 2 ++ controlpanel/frontend/views/app.py | 7 +++++++ settings.yaml | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/controlpanel/frontend/jinja2/webapp-create.html b/controlpanel/frontend/jinja2/webapp-create.html index f46201dd9..e4e588ab5 100644 --- a/controlpanel/frontend/jinja2/webapp-create.html +++ b/controlpanel/frontend/jinja2/webapp-create.html @@ -128,6 +128,7 @@

{{ page_title }}

] }) }} + {% if show_cloud_platform_assume_role %} {{ govukCheckboxes({ "name": "allow_cloud_platform_assume_role", "fieldset": { @@ -163,6 +164,7 @@

{{ page_title }}

}) }} + {% endif %}
diff --git a/controlpanel/frontend/views/app.py b/controlpanel/frontend/views/app.py index 7399c1689..e7ea9ced9 100644 --- a/controlpanel/frontend/views/app.py +++ b/controlpanel/frontend/views/app.py @@ -256,6 +256,13 @@ def form_valid(self, form): return FormMixin.form_invalid(self, form) return FormMixin.form_valid(self, form) + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context["show_cloud_platform_assume_role"] = ( + settings.features.cloud_platform_assume_role.enabled + ) + return context + class UpdateAppIPAllowlists(OIDCLoginRequiredMixin, PermissionRequiredMixin, UpdateView): diff --git a/settings.yaml b/settings.yaml index 5258fce67..31f0a63b6 100644 --- a/settings.yaml +++ b/settings.yaml @@ -11,6 +11,11 @@ enabled_features: _HOST_dev: true _HOST_test: true _HOST_prod: true + cloud_platform_assume_role: + _DEFAULT: false + _HOST_dev: false + _HOST_prod: false + _HOST_alpha: false AWS_SERVICE_URL: _HOST_dev: "https://aws.services.dev.analytical-platform.service.justice.gov.uk" From 806a66e1ede5eba58ffbbe850a2fae40a415f314 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:21:36 +0000 Subject: [PATCH 06/13] Moved code to correct view --- controlpanel/frontend/views/app.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/controlpanel/frontend/views/app.py b/controlpanel/frontend/views/app.py index e7ea9ced9..b59ada9a8 100644 --- a/controlpanel/frontend/views/app.py +++ b/controlpanel/frontend/views/app.py @@ -214,6 +214,13 @@ def form_valid(self, form): form.add_error("repo_url", str(ex)) return FormMixin.form_invalid(self, form) return FormMixin.form_valid(self, form) + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context["show_cloud_platform_assume_role"] = ( + settings.features.cloud_platform_assume_role.enabled + ) + return context class UpdateAppAuth0Connections(OIDCLoginRequiredMixin, PermissionRequiredMixin, UpdateView): @@ -256,13 +263,6 @@ def form_valid(self, form): return FormMixin.form_invalid(self, form) return FormMixin.form_valid(self, form) - def get_context_data(self, *args, **kwargs): - context = super().get_context_data(*args, **kwargs) - context["show_cloud_platform_assume_role"] = ( - settings.features.cloud_platform_assume_role.enabled - ) - return context - class UpdateAppIPAllowlists(OIDCLoginRequiredMixin, PermissionRequiredMixin, UpdateView): From 349d3feb39f75306383d1db77165211ec9c7d892 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:28:57 +0000 Subject: [PATCH 07/13] Ran black --- controlpanel/frontend/views/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controlpanel/frontend/views/app.py b/controlpanel/frontend/views/app.py index b59ada9a8..3d43529db 100644 --- a/controlpanel/frontend/views/app.py +++ b/controlpanel/frontend/views/app.py @@ -214,7 +214,7 @@ def form_valid(self, form): form.add_error("repo_url", str(ex)) return FormMixin.form_invalid(self, form) return FormMixin.form_valid(self, form) - + def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) context["show_cloud_platform_assume_role"] = ( From 14731ab6652ed23f063e4644ae5224b8d563a2f5 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:34:19 +0000 Subject: [PATCH 08/13] Fixed flake8 error --- controlpanel/api/validators.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/controlpanel/api/validators.py b/controlpanel/api/validators.py index 706589893..55941d3f7 100644 --- a/controlpanel/api/validators.py +++ b/controlpanel/api/validators.py @@ -69,7 +69,10 @@ def __call__(self, value): validate_aws_role_arn = RegexValidator( regex=r"^arn:aws:iam::[0-9]{12}:role/[a-zA-Z0-9-_]+$", - message="ARN is invalid. Check AWS ARN format (for example, 'arn:aws:iam::123456789012:role/role_name')", + message=( + "ARN is invalid. Check AWS ARN format " + "(for example, 'arn:aws:iam::123456789012:role/role_name')" + ) ) From f8d60d2bf655946cfc0ea85502ef7b14a3e4b805 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:38:01 +0000 Subject: [PATCH 09/13] Changed text on checkbox --- controlpanel/frontend/jinja2/webapp-create.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controlpanel/frontend/jinja2/webapp-create.html b/controlpanel/frontend/jinja2/webapp-create.html index e4e588ab5..945862d71 100644 --- a/controlpanel/frontend/jinja2/webapp-create.html +++ b/controlpanel/frontend/jinja2/webapp-create.html @@ -143,7 +143,7 @@

{{ page_title }}

"items": [ { "value": "True", - "text": "Test", + "text": "Access via Cloud Platform", "checked": form.allow_cloud_platform_assume_role.value() == True } ] From 4fb73f761bdcad627e1b4bd1f4dfd760a5b9cfcf Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 21 Nov 2024 11:39:45 +0000 Subject: [PATCH 10/13] Ran black again --- controlpanel/api/validators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controlpanel/api/validators.py b/controlpanel/api/validators.py index 55941d3f7..fdc8cfb1d 100644 --- a/controlpanel/api/validators.py +++ b/controlpanel/api/validators.py @@ -70,9 +70,9 @@ def __call__(self, value): validate_aws_role_arn = RegexValidator( regex=r"^arn:aws:iam::[0-9]{12}:role/[a-zA-Z0-9-_]+$", message=( - "ARN is invalid. Check AWS ARN format " + "ARN is invalid. Check AWS ARN format " "(for example, 'arn:aws:iam::123456789012:role/role_name')" - ) + ), ) From 404759f85dcb96f5ef9f7b53ab525d48f5dc33e0 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Wed, 27 Nov 2024 16:00:51 +0000 Subject: [PATCH 11/13] Updated migrations --- ...atform_role_arn.py => 0047_app_cloud_platform_role_arn.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename controlpanel/api/migrations/{0046_app_cloud_platform_role_arn.py => 0047_app_cloud_platform_role_arn.py} (83%) diff --git a/controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py b/controlpanel/api/migrations/0047_app_cloud_platform_role_arn.py similarity index 83% rename from controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py rename to controlpanel/api/migrations/0047_app_cloud_platform_role_arn.py index e2536bfb6..cecbc6e4d 100644 --- a/controlpanel/api/migrations/0046_app_cloud_platform_role_arn.py +++ b/controlpanel/api/migrations/0047_app_cloud_platform_role_arn.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.2 on 2024-11-19 13:22 +# Generated by Django 5.1.2 on 2024-11-27 15:46 # Third-party from django.db import migrations, models @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ("api", "0045_task_retried_at"), + ("api", "0046_alter_user_options"), ] operations = [ From c3da9239c587f467e9694240b06ff7276d7c2844 Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Wed, 27 Nov 2024 16:04:43 +0000 Subject: [PATCH 12/13] removed logging from JS --- .../static/javascripts/modules/toggle-checkbox-form.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js b/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js index 1b5bb8e7e..c63410e6b 100644 --- a/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js +++ b/controlpanel/frontend/static/javascripts/modules/toggle-checkbox-form.js @@ -6,7 +6,6 @@ moj.Modules.toggleCheckboxForm = { init() { const panels = document.querySelectorAll(`.${this.subFormClass}`); if (panels) { - console.log(panels); this.bindEvents(panels); } }, @@ -14,12 +13,8 @@ moj.Modules.toggleCheckboxForm = { bindEvents(panels) { panels.forEach(panel => { - console.log(panel); - console.log(this.selector); const attribute = panel.getAttribute(this.selector); - console.log(attribute); var formItem = document.querySelector(`[value=${attribute}]`); - console.log(formItem); this.setVisibility(panel, formItem.checked); From a741d3bd592a10f3700ce63020f8aaa04358db3f Mon Sep 17 00:00:00 2001 From: jamesstottmoj Date: Thu, 28 Nov 2024 12:48:58 +0000 Subject: [PATCH 13/13] Moved code to clean method in form. Enabled in dev for testing --- controlpanel/frontend/forms.py | 9 +++++++++ controlpanel/frontend/views/app.py | 9 --------- settings.yaml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/controlpanel/frontend/forms.py b/controlpanel/frontend/forms.py index 5e04f09ef..c688ace24 100644 --- a/controlpanel/frontend/forms.py +++ b/controlpanel/frontend/forms.py @@ -189,6 +189,15 @@ def clean(self): if connect_data_source == "existing" and not existing_datasource: self.add_error("existing_datasource_id", "This field is required.") + assume_role = cleaned_data.get("allow_cloud_platform_assume_role") + role_arn = cleaned_data.get("cloud_platform_role_arn") + + if assume_role and not role_arn: + self.add_error("cloud_platform_role_arn", "Role ARN is required") + + if not assume_role and role_arn: + cleaned_data.pop("cloud_platform_role_arn") + return cleaned_data def clean_repo_url(self): diff --git a/controlpanel/frontend/views/app.py b/controlpanel/frontend/views/app.py index 3d43529db..1b7e1ef76 100644 --- a/controlpanel/frontend/views/app.py +++ b/controlpanel/frontend/views/app.py @@ -200,15 +200,6 @@ def get_success_url(self): def form_valid(self, form): try: - assume_role = form.cleaned_data.get("allow_cloud_platform_assume_role") - role_arn = form.cleaned_data.get("cloud_platform_role_arn") - if assume_role and not role_arn: - form.add_error("cloud_platform_role_arn", "Role ARN is required") - return FormMixin.form_invalid(self, form) - - if not assume_role and role_arn: - form.cleaned_data.pop("cloud_platform_role_arn") - self.object = AppManager().register_app(self.request.user, form.cleaned_data) except Exception as ex: form.add_error("repo_url", str(ex)) diff --git a/settings.yaml b/settings.yaml index 31f0a63b6..b024537b6 100644 --- a/settings.yaml +++ b/settings.yaml @@ -13,7 +13,7 @@ enabled_features: _HOST_prod: true cloud_platform_assume_role: _DEFAULT: false - _HOST_dev: false + _HOST_dev: true _HOST_prod: false _HOST_alpha: false