Merge pull request #802 from dod-ccpo/accept-application-invite
Accept application invite
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from atst.database import db
|
||||
from atst.models.application_role import ApplicationRole
|
||||
from atst.models import ApplicationRole, ApplicationRoleStatus
|
||||
from atst.domain.permission_sets import PermissionSets
|
||||
|
||||
|
||||
@@ -21,3 +21,10 @@ class ApplicationRoles(object):
|
||||
db.session.commit()
|
||||
|
||||
return application_role
|
||||
|
||||
@classmethod
|
||||
def enable(cls, role):
|
||||
role.status = ApplicationRoleStatus.ACTIVE
|
||||
|
||||
db.session.add(role)
|
||||
db.session.commit()
|
||||
|
@@ -6,9 +6,7 @@ from atst.domain.application_roles import ApplicationRoles
|
||||
from atst.domain.environments import Environments
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
from atst.domain.users import Users
|
||||
from atst.models.application import Application
|
||||
from atst.models.environment import Environment
|
||||
from atst.models.environment_role import EnvironmentRole
|
||||
from atst.models import Application, ApplicationRole, ApplicationRoleStatus
|
||||
|
||||
|
||||
class Applications(BaseDomainClass):
|
||||
@@ -31,10 +29,11 @@ class Applications(BaseDomainClass):
|
||||
def for_user(self, user, portfolio):
|
||||
return (
|
||||
db.session.query(Application)
|
||||
.join(Environment)
|
||||
.join(EnvironmentRole)
|
||||
.join(ApplicationRole)
|
||||
.filter(Application.portfolio_id == portfolio.id)
|
||||
.filter(EnvironmentRole.user_id == user.id)
|
||||
.filter(ApplicationRole.application_id == Application.id)
|
||||
.filter(ApplicationRole.user_id == user.id)
|
||||
.filter(ApplicationRole.status == ApplicationRoleStatus.ACTIVE)
|
||||
.all()
|
||||
)
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
from atst.domain.authz import Authorization
|
||||
from atst.models.permissions import Permissions
|
||||
from atst.domain.applications import Applications
|
||||
from atst.domain.environments import Environments
|
||||
|
||||
|
||||
class ScopedResource(object):
|
||||
@@ -35,31 +34,6 @@ class ScopedPortfolio(ScopedResource):
|
||||
)
|
||||
|
||||
if can_view_all_applications:
|
||||
applications = self.resource.applications
|
||||
return self.resource.applications
|
||||
else:
|
||||
applications = Applications.for_user(self.user, self.resource)
|
||||
|
||||
return [
|
||||
ScopedApplication(self.user, application) for application in applications
|
||||
]
|
||||
|
||||
|
||||
class ScopedApplication(ScopedResource):
|
||||
"""
|
||||
An object that obeys the same API as a Portfolio, but with the added
|
||||
functionality that it only returns sub-resources (environments)
|
||||
that the given user is allowed to see.
|
||||
"""
|
||||
|
||||
@property
|
||||
def environments(self):
|
||||
can_view_all_environments = Authorization.has_portfolio_permission(
|
||||
self.user, self.resource.portfolio, Permissions.VIEW_ENVIRONMENT
|
||||
)
|
||||
|
||||
if can_view_all_environments:
|
||||
environments = self.resource.environments
|
||||
else:
|
||||
environments = Environments.for_user(self.user, self.resource)
|
||||
|
||||
return environments
|
||||
return Applications.for_user(self.user, self.resource)
|
||||
|
@@ -62,7 +62,13 @@ class ApplicationRole(
|
||||
|
||||
@property
|
||||
def history(self):
|
||||
return self.get_changes()
|
||||
previous_state = self.get_changes()
|
||||
change_set = {}
|
||||
if "status" in previous_state:
|
||||
from_status = previous_state["status"][0].value
|
||||
to_status = self.status.value
|
||||
change_set["status"] = [from_status, to_status]
|
||||
return change_set
|
||||
|
||||
def has_permission_set(self, perm_set_name):
|
||||
return first_or_none(
|
||||
|
@@ -6,6 +6,7 @@ from . import index
|
||||
from . import new
|
||||
from . import settings
|
||||
from . import team
|
||||
from . import invitations
|
||||
from atst.domain.environment_roles import EnvironmentRoles
|
||||
from atst.domain.exceptions import UnauthorizedError
|
||||
from atst.domain.authz.decorator import user_can_access_decorator as user_can
|
||||
|
@@ -5,7 +5,21 @@ from atst.domain.authz.decorator import user_can_access_decorator as user_can
|
||||
from atst.models.permissions import Permissions
|
||||
|
||||
|
||||
def has_portfolio_applications(_user, portfolio=None, **_kwargs):
|
||||
"""
|
||||
If the portfolio exists and the user has access to applications
|
||||
within the scoped portfolio, the user has access to the
|
||||
portfolio landing page.
|
||||
"""
|
||||
if portfolio and portfolio.applications:
|
||||
return True
|
||||
|
||||
|
||||
@applications_bp.route("/portfolios/<portfolio_id>/applications")
|
||||
@user_can(Permissions.VIEW_APPLICATION, message="view portfolio applications")
|
||||
@user_can(
|
||||
Permissions.VIEW_APPLICATION,
|
||||
override=has_portfolio_applications,
|
||||
message="view portfolio applications",
|
||||
)
|
||||
def portfolio_applications(portfolio_id):
|
||||
return render_template("portfolios/applications/index.html")
|
||||
|
16
atst/routes/applications/invitations.py
Normal file
16
atst/routes/applications/invitations.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from flask import redirect, url_for, g
|
||||
|
||||
from . import applications_bp
|
||||
from atst.domain.invitations import ApplicationInvitations
|
||||
|
||||
|
||||
@applications_bp.route("/applications/invitations/<token>", methods=["GET"])
|
||||
def accept_invitation(token):
|
||||
invite = ApplicationInvitations.accept(g.current_user, token)
|
||||
|
||||
return redirect(
|
||||
url_for(
|
||||
"applications.portfolio_applications",
|
||||
portfolio_id=invite.application.portfolio_id,
|
||||
)
|
||||
)
|
Reference in New Issue
Block a user