Merge pull request #809 from dod-ccpo/resource-finder

Resource finder
This commit is contained in:
dandds
2019-05-10 06:07:45 -04:00
committed by GitHub
9 changed files with 191 additions and 83 deletions

View File

@@ -33,6 +33,8 @@ from atst.queue import queue
from logging.config import dictConfig
from atst.utils.logging import JsonFormatter, RequestContextFilter
from atst.utils.context_processors import assign_resources
ENV = os.getenv("FLASK_ENV", "dev")
@@ -83,6 +85,10 @@ def make_app(config):
apply_authentication(app)
set_default_headers(app)
@app.before_request
def _set_resources():
assign_resources(request.view_args)
return app
@@ -107,6 +113,9 @@ def make_flask_callbacks(app):
@app.after_request
def _cleanup(response):
g.current_user = None
g.portfolio = None
g.application = None
g.task_order = None
return response

View File

@@ -3,39 +3,15 @@ from functools import wraps
from flask import g, current_app as app, request
from . import user_can_access
from atst.domain.portfolios import Portfolios
from atst.domain.task_orders import TaskOrders
from atst.domain.applications import Applications
from atst.domain.environments import Environments
from atst.domain.invitations import PortfolioInvitations
from atst.domain.exceptions import UnauthorizedError
def check_access(permission, message, override, *args, **kwargs):
access_args = {"message": message}
if "application_id" in kwargs:
application = Applications.get(kwargs["application_id"])
access_args["application"] = application
access_args["portfolio"] = application.portfolio
elif "task_order_id" in kwargs:
task_order = TaskOrders.get(kwargs["task_order_id"])
access_args["portfolio"] = task_order.portfolio
elif "token" in kwargs:
invite = PortfolioInvitations._get(kwargs["token"])
access_args["portfolio"] = invite.role.portfolio
elif "portfolio_id" in kwargs:
access_args["portfolio"] = Portfolios.get(
g.current_user, kwargs["portfolio_id"]
)
elif "environment_id" in kwargs:
environment = Environments.get(kwargs["environment_id"])
access_args["application"] = environment.application
access_args["portfolio"] = environment.application.portfolio
access_args = {
"message": message,
"portfolio": g.portfolio,
"application": g.application,
}
if override is not None and override(g.current_user, **access_args, **kwargs):
return True

View File

