From 4d6f51ed7fc2f931a992ae4f1a2830789b6e16fd Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 11:25:01 -0400 Subject: [PATCH 1/9] Add route for read-only view of request --- atst/routes/requests/requests_form.py | 13 +++++++++++++ templates/requests/view_pending.html | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 templates/requests/view_pending.html diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index e9f1957a..ba23af65 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -119,6 +119,19 @@ def requests_submit(request_id=None): return redirect("/requests?modal=pendingCCPOApproval") +@requests_bp.route("/requests/pending/", methods=["GET"]) +def view_pending_request(request_id=None): + request = Requests.get(request_id) + return render_template( + "requests/view_pending.html", + data=request.body, + service_branches=SERVICE_BRANCHES, + assistance_org_types=ASSISTANCE_ORG_TYPES, + data_transfer_amounts=DATA_TRANSFER_AMOUNTS, + completion_date_ranges=COMPLETION_DATE_RANGES, + ) + + # TODO: generalize this, along with other authorizations, into a policy-pattern # for authorization in the application def _check_can_view_request(request_id): diff --git a/templates/requests/view_pending.html b/templates/requests/view_pending.html new file mode 100644 index 00000000..9bc33d1c --- /dev/null +++ b/templates/requests/view_pending.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% from "components/alert.html" import Alert %} + +{% block content %} +
+
+
+

View Pending Request

