diff --git a/app/blueprints/fund/routes.py b/app/blueprints/fund/routes.py index 48b06253..3630bdc5 100644 --- a/app/blueprints/fund/routes.py +++ b/app/blueprints/fund/routes.py @@ -14,7 +14,6 @@ from app.db.queries.fund import add_fund, get_all_funds, get_fund_by_id, update_fund, delete_selected_fund from app.shared.helpers import flash_message from app.shared.table_pagination import GovUKTableAndPagination -from config import Config INDEX_BP_DASHBOARD = "index_bp.dashboard" SELECT_GRANT_PAGE = "select_grant" @@ -45,16 +44,18 @@ def view_all_funds(): return render_template("view_all_funds.html", **params) -@fund_bp.route("/", methods=["GET"]) +@fund_bp.route("/", methods=["GET", "DELETE"]) def view_fund_details(fund_id): """ Renders grant details page """ form = FundForm() + if request.method == "DELETE": + delete_selected_fund(fund_id) + return redirect(url_for("fund_bp.view_all_funds")) fund = get_fund_by_id(fund_id) - return render_template("fund_details.html", - form=form, fund=fund, - feature_flags=Config.FEATURE_FLAGS) + #TODO at this time we are not implementing the delete grant but later we have to implement + return render_template("fund_details.html", form=form, fund=fund) def _create_fund_get_previous_url(actions): @@ -180,11 +181,3 @@ def edit_fund(fund_id): params.update({"fund_id": fund_id, "form": form, "prev_nav_url": prev_nav_url}) return render_template("fund.html", **params) - - -@fund_bp.route("//delete", methods=["GET"]) -def delete_fund(fund_id): - if not Config.FEATURE_FLAGS.get('feature_delete'): - return "Delete Feature Disabled", 403 - delete_selected_fund(fund_id) - return redirect(url_for("fund_bp.view_all_funds")) diff --git a/app/blueprints/fund/templates/fund_details.html b/app/blueprints/fund/templates/fund_details.html index 9f4eb487..706a3eab 100644 --- a/app/blueprints/fund/templates/fund_details.html +++ b/app/blueprints/fund/templates/fund_details.html @@ -170,15 +170,4 @@

