diff --git a/atst/domain/application_roles.py b/atst/domain/application_roles.py index 826f7f6c..512887c3 100644 --- a/atst/domain/application_roles.py +++ b/atst/domain/application_roles.py @@ -1,8 +1,12 @@ +from itertools import groupby +from typing import List +from uuid import UUID + from sqlalchemy.orm.exc import NoResultFound from atst.database import db from atst.domain.environment_roles import EnvironmentRoles -from atst.models import ApplicationRole, ApplicationRoleStatus +from atst.models import Application, ApplicationRole, ApplicationRoleStatus, Portfolio from .permission_sets import PermissionSets from .exceptions import NotFoundError @@ -92,3 +96,29 @@ class ApplicationRoles(object): db.session.add(application_role) db.session.commit() + + @classmethod + def get_pending_creation(cls) -> List[List[UUID]]: + """ + Returns a list of lists of ApplicationRole IDs. The IDs + should be grouped by user and portfolio. + """ + results = ( + db.session.query(ApplicationRole.id, ApplicationRole.user_id, Portfolio.id) + .join(Application, Application.id == ApplicationRole.application_id) + .join(Portfolio, Portfolio.id == Application.portfolio_id) + .filter(Application.cloud_id.isnot(None)) + .filter(ApplicationRole.deleted == False) + .filter(ApplicationRole.cloud_id.is_(None)) + .filter(ApplicationRole.user_id.isnot(None)) + .filter(ApplicationRole.status == ApplicationRoleStatus.ACTIVE) + ).all() + + groups = [] + keyfunc = lambda pair: (pair[1], pair[2]) + sorted_results = sorted(results, key=keyfunc) + for _, g in groupby(sorted_results, keyfunc): + group = [pair[0] for pair in list(g)] + groups.append(group) + + return groups diff --git a/tests/domain/test_application_roles.py b/tests/domain/test_application_roles.py index ca5c6fc1..9dc42016 100644 --- a/tests/domain/test_application_roles.py +++ b/tests/domain/test_application_roles.py @@ -86,3 +86,70 @@ def test_disable(session): session.refresh(environment_role) assert member_role.status == ApplicationRoleStatus.DISABLED assert environment_role.deleted + + +def test_get_pending_creation(): + + # ready Applications belonging to the same Portfolio + portfolio_one = PortfolioFactory.create() + ready_app = ApplicationFactory.create(cloud_id="123", portfolio=portfolio_one) + ready_app2 = ApplicationFactory.create(cloud_id="321", portfolio=portfolio_one) + + # ready Application belonging to a new Portfolio + ready_app3 = ApplicationFactory.create(cloud_id="567") + unready_app = ApplicationFactory.create() + + # two distinct Users + user_one = UserFactory.create() + user_two = UserFactory.create() + + # Two ApplicationRoles belonging to the same User and + # different Applications. These should sort together because + # they are all under the same portfolio (portfolio_one). + role_one = ApplicationRoleFactory.create( + user=user_one, application=ready_app, status=ApplicationRoleStatus.ACTIVE + ) + role_two = ApplicationRoleFactory.create( + user=user_one, application=ready_app2, status=ApplicationRoleStatus.ACTIVE + ) + + # An ApplicationRole belonging to a different User. This will + # be included but sort separately because it belongs to a + # different user. + role_three = ApplicationRoleFactory.create( + user=user_two, application=ready_app, status=ApplicationRoleStatus.ACTIVE + ) + + # An ApplicationRole belonging to one of the existing users + # but under a different portfolio. It will sort separately. + role_four = ApplicationRoleFactory.create( + user=user_one, application=ready_app3, status=ApplicationRoleStatus.ACTIVE + ) + + # This ApplicationRole will not be in the results because its + # application is not ready (implicitly, its cloud_id is not + # set.) + ApplicationRoleFactory.create( + user=UserFactory.create(), + application=unready_app, + status=ApplicationRoleStatus.ACTIVE, + ) + + # This ApplicationRole will not be in the results because it + # does not have a user associated. + ApplicationRoleFactory.create( + user=None, application=ready_app, status=ApplicationRoleStatus.ACTIVE, + ) + + # This ApplicationRole will not be in the results because its + # status is not ACTIVE. + ApplicationRoleFactory.create( + user=UserFactory.create(), + application=unready_app, + status=ApplicationRoleStatus.DISABLED, + ) + + app_ids = ApplicationRoles.get_pending_creation() + expected_ids = [[role_one.id, role_two.id], [role_three.id], [role_four.id]] + # Sort them to produce the same order. + assert sorted(app_ids) == sorted(expected_ids)