+
+ +
+ {{ Alert('Your request is being reviewed', + message="

You cannot edit your submitted request while it is under review. Your request will be reviewed within 3 business days.

", + level='warning' + ) }} + + {% include "requests/_review.html" %} + +
+
+
+{% endblock %} From 0906134f5658dea6f8de5b834d932a5fc1e4fa4b Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 11:27:41 -0400 Subject: [PATCH 2/9] Move data variables to context for easier re-use --- atst/routes/requests/requests_form.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index ba23af65..b4af5c73 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -13,6 +13,15 @@ from atst.forms.data import ( COMPLETION_DATE_RANGES, ) +@requests_bp.context_processor +def option_data(): + return { + "service_branches": SERVICE_BRANCHES, + "assistance_org_types": ASSISTANCE_ORG_TYPES, + "data_transfer_amounts": DATA_TRANSFER_AMOUNTS, + "completion_date_ranges": COMPLETION_DATE_RANGES, + } + @requests_bp.route("/requests/new/", methods=["GET"]) def requests_form_new(screen): @@ -26,10 +35,6 @@ def requests_form_new(screen): current=screen, next_screen=screen + 1, can_submit=jedi_flow.can_submit, - service_branches=SERVICE_BRANCHES, - assistance_org_types=ASSISTANCE_ORG_TYPES, - data_transfer_amounts=DATA_TRANSFER_AMOUNTS, - completion_date_ranges=COMPLETION_DATE_RANGES, ) @@ -56,10 +61,6 @@ def requests_form_update(screen=1, request_id=None): request_id=request_id, jedi_request=jedi_flow.request, can_submit=jedi_flow.can_submit, - service_branches=SERVICE_BRANCHES, - assistance_org_types=ASSISTANCE_ORG_TYPES, - data_transfer_amounts=DATA_TRANSFER_AMOUNTS, - completion_date_ranges=COMPLETION_DATE_RANGES, ) @@ -122,14 +123,7 @@ def requests_submit(request_id=None): @requests_bp.route("/requests/pending/", methods=["GET"]) def view_pending_request(request_id=None): request = Requests.get(request_id) - return render_template( - "requests/view_pending.html", - data=request.body, - service_branches=SERVICE_BRANCHES, - assistance_org_types=ASSISTANCE_ORG_TYPES, - data_transfer_amounts=DATA_TRANSFER_AMOUNTS, - completion_date_ranges=COMPLETION_DATE_RANGES, - ) + return render_template("requests/view_pending.html", data=request.body) # TODO: generalize this, along with other authorizations, into a policy-pattern From e7aed35054718151397608ab351662c10eaed905 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 11:44:44 -0400 Subject: [PATCH 3/9] Link to pending request page from index --- atst/routes/requests/index.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/atst/routes/requests/index.py b/atst/routes/requests/index.py index 25ecfe3f..a4e6c579 100644 --- a/atst/routes/requests/index.py +++ b/atst/routes/requests/index.py @@ -11,15 +11,15 @@ def map_request(request): is_new = time_created.add(days=1) > pendulum.now() app_count = request.body.get("details_of_use", {}).get("num_software_systems", 0) annual_usage = request.annual_spend - update_url = url_for( - "requests.requests_form_update", screen=1, request_id=request.id - ) - verify_url = url_for("requests.financial_verification", request_id=request.id) - edit_link = ( - verify_url - if Requests.is_pending_financial_verification(request) - else update_url - ) + + if Requests.is_pending_financial_verification(request): + edit_link = url_for("requests.financial_verification", request_id=request.id) + elif Requests.is_pending_ccpo_approval(request): + edit_link = url_for("requests.view_pending_request", request_id=request.id) + else: + edit_link = url_for( + "requests.requests_form_update", screen=1, request_id=request.id + ) return { "order_id": request.id, From d785f19b5b36db344d1392d4b2ffdd017acadaa4 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 13:19:12 -0400 Subject: [PATCH 4/9] Enforce authorization when getting a request --- atst/domain/authz.py | 13 +++++ atst/domain/requests.py | 14 ++++-- .../routes/requests/financial_verification.py | 6 +-- atst/routes/requests/requests_form.py | 8 +-- tests/domain/test_requests.py | 5 +- tests/routes/test_financial_verification.py | 50 +++++++++++-------- tests/routes/test_request_new.py | 6 +-- tests/test_integration.py | 4 +- 8 files changed, 65 insertions(+), 41 deletions(-) diff --git a/atst/domain/authz.py b/atst/domain/authz.py index 506970b8..20bd539f 100644 --- a/atst/domain/authz.py +++ b/atst/domain/authz.py @@ -1,4 +1,5 @@ from atst.domain.workspace_users import WorkspaceUsers +from atst.models.permissions import Permissions class Authorization(object): @@ -10,3 +11,15 @@ class Authorization(object): @classmethod def is_in_workspace(cls, user, workspace): return user in workspace.users + + @classmethod + def can_view_request(cls, user, request): + if ( + Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST + in user.atat_permissions + ): + return True + elif request.creator == user: + return True + + return False diff --git a/atst/domain/requests.py b/atst/domain/requests.py index 57c69d4c..3169a95e 100644 --- a/atst/domain/requests.py +++ b/atst/domain/requests.py @@ -5,13 +5,14 @@ from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.orm.attributes import flag_modified from werkzeug.datastructures import FileStorage +from atst.database import db +from atst.domain.authz import Authorization +from atst.domain.task_orders import TaskOrders +from atst.domain.workspaces import Workspaces from atst.models.request import Request from atst.models.request_status_event import RequestStatusEvent, RequestStatus -from atst.domain.workspaces import Workspaces -from atst.database import db -from atst.domain.task_orders import TaskOrders -from .exceptions import NotFoundError +from .exceptions import NotFoundError, UnauthorizedError def deep_merge(source, destination: dict): @@ -59,12 +60,15 @@ class Requests(object): return False @classmethod - def get(cls, request_id): + def get(cls, user, request_id): try: request = db.session.query(Request).filter_by(id=request_id).one() except NoResultFound: raise NotFoundError("request") + if not Authorization.can_view_request(user, request): + raise UnauthorizedError(user, "get request") + return request @classmethod diff --git a/atst/routes/requests/financial_verification.py b/atst/routes/requests/financial_verification.py index 17137387..fc22f8f4 100644 --- a/atst/routes/requests/financial_verification.py +++ b/atst/routes/requests/financial_verification.py @@ -1,4 +1,4 @@ -from flask import render_template, redirect, url_for +from flask import g, render_template, redirect, url_for from flask import request as http_request from . import requests_bp @@ -15,7 +15,7 @@ def financial_form(data): @requests_bp.route("/requests/verify/", methods=["GET"]) def financial_verification(request_id=None): - request = Requests.get(request_id) + request = Requests.get(g.current_user, request_id) form = financial_form(request.body.get("financial_verification")) return render_template( "requests/financial_verification.html", @@ -28,7 +28,7 @@ def financial_verification(request_id=None): @requests_bp.route("/requests/verify/", methods=["POST"]) def update_financial_verification(request_id): post_data = http_request.form - existing_request = Requests.get(request_id) + existing_request = Requests.get(g.current_user, request_id) form = financial_form(post_data) rerender_args = dict( request_id=request_id, f=form, extended=http_request.args.get("extended") diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index b4af5c73..08a40e20 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -46,7 +46,7 @@ def requests_form_update(screen=1, request_id=None): if request_id: _check_can_view_request(request_id) - request = Requests.get(request_id) if request_id is not None else None + request = Requests.get(g.current_user, request_id) if request_id is not None else None jedi_flow = JEDIRequestFlow( screen, request=request, request_id=request_id, current_user=g.current_user ) @@ -72,7 +72,7 @@ def requests_update(screen=1, request_id=None): screen = int(screen) post_data = http_request.form current_user = g.current_user - existing_request = Requests.get(request_id) if request_id is not None else None + existing_request = Requests.get(g.current_user, request_id) if request_id is not None else None jedi_flow = JEDIRequestFlow( screen, post_data=post_data, @@ -110,7 +110,7 @@ def requests_update(screen=1, request_id=None): @requests_bp.route("/requests/submit/", methods=["POST"]) def requests_submit(request_id=None): - request = Requests.get(request_id) + request = Requests.get(g.current_user, request_id) Requests.submit(request) if request.status == RequestStatus.PENDING_FINANCIAL_VERIFICATION: @@ -122,7 +122,7 @@ def requests_submit(request_id=None): @requests_bp.route("/requests/pending/", methods=["GET"]) def view_pending_request(request_id=None): - request = Requests.get(request_id) + request = Requests.get(g.current_user, request_id) return render_template("requests/view_pending.html", data=request.body) diff --git a/tests/domain/test_requests.py b/tests/domain/test_requests.py index 7d4e4f3e..38a76e93 100644 --- a/tests/domain/test_requests.py +++ b/tests/domain/test_requests.py @@ -21,14 +21,15 @@ def new_request(session): def test_can_get_request(new_request): - request = Requests.get(new_request.id) + request = Requests.get(new_request.creator, new_request.id) assert request.id == new_request.id def test_nonexistent_request_raises(): + a_user = UserFactory.build() with pytest.raises(NotFoundError): - Requests.get(uuid4()) + Requests.get(a_user, uuid4()) def test_new_request_has_started_status(): diff --git a/tests/routes/test_financial_verification.py b/tests/routes/test_financial_verification.py index f8a89691..6163d5b0 100644 --- a/tests/routes/test_financial_verification.py +++ b/tests/routes/test_financial_verification.py @@ -5,7 +5,7 @@ from flask import url_for from atst.eda_client import MockEDAClient from tests.mocks import MOCK_REQUEST, MOCK_USER -from tests.factories import PENumberFactory, RequestFactory +from tests.factories import PENumberFactory, RequestFactory, UserFactory class TestPENumberInForm: @@ -30,12 +30,14 @@ class TestPENumberInForm: monkeypatch.setattr( "atst.forms.financial.FinancialForm.validate", lambda s: True ) + user = UserFactory.create() monkeypatch.setattr( - "atst.domain.auth.get_current_user", lambda *args: MOCK_USER + "atst.domain.auth.get_current_user", lambda *args: user ) + return user - def submit_data(self, client, data, extended=False): - request = RequestFactory.create(body=MOCK_REQUEST.body) + def submit_data(self, client, user, data, extended=False): + request = RequestFactory.create(creator=user, body=MOCK_REQUEST.body) url_kwargs = {"request_id": request.id} if extended: url_kwargs["extended"] = True @@ -47,43 +49,43 @@ class TestPENumberInForm: return response def test_submit_request_form_with_invalid_pe_id(self, monkeypatch, client): - self._set_monkeypatches(monkeypatch) + user = self._set_monkeypatches(monkeypatch) - response = self.submit_data(client, self.required_data) + response = self.submit_data(client, user, self.required_data) assert "We couldn't find that PE number" in response.data.decode() assert response.status_code == 200 def test_submit_request_form_with_unchanged_pe_id(self, monkeypatch, client): - self._set_monkeypatches(monkeypatch) + user = self._set_monkeypatches(monkeypatch) data = dict(self.required_data) data["pe_id"] = MOCK_REQUEST.body["financial_verification"]["pe_id"] - response = self.submit_data(client, data) + response = self.submit_data(client, user, data) assert response.status_code == 302 assert "/workspaces" in response.headers.get("Location") def test_submit_request_form_with_new_valid_pe_id(self, monkeypatch, client): - self._set_monkeypatches(monkeypatch) + user = self._set_monkeypatches(monkeypatch) pe = PENumberFactory.create(number="8675309U", description="sample PE number") data = dict(self.required_data) data["pe_id"] = pe.number - response = self.submit_data(client, data) + response = self.submit_data(client, user, data) assert response.status_code == 302 assert "/workspaces" in response.headers.get("Location") def test_submit_request_form_with_missing_pe_id(self, monkeypatch, client): - self._set_monkeypatches(monkeypatch) + user = self._set_monkeypatches(monkeypatch) data = dict(self.required_data) data["pe_id"] = "" - response = self.submit_data(client, data) + response = self.submit_data(client, user, data) assert "There were some errors" in response.data.decode() assert response.status_code == 200 @@ -91,41 +93,44 @@ class TestPENumberInForm: def test_submit_financial_form_with_invalid_task_order( self, monkeypatch, user_session, client ): - user_session() + user = UserFactory.create() + user_session(user) data = dict(self.required_data) data["pe_id"] = MOCK_REQUEST.body["financial_verification"]["pe_id"] data["task_order_number"] = "1234" - response = self.submit_data(client, data) + response = self.submit_data(client, user, data) assert "enter TO information manually" in response.data.decode() def test_submit_financial_form_with_valid_task_order( self, monkeypatch, user_session, client ): - monkeypatch.setattr("atst.domain.requests.Requests.get", lambda i: MOCK_REQUEST) - user_session() + user = UserFactory.create() + monkeypatch.setattr("atst.domain.requests.Requests.get", lambda *args: MOCK_REQUEST) + user_session(user) data = dict(self.required_data) data["pe_id"] = MOCK_REQUEST.body["financial_verification"]["pe_id"] data["task_order_number"] = MockEDAClient.MOCK_CONTRACT_NUMBER - response = self.submit_data(client, data) + response = self.submit_data(client, user, data) assert "enter TO information manually" not in response.data.decode() def test_submit_extended_financial_form( self, monkeypatch, user_session, client, extended_financial_verification_data ): - request = RequestFactory.create() - monkeypatch.setattr("atst.domain.requests.Requests.get", lambda i: request) + user = UserFactory.create() + request = RequestFactory.create(creator=user) + monkeypatch.setattr("atst.domain.requests.Requests.get", lambda *args: request) monkeypatch.setattr("atst.forms.financial.validate_pe_id", lambda *args: True) user_session() data = {**self.required_data, **extended_financial_verification_data} data["task_order_number"] = "1234567" - response = self.submit_data(client, data, extended=True) + response = self.submit_data(client, user, data, extended=True) assert response.status_code == 302 assert "/projects/new" in response.headers.get("Location") @@ -134,11 +139,12 @@ class TestPENumberInForm: self, monkeypatch, user_session, client, extended_financial_verification_data ): monkeypatch.setattr("atst.forms.financial.validate_pe_id", lambda *args: True) - user_session() + user = UserFactory.create() + user_session(user) data = {**self.required_data, **extended_financial_verification_data} data["task_order_number"] = "1234567" del (data["clin_0001"]) - response = self.submit_data(client, data, extended=True) + response = self.submit_data(client, user, data, extended=True) assert response.status_code == 200 diff --git a/tests/routes/test_request_new.py b/tests/routes/test_request_new.py index 3687900f..1b41eef5 100644 --- a/tests/routes/test_request_new.py +++ b/tests/routes/test_request_new.py @@ -122,7 +122,7 @@ def test_am_poc_causes_poc_to_be_autopopulated(client, user_session): headers={"Content-Type": "application/x-www-form-urlencoded"}, data="am_poc=yes", ) - request = Requests.get(request.id) + request = Requests.get(creator, request.id) assert request.body["primary_poc"]["dodid_poc"] == creator.dod_id @@ -167,7 +167,7 @@ def test_poc_details_can_be_autopopulated_on_new_request(client, user_session): data="am_poc=yes", ) request_id = response.headers["Location"].split("/")[-1] - request = Requests.get(request_id) + request = Requests.get(creator, request_id) assert request.body["primary_poc"]["dodid_poc"] == creator.dod_id @@ -191,7 +191,7 @@ def test_poc_autofill_checks_information_about_you_form_first(client, user_sessi headers={"Content-Type": "application/x-www-form-urlencoded"}, data=urlencode(poc_input), ) - request = Requests.get(request.id) + request = Requests.get(creator, request.id) assert dict_contains( request.body["primary_poc"], { diff --git a/tests/test_integration.py b/tests/test_integration.py index 633f14b1..8b674f9b 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -55,7 +55,7 @@ def test_stepthrough_request_form(user_session, screens, client): # at this point, the real request we made and the mock_request bodies # should be equivalent - assert Requests.get(req_id).body == mock_request.body + assert Requests.get(user, req_id).body == mock_request.body # finish the review and submit step client.post( @@ -63,5 +63,5 @@ def test_stepthrough_request_form(user_session, screens, client): headers={"Content-Type": "application/x-www-form-urlencoded"}, ) - finished_request = Requests.get(req_id) + finished_request = Requests.get(user, req_id) assert finished_request.status == RequestStatus.PENDING_CCPO_APPROVAL From 7040157f2501e2b31f834033cc33a72d25bbd373 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 14:23:08 -0400 Subject: [PATCH 5/9] Formatting fixes --- atst/routes/requests/requests_form.py | 9 +++++++-- tests/routes/test_financial_verification.py | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index 08a40e20..862e3810 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -13,6 +13,7 @@ from atst.forms.data import ( COMPLETION_DATE_RANGES, ) + @requests_bp.context_processor def option_data(): return { @@ -46,7 +47,9 @@ def requests_form_update(screen=1, request_id=None): if request_id: _check_can_view_request(request_id) - request = Requests.get(g.current_user, request_id) if request_id is not None else None + request = ( + Requests.get(g.current_user, request_id) if request_id is not None else None + ) jedi_flow = JEDIRequestFlow( screen, request=request, request_id=request_id, current_user=g.current_user ) @@ -72,7 +75,9 @@ def requests_update(screen=1, request_id=None): screen = int(screen) post_data = http_request.form current_user = g.current_user - existing_request = Requests.get(g.current_user, request_id) if request_id is not None else None + existing_request = ( + Requests.get(g.current_user, request_id) if request_id is not None else None + ) jedi_flow = JEDIRequestFlow( screen, post_data=post_data, diff --git a/tests/routes/test_financial_verification.py b/tests/routes/test_financial_verification.py index 6163d5b0..c35b24bb 100644 --- a/tests/routes/test_financial_verification.py +++ b/tests/routes/test_financial_verification.py @@ -31,9 +31,7 @@ class TestPENumberInForm: "atst.forms.financial.FinancialForm.validate", lambda s: True ) user = UserFactory.create() - monkeypatch.setattr( - "atst.domain.auth.get_current_user", lambda *args: user - ) + monkeypatch.setattr("atst.domain.auth.get_current_user", lambda *args: user) return user def submit_data(self, client, user, data, extended=False): @@ -108,7 +106,9 @@ class TestPENumberInForm: self, monkeypatch, user_session, client ): user = UserFactory.create() - monkeypatch.setattr("atst.domain.requests.Requests.get", lambda *args: MOCK_REQUEST) + monkeypatch.setattr( + "atst.domain.requests.Requests.get", lambda *args: MOCK_REQUEST + ) user_session(user) data = dict(self.required_data) From 6bfc7f77bc986b00d1eda2c891fc0e57cefcd568 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 14:30:20 -0400 Subject: [PATCH 6/9] Add test for new Authorization check --- tests/domain/test_authz.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/domain/test_authz.py diff --git a/tests/domain/test_authz.py b/tests/domain/test_authz.py new file mode 100644 index 00000000..32368cb6 --- /dev/null +++ b/tests/domain/test_authz.py @@ -0,0 +1,20 @@ +from atst.domain.authz import Authorization +from atst.domain.roles import Roles + +from tests.factories import RequestFactory, UserFactory + + +def test_creator_can_view_own_request(): + user = UserFactory.create() + request = RequestFactory.create(creator=user) + assert Authorization.can_view_request(user, request) + + other_user = UserFactory.create() + assert not Authorization.can_view_request(other_user, request) + + +def test_ccpo_user_can_view_request(): + role = Roles.get("ccpo") + ccpo_user = UserFactory.create(atat_role=role) + request = RequestFactory.create() + assert Authorization.can_view_request(ccpo_user, request) From 27b85ce5608030036675663ca8a1d9e2806c37f8 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 14:38:23 -0400 Subject: [PATCH 7/9] Catch DataError when querying for request A `DataError` can be raised if we try to find a request with an id that is not a valid UUID. --- atst/domain/requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atst/domain/requests.py b/atst/domain/requests.py index 3169a95e..28c78ae8 100644 --- a/atst/domain/requests.py +++ b/atst/domain/requests.py @@ -63,7 +63,7 @@ class Requests(object): def get(cls, user, request_id): try: request = db.session.query(Request).filter_by(id=request_id).one() - except NoResultFound: + except (NoResultFound, exc.DataError): raise NotFoundError("request") if not Authorization.can_view_request(user, request): From 457f8de6083a73ff065aa4f59b4ac47aeccb2be9 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 14:39:07 -0400 Subject: [PATCH 8/9] Remove now unnecessary auth check --- atst/routes/requests/requests_form.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index 862e3810..917413b0 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -44,9 +44,6 @@ def requests_form_new(screen): ) @requests_bp.route("/requests/new//", methods=["GET"]) def requests_form_update(screen=1, request_id=None): - if request_id: - _check_can_view_request(request_id) - request = ( Requests.get(g.current_user, request_id) if request_id is not None else None ) @@ -129,17 +126,3 @@ def requests_submit(request_id=None): def view_pending_request(request_id=None): request = Requests.get(g.current_user, request_id) return render_template("requests/view_pending.html", data=request.body) - - -# TODO: generalize this, along with other authorizations, into a policy-pattern -# for authorization in the application -def _check_can_view_request(request_id): - if ( - Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST - in g.current_user.atat_permissions - ): - pass - elif Requests.exists(request_id, g.current_user): - pass - else: - raise UnauthorizedError(g.current_user, "view request {}".format(request_id)) From 622d28dd8b61cac86a2d3fcf45a8bc29787453b4 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 30 Aug 2018 15:02:02 -0400 Subject: [PATCH 9/9] Remove unused imports --- atst/routes/requests/requests_form.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py index 917413b0..1a0353bc 100644 --- a/atst/routes/requests/requests_form.py +++ b/atst/routes/requests/requests_form.py @@ -3,9 +3,7 @@ from flask import g, redirect, render_template, url_for, request as http_request from . import requests_bp from atst.domain.requests import Requests from atst.routes.requests.jedi_request_flow import JEDIRequestFlow -from atst.models.permissions import Permissions from atst.models.request_status_event import RequestStatus -from atst.domain.exceptions import UnauthorizedError from atst.forms.data import ( SERVICE_BRANCHES, ASSISTANCE_ORG_TYPES,