From 2d99b5cfc562082acd83a7fef73d6a801f93cd1f Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 6 May 2019 11:33:33 -0400 Subject: [PATCH] Permission-check for templates accounts for all permission levels. `user_can` function built for Jinja template contexts should check application, portfolio, and atat level permissions depending on what resources are available on `g`. --- atst/utils/context_processors.py | 28 ++++++++++------- tests/utils/test_context_processors.py | 43 +++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/atst/utils/context_processors.py b/atst/utils/context_processors.py index 946e62a8..243de728 100644 --- a/atst/utils/context_processors.py +++ b/atst/utils/context_processors.py @@ -5,16 +5,16 @@ from sqlalchemy.orm.exc import NoResultFound from atst.database import db from atst.domain.authz import Authorization +from atst.domain.portfolios.scopes import ScopedPortfolio from atst.models import ( Application, Environment, + Permissions, Portfolio, PortfolioInvitation, PortfolioRole, TaskOrder, ) -from atst.models.permissions import Permissions -from atst.domain.portfolios.scopes import ScopedPortfolio def get_resources_from_context(view_args): @@ -81,15 +81,21 @@ def assign_resources(view_args): g.task_order = resource -def portfolio(): - def user_can(permission): - if g.portfolio: - return Authorization.has_portfolio_permission( - g.current_user, g.portfolio, permission - ) - return False +def user_can_view(permission): + if g.application: + return Authorization.has_application_permission( + g.current_user, g.application, permission + ) + elif g.portfolio: + return Authorization.has_portfolio_permission( + g.current_user, g.portfolio, permission + ) + else: + return Authorization.has_atat_permission(g.current_user, permission) - if not g.portfolio is None: + +def portfolio(): + if g.portfolio is not None: active_task_orders = [ task_order for task_order in g.portfolio.task_orders if task_order.is_active ] @@ -106,7 +112,7 @@ def portfolio(): return { "portfolio": g.portfolio, "permissions": Permissions, - "user_can": user_can, + "user_can": user_can_view, "funding_end_date": funding_end_date, "funded": funded, } diff --git a/tests/utils/test_context_processors.py b/tests/utils/test_context_processors.py index 4e810e03..722cdd4a 100644 --- a/tests/utils/test_context_processors.py +++ b/tests/utils/test_context_processors.py @@ -1,4 +1,8 @@ -from atst.utils.context_processors import get_resources_from_context +import pytest + +from atst.domain.permission_sets import PermissionSets +from atst.models import Permissions +from atst.utils.context_processors import get_resources_from_context, user_can_view from tests.factories import * @@ -22,3 +26,40 @@ def test_get_resources_from_context(): portfolio, task_order, ) + + +@pytest.fixture +def set_g(request_ctx): + def _set_g(attr, val): + setattr(request_ctx.g, attr, val) + + yield _set_g + + setattr(request_ctx.g, "application", None) + setattr(request_ctx.g, "portfolio", None) + setattr(request_ctx.g, "current_user", None) + + +def test_user_can_view(set_g): + owner = UserFactory.create() + app_user = UserFactory.create() + rando = UserFactory.create() + + portfolio = PortfolioFactory.create(owner=owner) + application = ApplicationFactory.create(portfolio=portfolio) + ApplicationRoleFactory.create( + user=app_user, + application=application, + permission_sets=PermissionSets.get_many([PermissionSets.VIEW_APPLICATION]), + ) + + set_g("portfolio", portfolio) + set_g("application", application) + set_g("current_user", owner) + assert user_can_view(Permissions.VIEW_APPLICATION) + + set_g("current_user", app_user) + assert user_can_view(Permissions.VIEW_APPLICATION) + + set_g("current_user", rando) + assert not user_can_view(Permissions.VIEW_APPLICATION)