@@ -19,9 +19,9 @@ def send_invite_email(owner_name, token, new_member_email):
)
@portfolios_bp.route("/portfolios/invitations/<token>", methods=["GET"])
def accept_invitation(token):
invite = PortfolioInvitations.accept(g.current_user, token)
@portfolios_bp.route("/portfolios/invitations/<portfolio_token>", methods=["GET"])
def accept_invitation(portfolio_token):
invite = PortfolioInvitations.accept(g.current_user, portfolio_token)
for task_order in invite.portfolio.task_orders:
if g.current_user in task_order.officers:
@@ -35,11 +35,11 @@ def accept_invitation(token):
@portfolios_bp.route(
"/portfolios/<portfolio_id>/invitations/<token>/revoke", methods=["POST"]
"/portfolios/<portfolio_id>/invitations/<portfolio_token>/revoke", methods=["POST"]
)
@user_can(Permissions.EDIT_PORTFOLIO_USERS, message="revoke invitation")
def revoke_invitation(portfolio_id, token):
PortfolioInvitations.revoke(token)
def revoke_invitation(portfolio_id, portfolio_token):
PortfolioInvitations.revoke(portfolio_token)
return redirect(
url_for(
@@ -52,11 +52,11 @@ def revoke_invitation(portfolio_id, token):
@portfolios_bp.route(
"/portfolios/<portfolio_id>/invitations/<token>/resend", methods=["POST"]
"/portfolios/<portfolio_id>/invitations/<portfolio_token>/resend", methods=["POST"]
)
@user_can(Permissions.EDIT_PORTFOLIO_USERS, message="resend invitation")
def resend_invitation(portfolio_id, token):
invite = PortfolioInvitations.resend(g.current_user, token)
def resend_invitation(portfolio_id, portfolio_token):
invite = PortfolioInvitations.resend(g.current_user, portfolio_token)
send_invite_email(g.current_user.full_name, invite.token, invite.email)
flash("resend_portfolio_invitation", user_name=invite.user_name)
return redirect(

View File

@@ -1,33 +1,51 @@
from operator import attrgetter
from flask import request as http_request, g
from flask import g
from sqlalchemy.orm.exc import NoResultFound
from atst.database import db
from atst.domain.authz import Authorization
from atst.models import Application, Environment, Portfolio, TaskOrder
from atst.models.permissions import Permissions
from atst.domain.portfolios.scopes import ScopedPortfolio
from atst.models import (
Application,
Environment,
Permissions,
Portfolio,
PortfolioInvitation,
PortfolioRole,
TaskOrder,
)
def get_portfolio_from_context(view_args):
def get_resources_from_context(view_args):
query = None
if "portfolio_id" in view_args:
if "portfolio_token" in view_args:
query = (
db.session.query(Portfolio)
.join(PortfolioRole, PortfolioRole.portfolio_id == Portfolio.id)
.join(
PortfolioInvitation,
PortfolioInvitation.portfolio_role_id == PortfolioRole.id,
)
.filter(PortfolioInvitation.token == view_args["portfolio_token"])
)
elif "portfolio_id" in view_args:
query = db.session.query(Portfolio).filter(
Portfolio.id == view_args["portfolio_id"]
)
elif "application_id" in view_args:
query = (
db.session.query(Portfolio)
db.session.query(Portfolio, Application)
.join(Application, Application.portfolio_id == Portfolio.id)
.filter(Application.id == view_args["application_id"])
)
elif "environment_id" in view_args:
query = (
db.session.query(Portfolio)
db.session.query(Portfolio, Application)
.join(Application, Application.portfolio_id == Portfolio.id)
.join(Environment, Environment.application_id == Application.id)
.filter(Environment.id == view_args["environment_id"])
@@ -35,33 +53,51 @@ def get_portfolio_from_context(view_args):
elif "task_order_id" in view_args:
query = (
db.session.query(Portfolio)
db.session.query(Portfolio, TaskOrder)
.join(TaskOrder, TaskOrder.portfolio_id == Portfolio.id)
.filter(TaskOrder.id == view_args["task_order_id"])
)
if query:
try:
portfolio = query.one()
return ScopedPortfolio(g.current_user, portfolio)
return query.only_return_tuples(True).one()
except NoResultFound:
raise NotFoundError("portfolio")
def assign_resources(view_args):
g.portfolio = None
g.application = None
g.task_order = None
resources = get_resources_from_context(view_args)
if resources:
for resource in resources:
if isinstance(resource, Portfolio):
g.portfolio = ScopedPortfolio(g.current_user, resource)
elif isinstance(resource, Application):
g.application = resource
elif isinstance(resource, TaskOrder):
g.task_order = resource
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)
def portfolio():
portfolio = get_portfolio_from_context(http_request.view_args)
def user_can(permission):
if portfolio:
return Authorization.has_portfolio_permission(
g.current_user, portfolio, permission
)
return False
if not portfolio is None:
if g.portfolio is not None:
active_task_orders = [
task_order for task_order in portfolio.task_orders if task_order.is_active
task_order for task_order in g.portfolio.task_orders if task_order.is_active
]
funding_end_date = (
sorted(active_task_orders, key=attrgetter("end_date"))[-1].end_date
@@ -74,9 +110,9 @@ def portfolio():
funded = None
return {
"portfolio": portfolio,
"portfolio": g.portfolio,
"permissions": Permissions,
"user_can": user_can,
"user_can": user_can_view,
"funding_end_date": funding_end_date,
"funded": funded,
}