def create_or_update_new_application_step_1(portfolio_id=None, application_id=None): form = get_new_application_form({**http_request.form}, NameAndDescriptionForm, application_id) if form.validate(): application = None if application_id: application = Applications.get(application_id) application = Applications.update(application, form.data) flash("application_updated", application_name=application.name) else: portfolio = Portfolios.get_for_update(portfolio_id) application = Applications.create(g.current_user, portfolio, **form.data) flash("application_created", application_name=application.name) return redirect( url_for( "applications.update_new_application_step_2", application_id=application.id, )) else: return ( render_new_application_form( "applications/new/step_1.html", NameAndDescriptionForm, portfolio_id, application_id, form, ), 400, )
def handle_create_member(application_id, form_data): application = Applications.get(application_id) form = NewMemberForm(form_data) if form.validate(): try: invite = Applications.invite( application=application, inviter=g.current_user, user_data=form.user_data.data, permission_sets_names=form.data["permission_sets"], environment_roles_data=form.environment_roles.data, ) send_application_invitation( invitee_email=invite.email, inviter_name=g.current_user.full_name, token=invite.token, ) flash("new_application_member", user_name=invite.first_name) except AlreadyExistsError: return render_template( "error.html", message="There was an error processing your request.") else: pass
def test_create_does_not_duplicate_names_within_portfolio(): portfolio = PortfolioFactory.create() name = "An Awesome Application" assert Applications.create(portfolio.owner, portfolio, name, "") with pytest.raises(AlreadyExistsError): Applications.create(portfolio.owner, portfolio, name, "")
def test_can_only_update_name_and_description(): owner = UserFactory.create() portfolio = PortfolioFactory.create( owner=owner, applications=[{ "name": "Application 1", "description": "a application", "environments": [{ "name": "dev" }], }], ) application = Applications.get(portfolio.applications[0].id) env_name = application.environments[0].name Applications.update( application, { "name": "New Name", "description": "a new application", "environment_name": "prod", }, ) assert application.name == "New Name" assert application.description == "a new application" assert len(application.environments) == 1 assert application.environments[0].name == env_name
def test_get_portfolio_events_includes_app_and_env_events(): owner = UserFactory.create() # add portfolio level events portfolio = PortfolioFactory.create(owner=owner) portfolio_events = AuditLog.get_portfolio_events(portfolio) # add application level events application = ApplicationFactory.create(portfolio=portfolio) Applications.update(application, {"name": "Star Cruiser"}) app_role = ApplicationRoleFactory.create(application=application) app_invite = ApplicationInvitationFactory.create(role=app_role) portfolio_and_app_events = AuditLog.get_portfolio_events(portfolio) assert len(portfolio_events) < len(portfolio_and_app_events) # add environment level events env = EnvironmentFactory.create(application=application) env_role = EnvironmentRoleFactory.create(environment=env, application_role=app_role) portfolio_app_and_env_events = AuditLog.get_portfolio_events(portfolio) assert len(portfolio_and_app_events) < len(portfolio_app_and_env_events) resource_types = [event.resource_type for event in portfolio_app_and_env_events] assert "application" in resource_types assert "application_role" in resource_types assert "application_invitation" in resource_types assert "environment" in resource_types assert "environment_role" in resource_types
def test_get_application(): app = ApplicationFactory.create() assert Applications.get(app.id) == app assert Applications.get(app.id, portfolio_id=app.portfolio_id) == app with pytest.raises(NotFoundError): # make the uuid a string like you'd get from a route rando_id = str(uuid4()) Applications.get(app.id, portfolio_id=rando_id)
def test_update_does_not_duplicate_names_within_portfolio(): portfolio = PortfolioFactory.create() name = "An Awesome Application" application = ApplicationFactory.create(portfolio=portfolio, name=name) dupe_application = ApplicationFactory.create(portfolio=portfolio) with pytest.raises(AlreadyExistsError): Applications.update(dupe_application, {"name": name})
def delete(application_id): application = Applications.get(application_id) Applications.delete(application) flash("application_deleted", application_name=application.name) return redirect( url_for("applications.portfolio_applications", portfolio_id=application.portfolio_id))
def test_scoped_portfolio_returns_all_applications_for_portfolio_owner( portfolio, portfolio_owner): for _ in range(5): Applications.create( portfolio.owner, portfolio, "My Application", "My application", ["dev", "staging", "prod"], ) scoped_portfolio = Portfolios.get(portfolio_owner, portfolio.id) assert len(scoped_portfolio.applications) == 5 assert len(scoped_portfolio.applications[0].environments) == 3
def update(application_id): application = Applications.get(application_id) form = NameAndDescriptionForm(http_request.form) if form.validate(): application_data = form.data Applications.update(application, application_data) return redirect( url_for( "applications.portfolio_applications", portfolio_id=application.portfolio_id, )) else: return render_settings_page(application=application, application_form=form)
def handle_update_member(application_id, application_role_id, form_data): app_role = ApplicationRoles.get_by_id(application_role_id) application = Applications.get(application_id) existing_env_roles_data = filter_env_roles_form_data( app_role, application.environments) form = UpdateMemberForm(formdata=form_data, environment_roles=existing_env_roles_data) if form.validate(): try: ApplicationRoles.update_permission_sets( app_role, form.data["permission_sets"]) for env_role in form.environment_roles: environment = Environments.get(env_role.environment_id.data) new_role = None if env_role.disabled.data else env_role.data[ "role"] Environments.update_env_role(environment, app_role, new_role) flash("application_member_updated", user_name=app_role.user_name) except GeneralCSPException as exc: log_error(exc) flash( "application_member_update_error", user_name=app_role.user_name, ) else: pass
def test_invite(): application = ApplicationFactory.create() env1 = EnvironmentFactory.create(application=application) env2 = EnvironmentFactory.create(application=application) user_data = UserFactory.dictionary() permission_sets_names = [PermissionSets.EDIT_APPLICATION_TEAM] invitation = Applications.invite( application=application, inviter=application.portfolio.owner, user_data=user_data, permission_sets_names=permission_sets_names, environment_roles_data=[ { "environment_id": env1.id, "role": CSPRole.BASIC_ACCESS.value }, { "environment_id": env2.id, "role": None }, ], ) member_role = invitation.role assert invitation.dod_id == user_data["dod_id"] # view application AND edit application team assert len(member_role.permission_sets) == 2 env_roles = member_role.environment_roles assert len(env_roles) == 1 assert env_roles[0].environment == env1
def test_for_user(): user = UserFactory.create() portfolio = PortfolioFactory.create() for _x in range(4): ApplicationFactory.create(portfolio=portfolio) ApplicationRoleFactory.create( application=portfolio.applications[0], user=user, status=ApplicationRoleStatus.ACTIVE, ) ApplicationRoleFactory.create( application=portfolio.applications[1], user=user, status=ApplicationRoleStatus.ACTIVE, ) ApplicationRoleFactory.create( application=portfolio.applications[2], user=user, status=ApplicationRoleStatus.PENDING, ) assert len(portfolio.applications) == 4 user_applications = Applications.for_user(user, portfolio) assert len(user_applications) == 2
def settings(application_id): application = Applications.get(application_id) return render_settings_page( application=application, active_toggler=http_request.args.get("active_toggler"), active_toggler_section=http_request.args.get("active_toggler_section"), )
def applications(self): can_view_all_applications = Authorization.has_portfolio_permission( self.user, self.resource, Permissions.VIEW_APPLICATION) if can_view_all_applications: return self.resource.applications else: return Applications.for_user(self.user, self.resource)
def test_scoped_portfolio_for_admin_missing_view_apps_perms( portfolio_owner, portfolio): Applications.create( portfolio.owner, portfolio, "My Application 2", "My application 2", ["dev", "staging", "prod"], ) restricted_admin = UserFactory.create() PortfolioRoleFactory.create( portfolio=portfolio, user=restricted_admin, permission_sets=[PermissionSets.get(PermissionSets.VIEW_PORTFOLIO)], ) scoped_portfolio = Portfolios.get(restricted_admin, portfolio.id) assert scoped_portfolio.id == portfolio.id assert len(portfolio.applications) == 1 assert len(scoped_portfolio.applications) == 0
def test_create_application_with_multiple_environments(): portfolio = PortfolioFactory.create() application = Applications.create(portfolio.owner, portfolio, "My Test Application", "Test", ["dev", "prod"]) assert application.portfolio == portfolio assert application.name == "My Test Application" assert application.description == "Test" assert sorted(e.name for e in application.environments) == ["dev", "prod"]
def test_delete_application(session): app = ApplicationFactory.create() app_role = ApplicationRoleFactory.create(user=UserFactory.create(), application=app) env1 = EnvironmentFactory.create(application=app) env2 = EnvironmentFactory.create(application=app) assert not app.deleted assert not env1.deleted assert not env2.deleted assert not app_role.deleted Applications.delete(app) assert app.deleted assert env1.deleted assert env2.deleted assert app_role.deleted # changes are flushed assert not session.dirty
def test_scoped_portfolio_returns_all_applications_for_portfolio_admin( portfolio, portfolio_owner): for _ in range(5): Applications.create( portfolio.owner, portfolio, "My Application", "My application", ["dev", "staging", "prod"], ) admin = UserFactory.create() perm_sets = get_all_portfolio_permission_sets() PortfolioRoleFactory.create(user=admin, portfolio=portfolio, permission_sets=perm_sets) scoped_portfolio = Portfolios.get(admin, portfolio.id) assert len(scoped_portfolio.applications) == 5 assert len(scoped_portfolio.applications[0].environments) == 3
def handle_update_application(form, application_id=None, portfolio_id=None): if form.validate(): application = None try: if application_id: application = Applications.get(application_id) application = Applications.update(application, form.data) flash("application_updated", application_name=application.name) else: portfolio = Portfolios.get_for_update(portfolio_id) application = Applications.create(g.current_user, portfolio, **form.data) flash("application_created", application_name=application.name) return application except AlreadyExistsError: flash("application_name_error", name=form.data["name"]) return False
def test_invite_to_nonexistent_environment(): application = ApplicationFactory.create() env1 = EnvironmentFactory.create(application=application) user_data = UserFactory.dictionary() with pytest.raises(NotFoundError): Applications.invite( application=application, inviter=application.portfolio.owner, user_data=user_data, environment_roles_data=[ { "environment_id": env1.id, "role": CSPRole.BASIC_ACCESS.value }, { "environment_id": uuid4(), "role": CSPRole.BASIC_ACCESS.value }, ], )
def test_get_application_events(): # add in some portfolio level events portfolio = PortfolioFactory.create() Portfolios.update(portfolio, {"name": "New Name"}) # add app level events application = ApplicationFactory.create(portfolio=portfolio) Applications.update(application, {"name": "Star Cruiser"}) app_role = ApplicationRoleFactory.create(application=application) app_invite = ApplicationInvitationFactory.create(role=app_role) env = EnvironmentFactory.create(application=application) env_role = EnvironmentRoleFactory.create(environment=env, application_role=app_role) # add rando app rando_app = ApplicationFactory.create(portfolio=portfolio) events = AuditLog.get_application_events(application) for event in events: assert event.application_id == application.id assert not event.application_id == rando_app.id resource_types = [event.resource_type for event in events] assert "portfolio" not in resource_types
def view_new_application_step_3(application_id): application = Applications.get(application_id) members = get_members_data(application) new_member_form = get_new_member_form(application) return render_template( "applications/new/step_3.html", application_id=application_id, application=application, members=members, new_member_form=new_member_form, )
def update_new_application_step_2(application_id): form = get_new_application_form({**http_request.form}, EnvironmentsForm, application_id) if form.validate(): application = Applications.get(application_id) application = Applications.update(application, form.data) flash("application_environments_updated") return redirect( url_for( "applications.update_new_application_step_3", application_id=application_id, )) else: return ( render_new_application_form( "applications/new/step_2.html", EnvironmentsForm, application_id=application_id, form=form, ), 400, )
def view_new_application_step_2(application_id): application = Applications.get(application_id) render_args = { "form": EnvironmentsForm( data={ "environment_names": [environment.name for environment in application.environments] }), "application": application, } return render_template("applications/new/step_2.html", **render_args)
def render_new_application_form(template, form_class, portfolio_id=None, application_id=None, form=None): render_args = {"application_id": application_id} if application_id: application = Applications.get(application_id) render_args["form"] = form or form_class(obj=application) render_args["application"] = application else: render_args["form"] = form or form_class() return render_template(template, **render_args)
def test_portfolio_owner_can_view_environments(): owner = UserFactory.create() portfolio = PortfolioFactory.create( owner=owner, applications=[{ "environments": [{ "name": "dev" }, { "name": "prod" }] }], ) application = Applications.get(portfolio.applications[0].id) assert len(application.environments) == 2
def update(application_id): application = Applications.get(application_id) form = NameAndDescriptionForm(http_request.form) updated_application = handle_update_application(form, application_id) if updated_application: return redirect( url_for( "applications.portfolio_applications", portfolio_id=application.portfolio_id, )) else: return ( render_settings_page(application=application, show_flash=True), 400, )
def new_environment(application_id): application = Applications.get(application_id) env_form = EditEnvironmentForm(formdata=http_request.form) environment = handle_update_environment(form=env_form, application=application) if environment: return redirect( url_for( "applications.settings", application_id=application.id, fragment="application-environments", _anchor="application-environments", )) else: return (render_settings_page(application=application, show_flash=True), 400)
def test_application_settings(client, user_session): portfolio = PortfolioFactory.create() application = Applications.create( portfolio.owner, portfolio, "Snazzy Application", "A new application for me and my friends", {"env1", "env2"}, ) user_session(portfolio.owner) response = client.get( url_for("applications.settings", application_id=application.id)) assert response.status_code == 200 # the assertion below is a quick check to prevent regressions -- this ensures that # the correct URL for creating a member for an application is _somewhere_ in # the settings page. assert (url_for("applications.create_member", application_id=application.id) in response.data.decode())