From 6487fe91baa7c653a32cf8bfbe717e99e202b352 Mon Sep 17 00:00:00 2001 From: George Drummond Date: Mon, 20 May 2019 15:18:26 -0400 Subject: [PATCH] Applications users were invited to were not showing in the portfolios sidebar --- atst/domain/portfolios/query.py | 36 ++++++++++++++++++++- atst/routes/portfolios/index.py | 10 +----- atst/routes/portfolios/invitations.py | 2 +- atst/utils/flash.py | 2 +- templates/navigation/global_sidenav.html | 2 +- tests/routes/portfolios/test_invitations.py | 4 +-- tests/test_access.py | 13 -------- 7 files changed, 41 insertions(+), 28 deletions(-) diff --git a/atst/domain/portfolios/query.py b/atst/domain/portfolios/query.py index eb78c56d..f38c70d6 100644 --- a/atst/domain/portfolios/query.py +++ b/atst/domain/portfolios/query.py @@ -2,6 +2,11 @@ from atst.database import db from atst.domain.common import Query from atst.models.portfolio import Portfolio from atst.models.portfolio_role import PortfolioRole, Status as PortfolioRoleStatus +from atst.models.application_role import ( + ApplicationRole, + Status as ApplicationRoleStatus, +) +from atst.models.application import Application class PortfoliosQuery(Query): @@ -9,7 +14,24 @@ class PortfoliosQuery(Query): @classmethod def get_for_user(cls, user): - return ( + granted_applications = ( + db.session.query(Application) + .join(ApplicationRole) + .filter(ApplicationRole.application_id == Application.id) + .filter(ApplicationRole.user_id == user.id) + .filter(ApplicationRole.status == ApplicationRoleStatus.ACTIVE) + .subquery() + ) + + application_portfolios = ( + db.session.query(Portfolio) + .join(Application) + .filter(Portfolio.id == Application.portfolio_id) + .filter(Application.id == granted_applications.c.id) + .all() + ) + + portfolios = ( db.session.query(Portfolio) .join(PortfolioRole) .filter(PortfolioRole.user == user) @@ -17,6 +39,18 @@ class PortfoliosQuery(Query): .all() ) + portfolio_ids = [] + + [portfolio_ids.append(p.id) for p in portfolios] + [portfolio_ids.append(p.id) for p in application_portfolios] + + return ( + db.session.query(Portfolio) + .filter(Portfolio.id.in_(portfolio_ids)) + .order_by(Portfolio.name.desc()) + .all() + ) + @classmethod def create_portfolio_role(cls, user, portfolio, **kwargs): return PortfolioRole(user=user, portfolio=portfolio, **kwargs) diff --git a/atst/routes/portfolios/index.py b/atst/routes/portfolios/index.py index 28bb079e..f0758b93 100644 --- a/atst/routes/portfolios/index.py +++ b/atst/routes/portfolios/index.py @@ -1,6 +1,6 @@ from datetime import date, timedelta -from flask import render_template, request as http_request, g, redirect, url_for +from flask import render_template, request as http_request, g from . import portfolios_bp from atst.domain.reports import Reports @@ -19,14 +19,6 @@ def portfolios(): return render_template("portfolios/blank_slate.html") -@portfolios_bp.route("/portfolios/") -@user_can(Permissions.VIEW_PORTFOLIO, message="view portfolio") -def show_portfolio(portfolio_id): - return redirect( - url_for("applications.portfolio_applications", portfolio_id=portfolio_id) - ) - - @portfolios_bp.route("/portfolios//reports") @user_can(Permissions.VIEW_PORTFOLIO_REPORTS, message="view portfolio reports") def reports(portfolio_id): diff --git a/atst/routes/portfolios/invitations.py b/atst/routes/portfolios/invitations.py index 4c3a53a8..dd1f1c5a 100644 --- a/atst/routes/portfolios/invitations.py +++ b/atst/routes/portfolios/invitations.py @@ -30,7 +30,7 @@ def accept_invitation(portfolio_token): ) return redirect( - url_for("portfolios.show_portfolio", portfolio_id=invite.portfolio.id) + url_for("applications.portfolio_applications", portfolio_id=invite.portfolio.id) ) diff --git a/atst/utils/flash.py b/atst/utils/flash.py index 0a96366a..001293af 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -145,7 +145,7 @@ MESSAGES = { "actions": """ {% from "components/icon.html" import Icon %}
- + {{ Icon('shield') }} {{ "flash.portfolio_home" | translate }} diff --git a/templates/navigation/global_sidenav.html b/templates/navigation/global_sidenav.html index 555b7fdd..e61524ee 100644 --- a/templates/navigation/global_sidenav.html +++ b/templates/navigation/global_sidenav.html @@ -21,7 +21,7 @@ {% if portfolios %} {% for other_portfolio in portfolios|sort(attribute='name') %} {{ SidenavItem(other_portfolio.name, - href=url_for("portfolios.show_portfolio", portfolio_id=other_portfolio.id), + href=url_for("applications.portfolio_applications", portfolio_id=other_portfolio.id), active=(other_portfolio.id | string) == request.view_args.get('portfolio_id') ) }} {% endfor %} diff --git a/tests/routes/portfolios/test_invitations.py b/tests/routes/portfolios/test_invitations.py index 5134957b..9dbf481f 100644 --- a/tests/routes/portfolios/test_invitations.py +++ b/tests/routes/portfolios/test_invitations.py @@ -34,7 +34,7 @@ def test_existing_member_accepts_valid_invite(client, user_session): # user is redirected to the portfolio view assert response.status_code == 302 assert ( - url_for("portfolios.show_portfolio", portfolio_id=invite.portfolio.id) + url_for("applications.portfolio_applications", portfolio_id=invite.portfolio.id) in response.headers["Location"] ) # the one-time use invite is no longer usable @@ -77,7 +77,7 @@ def test_new_member_accepts_valid_invite(monkeypatch, client, user_session): # user is redirected to the portfolio view assert response.status_code == 302 assert ( - url_for("portfolios.show_portfolio", portfolio_id=portfolio.id) + url_for("applications.portfolio_applications", portfolio_id=portfolio.id) in response.headers["Location"] ) # the user has access to the portfolio diff --git a/tests/test_access.py b/tests/test_access.py index 84f1d167..2d7874a4 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -466,19 +466,6 @@ def test_portfolios_revoke_invitation_access(post_url_assert_status): post_url_assert_status(user, url, status) -# portfolios.show_portfolio -def test_portfolios_show_portfolio_access(get_url_assert_status): - ccpo = user_with(PermissionSets.VIEW_PORTFOLIO) - owner = user_with() - rando = user_with() - portfolio = PortfolioFactory.create(owner=owner) - - url = url_for("portfolios.show_portfolio", portfolio_id=portfolio.id) - get_url_assert_status(ccpo, url, 302) - get_url_assert_status(owner, url, 302) - get_url_assert_status(rando, url, 404) - - # task_orders.so_review def test_task_orders_so_review_access(get_url_assert_status): ccpo = UserFactory.create_ccpo()