{{ fund.name_json["en"] }}

}) }} - {% if feature_flags.get('feature_delete') %} -
-
- {{ govukButton({ - "text": "Delete grant ", - "classes": "govuk-button--warning", - "href": url_for("fund_bp.delete_fund", fund_id=fund.fund_id) - }) }} -
-
- {% endif %} {% endblock content %} diff --git a/app/blueprints/round/routes.py b/app/blueprints/round/routes.py index 074fa4a6..454c7392 100644 --- a/app/blueprints/round/routes.py +++ b/app/blueprints/round/routes.py @@ -198,22 +198,16 @@ def clone_round(round_id): return redirect(url_for(ROUND_DETAILS, round_id=round_id)) -@round_bp.route("/") +@round_bp.route("/", methods=["GET", "DELETE"]) def round_details(round_id): fund_round = get_round_by_id(round_id) form = RoundForm(data={"fund_id": fund_round.fund_id}) - cloned_form = CloneRoundForm(data={"fund_id": fund_round.fund_id}) fund_form = FundForm() + if request.method == "DELETE": + delete_selected_round(round_id) + return redirect(url_for("round_bp.view_all_rounds")) + cloned_form = CloneRoundForm(data={"fund_id": fund_round.fund_id}) + # TODO at this time we are not implementing the delete applications but later we have to implement return render_template( "round_details.html", form=form, fund_form=fund_form, round=fund_round, - cloned_form=cloned_form, - feature_flags=Config.FEATURE_FLAGS - ) - - -@round_bp.route("//delete", methods=["GET"]) -def delete_round(round_id): - if not Config.FEATURE_FLAGS.get('feature_delete'): - return "Delete Feature Disabled", 403 - delete_selected_round(round_id) - return redirect(url_for("round_bp.view_all_rounds")) + cloned_form=cloned_form) diff --git a/app/blueprints/round/templates/round_details.html b/app/blueprints/round/templates/round_details.html index 42350234..610cbc62 100644 --- a/app/blueprints/round/templates/round_details.html +++ b/app/blueprints/round/templates/round_details.html @@ -9,8 +9,8 @@ {% set active_item_identifier = "applications" %} {% extends "base.html" %} {% block beforeContent %} - {{ super() }} -
+ {{ super() }} +
{{ govukBackLink({ "text": "Back", @@ -20,39 +20,37 @@
{% endblock beforeContent %} {% block content %} -
-
-

Apply for {{ round.fund.title_json["en"] }}

- Change - application name -
-
- {{ govukButton({ "text": "Build application", +
+
+

Apply for {{ round.fund.title_json["en"] }}

+ Change application name +
+
+ {{ govukButton({ "text": "Build application", "href": url_for("application_bp.build_application", round_id=round.round_id, action="application_details"), "classes": "govuk-button--secondary" }) }} -
-
-
-
-
- {{ cloned_form.hidden_tag() }} - {{ cloned_form.fund_id() }} -
- {{ govukButton({ "text": "Copy application", "type": submit, +
+
+
+ +
+ {{ cloned_form.hidden_tag() }} + {{ cloned_form.fund_id() }} +
+ {{ govukButton({ "text": "Copy application", "type": submit, "classes": "govuk-button--secondary" }) }} - + -
-
-
-

Grant: {{ round.fund.name_json['en'] }}

+
+
+
+

Grant: {{ round.fund.name_json['en'] }}

- {{ govukSummaryList({ + {{ govukSummaryList({ "classes": "govuk-!-margin-bottom-9", "rows": [ { @@ -463,17 +461,6 @@

Apply for {{ round.fund.titl }, ] }) }} -

- {% if feature_flags.get('feature_delete') %} -
-
- {{ govukButton({ - "text": "Delete application ", - "classes": "govuk-button--warning", - "href": url_for("round_bp.delete_round", round_id=round.round_id) - }) }} -
-
- {% endif %} +
{% endblock content %} diff --git a/config/envs/default.py b/config/envs/default.py index b1545dab..d337448f 100644 --- a/config/envs/default.py +++ b/config/envs/default.py @@ -85,7 +85,3 @@ class DefaultConfig(object): "x_xss_protection": True, "content_security_policy_nonce_in": ["script-src"], } - - FEATURE_FLAGS = { - "feature_delete": getenv("FEATURE_DELETE", "False").strip().lower() == "true", - } diff --git a/copilot/fsd-fund-application-builder/manifest.yml b/copilot/fsd-fund-application-builder/manifest.yml index 40b7900b..b1235270 100644 --- a/copilot/fsd-fund-application-builder/manifest.yml +++ b/copilot/fsd-fund-application-builder/manifest.yml @@ -54,7 +54,6 @@ variables: NOTIFICATION_SERVICE_HOST: http://fsd-notification:8080 MAINTENANCE_MODE: false SENTRY_DSN: https://4128cfd691c439577e8f106968217f72@o1432034.ingest.us.sentry.io/4508496706666497 - FEATURE_DELETE: false secrets: RSA256_PUBLIC_KEY_BASE64: /copilot/${COPILOT_APPLICATION_NAME}/${COPILOT_ENVIRONMENT_NAME}/secrets/RSA256_PUBLIC_KEY_BASE64 @@ -65,8 +64,6 @@ environments: dev: count: spot: 1 - variables: - FEATURE_DELETE: true sidecars: nginx: port: 8087 @@ -86,8 +83,6 @@ environments: test: count: spot: 2 - variables: - FEATURE_DELETE: true sidecars: nginx: port: 8087 diff --git a/tests/blueprints/fund/test_routes.py b/tests/blueprints/fund/test_routes.py index be137526..2e24a159 100644 --- a/tests/blueprints/fund/test_routes.py +++ b/tests/blueprints/fund/test_routes.py @@ -1,13 +1,12 @@ import pytest from bs4 import BeautifulSoup from flask import g +from sqlalchemy.orm import joinedload -from app.db.models import Fund, Round, Form, Section, Component, Lizt +from app.db.models import Fund, Round, Section, Component, Lizt from app.db.models.fund import FundingType from app.db.queries.fund import get_fund_by_id from tests.helpers import submit_form -from config import Config -from sqlalchemy.orm import joinedload @pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user") @@ -361,33 +360,27 @@ def test_create_fund_welsh_error_messages(flask_test_client, seed_dynamic_data): @pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user") -def test_delete_fund_feature_disabled(flask_test_client, monkeypatch, seed_fund_without_assessment): - """Test that the delete endpoint returns 403 when a feature flag is disabled.""" - test_fund: Fund = seed_fund_without_assessment["funds"][0] - monkeypatch.setattr(Config, "FEATURE_FLAGS", {"feature_delete": False}) - response = flask_test_client.get(f"/grants/{test_fund.fund_id}/delete", follow_redirects=True) - assert response.status_code == 403 - assert b"Delete Feature Disabled" in response.data - - -@pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user") -def test_delete_fund_feature_enabled(_db, flask_test_client, monkeypatch, seed_fund_without_assessment): +def test_delete_fund_feature_enabled(_db, flask_test_client, seed_fund_without_assessment): """Test that the delete endpoint redirects when a feature flag is enabled.""" test_fund: Fund = seed_fund_without_assessment["funds"][0] - monkeypatch.setattr(Config, "FEATURE_FLAGS", {"feature_delete": True}) - output: Fund = _db.session.get(Fund, test_fund.fund_id, + flask_test_client.get(f"/grants/{test_fund.fund_id}") + with flask_test_client.session_transaction(): + output: Fund = _db.session.get(Fund, test_fund.fund_id, + options=[joinedload(Fund.rounds).joinedload(Round.sections)]) + assert output is not None, "No values present in the db" + response = flask_test_client.delete(f"/grants/{test_fund.fund_id}", data={ + "csrf_token": g.csrf_token, + }, follow_redirects=True) + assert response.status_code == 200 # Assuming redirection to a valid page + _db.session.commit() + output_f = _db.session.get(Fund, test_fund.fund_id, options=[joinedload(Fund.rounds).joinedload(Round.sections)]) - assert output is not None, "No values present in the db" - response = flask_test_client.get(f"/grants/{test_fund.fund_id}/delete", follow_redirects=True) - assert response.status_code == 200 # Assuming redirection to a valid page - _db.session.commit() - output_f = _db.session.get(Fund, test_fund.fund_id, options=[joinedload(Fund.rounds).joinedload(Round.sections)]) - assert output_f is None, "Grant delete did not happened" - output_r = _db.session.query(Round).all() - assert not output_r, "Round delete did not happened" - output_s = _db.session.query(Section).all() - assert not output_s, "Section delete did not happened" - output_c = _db.session.query(Component).all() - assert not output_c, "Component delete did not happened" - output_l = _db.session.query(Lizt).all() - assert not output_l, "Lizt delete did not happened" + assert output_f is None, "Grant delete did not happened" + output_r = _db.session.query(Round).all() + assert not output_r, "Round delete did not happened" + output_s = _db.session.query(Section).all() + assert not output_s, "Section delete did not happened" + output_c = _db.session.query(Component).all() + assert not output_c, "Component delete did not happened" + output_l = _db.session.query(Lizt).all() + assert not output_l, "Lizt delete did not happened" diff --git a/tests/blueprints/round/test_routes.py b/tests/blueprints/round/test_routes.py index 0602545d..2e6c9e2a 100644 --- a/tests/blueprints/round/test_routes.py +++ b/tests/blueprints/round/test_routes.py @@ -1,12 +1,11 @@ import pytest from bs4 import BeautifulSoup from flask import g, url_for +from sqlalchemy.orm import joinedload from app.db.models import Round, Fund, Section, Component, Lizt from app.db.queries.round import get_round_by_id from tests.helpers import submit_form -from config import Config -from sqlalchemy.orm import joinedload round_data_info = { "opens": ["01", "10", "2024", "09", "00"], @@ -335,33 +334,27 @@ def test_clone_round(flask_test_client, seed_dynamic_data): @pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user") -def test_delete_fund_feature_disabled(flask_test_client, monkeypatch, seed_fund_without_assessment): - """Test that the delete endpoint returns 403 when a feature flag is disabled.""" - test_round: Round = seed_fund_without_assessment["rounds"][0] - monkeypatch.setattr(Config, "FEATURE_FLAGS", {"feature_delete": False}) - response = flask_test_client.get(f"/rounds/{test_round.round_id}/delete", follow_redirects=True) - assert response.status_code == 403 - assert b"Delete Feature Disabled" in response.data - - -@pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user") -def test_delete_fund_feature_enabled(_db, flask_test_client, monkeypatch, seed_fund_without_assessment): +def test_delete_fund_feature_enabled(_db, flask_test_client, seed_fund_without_assessment): """Test that the delete endpoint redirects when a feature flag is enabled.""" test_round: Round = seed_fund_without_assessment["rounds"][0] - monkeypatch.setattr(Config, "FEATURE_FLAGS", {"feature_delete": True}) - output: Fund = _db.session.get(Fund, test_round.fund_id, + flask_test_client.get(f"/rounds/{test_round.round_id}") + with flask_test_client.session_transaction(): + output: Fund = _db.session.get(Fund, test_round.fund_id, + options=[joinedload(Fund.rounds).joinedload(Round.sections)]) + assert output is not None, "No values present in the db" + response = flask_test_client.delete(f"/rounds/{test_round.round_id}", data={ + "csrf_token": g.csrf_token, + }, follow_redirects=True) + assert response.status_code == 200 # Assuming redirection to a valid page + _db.session.commit() + output_f = _db.session.get(Fund, test_round.fund_id, options=[joinedload(Fund.rounds).joinedload(Round.sections)]) - assert output is not None, "No values present in the db" - response = flask_test_client.get(f"/rounds/{test_round.round_id}/delete", follow_redirects=True) - assert response.status_code == 200 # Assuming redirection to a valid page - _db.session.commit() - output_f = _db.session.get(Fund, test_round.fund_id, options=[joinedload(Fund.rounds).joinedload(Round.sections)]) - assert output_f is not None, "Grant deleted" - output_r = _db.session.query(Round).all() - assert not output_r, "Round delete did not happened" - output_s = _db.session.query(Section).all() - assert not output_s, "Section delete did not happened" - output_c = _db.session.query(Component).all() - assert not output_c, "Component delete did not happened" - output_l = _db.session.query(Lizt).all() - assert not output_l, "Lizt delete did not happened" \ No newline at end of file + assert output_f is not None, "Grant deleted" + output_r = _db.session.query(Round).all() + assert not output_r, "Round delete did not happened" + output_s = _db.session.query(Section).all() + assert not output_s, "Section delete did not happened" + output_c = _db.session.query(Component).all() + assert not output_c, "Component delete did not happened" + output_l = _db.session.query(Lizt).all() + assert not output_l, "Lizt delete did not happened"