Handle setting no access for user environment roles:

- use constant for no access string
- update no access constant
- update language and permissions for rendering remove app member button
This commit is contained in:
dandds 2019-05-15 09:27:07 -04:00
parent 0dc0397702
commit 815632ed00
13 changed files with 47 additions and 33 deletions

View File

@ -2,18 +2,18 @@ from flask_wtf import FlaskForm
from wtforms.fields import FieldList, FormField, HiddenField, RadioField, StringField from wtforms.fields import FieldList, FormField, HiddenField, RadioField, StringField
from .forms import BaseForm from .forms import BaseForm
from .data import ENV_ROLES from .data import ENV_ROLES, ENV_ROLE_NO_ACCESS as NO_ACCESS
class MemberForm(FlaskForm): class MemberForm(FlaskForm):
user_id = HiddenField() user_id = HiddenField()
user_name = StringField() user_name = StringField()
role_name = RadioField(choices=ENV_ROLES, default="no_access") role_name = RadioField(choices=ENV_ROLES, default=NO_ACCESS)
@property @property
def data(self): def data(self):
_data = super().data _data = super().data
if "role_name" in _data and _data["role_name"] == "no_access": if "role_name" in _data and _data["role_name"] == NO_ACCESS:
_data["role_name"] = None _data["role_name"] = None
return _data return _data

View File

@ -217,6 +217,7 @@ REQUIRED_DISTRIBUTIONS = [
("other", "Other as necessary"), ("other", "Other as necessary"),
] ]
ENV_ROLE_NO_ACCESS = "No Access"
ENV_ROLES = [(role.value, role.value) for role in CSPRole] + [ ENV_ROLES = [(role.value, role.value) for role in CSPRole] + [
("no_access", "No access") (ENV_ROLE_NO_ACCESS, "No access")
] ]

View File

@ -3,7 +3,7 @@ from wtforms.fields import FormField, FieldList, HiddenField, RadioField, String
from wtforms.validators import Required from wtforms.validators import Required
from .application_member import EnvironmentForm as BaseEnvironmentForm from .application_member import EnvironmentForm as BaseEnvironmentForm
from .data import ENV_ROLES from .data import ENV_ROLES, ENV_ROLE_NO_ACCESS as NO_ACCESS
from .forms import BaseForm from .forms import BaseForm
from atst.forms.fields import SelectField from atst.forms.fields import SelectField
from atst.domain.permission_sets import PermissionSets from atst.domain.permission_sets import PermissionSets
@ -18,6 +18,13 @@ class EnvironmentForm(BaseEnvironmentForm):
filters=[lambda x: None if x == "None" else x], filters=[lambda x: None if x == "None" else x],
) )
@property
def data(self):
_data = super().data
if "role" in _data and _data["role"] == NO_ACCESS:
_data["role"] = None
return _data
class PermissionsForm(FlaskForm): class PermissionsForm(FlaskForm):
perms_team_mgmt = SelectField( perms_team_mgmt = SelectField(

View File

@ -5,6 +5,7 @@ from atst.domain.environments import Environments
from atst.domain.applications import Applications from atst.domain.applications import Applications
from atst.forms.app_settings import AppEnvRolesForm from atst.forms.app_settings import AppEnvRolesForm
from atst.forms.application import ApplicationForm, EditEnvironmentForm from atst.forms.application import ApplicationForm, EditEnvironmentForm
from atst.forms.data import ENV_ROLE_NO_ACCESS as NO_ACCESS
from atst.domain.authz.decorator import user_can_access_decorator as user_can from atst.domain.authz.decorator import user_can_access_decorator as user_can
from atst.models.environment_role import CSPRole from atst.models.environment_role import CSPRole
from atst.domain.exceptions import NotFoundError from atst.domain.exceptions import NotFoundError
@ -46,10 +47,10 @@ def sort_env_users_by_role(env):
users_list = [] users_list = []
no_access_users = env.application.users - env.users no_access_users = env.application.users - env.users
no_access_list = [ no_access_list = [
{"user_id": str(user.id), "user_name": user.full_name, "role_name": "no_access"} {"user_id": str(user.id), "user_name": user.full_name, "role_name": NO_ACCESS}
for user in no_access_users for user in no_access_users
] ]
users_list.append({"role": "no_access", "members": no_access_list}) users_list.append({"role": NO_ACCESS, "members": no_access_list})
for role in CSPRole: for role in CSPRole:
users_list.append( users_list.append(

View File

@ -113,7 +113,7 @@ def update_team(application_id):
environment_role_form.environment_id.data environment_role_form.environment_id.data
) )
Environments.update_env_role( Environments.update_env_role(
environment, user, environment_role_form.role.data environment, user, environment_role_form.data.get("role")
) )
flash("updated_application_team_settings", application_name=application.name) flash("updated_application_team_settings", application_name=application.name)

View File

@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils' import { shallowMount } from '@vue/test-utils'
import EditEnvironmentRole from '../forms/edit_environment_role' import { NO_ACCESS, EditEnvironmentRole } from '../forms/edit_environment_role'
describe('EditEnvironmentRole', () => { describe('EditEnvironmentRole', () => {
var initialRoleCategories, wrapper var initialRoleCategories, wrapper
@ -7,7 +7,7 @@ describe('EditEnvironmentRole', () => {
beforeEach(() => { beforeEach(() => {
initialRoleCategories = [ initialRoleCategories = [
{ {
role: 'no_access', role: NO_ACCESS,
members: [ members: [
{ role_name: null, user_id: '123' }, { role_name: null, user_id: '123' },
{ role_name: null, user_id: '456' }, { role_name: null, user_id: '456' },
@ -41,10 +41,10 @@ describe('EditEnvironmentRole', () => {
it('removes null roles to no_access', () => { it('removes null roles to no_access', () => {
let roles = wrapper.vm.sanitizeValues([ let roles = wrapper.vm.sanitizeValues([
{ role: 'no_access', members: [{ role_name: null }] }, { role: NO_ACCESS, members: [{ role_name: null }] },
]) ])
expect(roles).toEqual([ expect(roles).toEqual([
{ role: 'no_access', members: [{ role_name: 'no_access' }] }, { role: NO_ACCESS, members: [{ role_name: NO_ACCESS }] },
]) ])
}) })

View File

@ -1,7 +1,7 @@
import FormMixin from '../../mixins/form' import FormMixin from '../../mixins/form'
import Modal from '../../mixins/modal' import Modal from '../../mixins/modal'
import toggler from '../toggler' import toggler from '../toggler'
import EditEnvironmentRole from './edit_environment_role' import { EditEnvironmentRole } from './edit_environment_role'
export default { export default {
name: 'edit-application-roles', name: 'edit-application-roles',

View File

@ -5,7 +5,9 @@ import Modal from '../../mixins/modal'
// https://github.com/dod-ccpo/atst/pull/799/files#r282240663 // https://github.com/dod-ccpo/atst/pull/799/files#r282240663
// May also want to reconsider the data structure by storing the roles and members separately // May also want to reconsider the data structure by storing the roles and members separately
export default { export const NO_ACCESS = 'No Access'
export const EditEnvironmentRole = {
name: 'edit-environment-role', name: 'edit-environment-role',
mixins: [FormMixin], mixins: [FormMixin],
@ -26,7 +28,7 @@ export default {
roles.forEach(role => { roles.forEach(role => {
role.members.forEach(member => { role.members.forEach(member => {
if (member.role_name === null) { if (member.role_name === null) {
member.role_name = 'no_access' member.role_name = NO_ACCESS
} }
}) })
}) })
@ -34,7 +36,7 @@ export default {
}, },
checkNoAccess: function(role) { checkNoAccess: function(role) {
return role === 'no_access' return role === NO_ACCESS
}, },
toggleSection: function(sectionName) { toggleSection: function(sectionName) {

View File

@ -1,4 +1,4 @@
import editEnvironmentRole from './forms/edit_environment_role' import { EditEnvironmentRole } from './forms/edit_environment_role'
import FormMixin from '../mixins/form' import FormMixin from '../mixins/form'
import optionsinput from './options_input' import optionsinput from './options_input'
import textinput from './text_input' import textinput from './text_input'
@ -17,7 +17,7 @@ export default {
}, },
components: { components: {
editEnvironmentRole, EditEnvironmentRole,
optionsinput, optionsinput,
textinput, textinput,
optionsinput, optionsinput,

View File

@ -18,7 +18,7 @@ import poc from './components/forms/poc'
import oversight from './components/forms/oversight' import oversight from './components/forms/oversight'
import toggler from './components/toggler' import toggler from './components/toggler'
import NewApplication from './components/forms/new_application' import NewApplication from './components/forms/new_application'
import EditEnvironmentRole from './components/forms/edit_environment_role' import { EditEnvironmentRole } from './components/forms/edit_environment_role'
import EditApplicationRoles from './components/forms/edit_application_roles' import EditApplicationRoles from './components/forms/edit_application_roles'
import MultiStepModalForm from './components/forms/multi_step_modal_form' import MultiStepModalForm from './components/forms/multi_step_modal_form'
import funding from './components/forms/funding' import funding from './components/forms/funding'

View File

@ -79,13 +79,15 @@
{{ "portfolios.applications.team_settings.add_to_environment" | translate }} {{ "portfolios.applications.team_settings.add_to_environment" | translate }}
{{ Icon("plus") }} {{ Icon("plus") }}
</a> </a>
{% if user_can(permissions.DELETE_APPLICATION_MEMBER) %}
<button <button
type="button" type="button"
class='usa-button button-danger' class='usa-button button-danger'
v-on:click="openModal('{{ delete_modal_id }}')" v-on:click="openModal('{{ delete_modal_id }}')"
> >
{{ "portfolios.members.archive_button" | translate }} {{ "portfolios.applications.remove_member.button" | translate }}
</button> </button>
{% endif %}
</div> </div>
{% endcall %} {% endcall %}
{{ member_form.user_id() }} {{ member_form.user_id() }}

View File

@ -18,11 +18,11 @@ from atst.domain.environments import Environments
from atst.domain.permission_sets import PermissionSets from atst.domain.permission_sets import PermissionSets
from atst.domain.portfolios import Portfolios from atst.domain.portfolios import Portfolios
from atst.domain.exceptions import NotFoundError from atst.domain.exceptions import NotFoundError
from atst.models.environment_role import CSPRole from atst.models.environment_role import CSPRole
from atst.models.portfolio_role import Status as PortfolioRoleStatus from atst.models.portfolio_role import Status as PortfolioRoleStatus
from atst.forms.application import EditEnvironmentForm from atst.forms.application import EditEnvironmentForm
from atst.forms.app_settings import AppEnvRolesForm from atst.forms.app_settings import AppEnvRolesForm
from atst.forms.data import ENV_ROLE_NO_ACCESS as NO_ACCESS
from tests.utils import captured_templates from tests.utils import captured_templates
@ -166,7 +166,7 @@ def test_data_for_app_env_roles_form(app, client, user_session):
"env_id": env.id, "env_id": env.id,
"team_roles": [ "team_roles": [
{ {
"role": "no_access", "role": NO_ACCESS,
"members": [ "members": [
{ {
"user_id": str(app_role.user_id), "user_id": str(app_role.user_id),
@ -309,7 +309,7 @@ def test_update_team_env_roles(client, user_session):
"envs-0-team_roles-1-members-1-user_id": env_role_2.user.id, "envs-0-team_roles-1-members-1-user_id": env_role_2.user.id,
"envs-0-team_roles-1-members-1-role_name": CSPRole.BASIC_ACCESS.value, "envs-0-team_roles-1-members-1-role_name": CSPRole.BASIC_ACCESS.value,
"envs-0-team_roles-1-members-2-user_id": env_role_3.user.id, "envs-0-team_roles-1-members-2-user_id": env_role_3.user.id,
"envs-0-team_roles-1-members-2-role_name": "no_access", "envs-0-team_roles-1-members-2-role_name": NO_ACCESS,
} }
user_session(application.portfolio.owner) user_session(application.portfolio.owner)

View File

@ -4,6 +4,7 @@ from flask import url_for
from atst.domain.permission_sets import PermissionSets from atst.domain.permission_sets import PermissionSets
from atst.models import CSPRole from atst.models import CSPRole
from atst.forms.data import ENV_ROLE_NO_ACCESS as NO_ACCESS
from tests.factories import * from tests.factories import *
@ -120,8 +121,7 @@ def test_update_team_environment_roles(client, user_session):
assert env_role.role == CSPRole.TECHNICAL_READ.value assert env_role.role == CSPRole.TECHNICAL_READ.value
@pytest.mark.skip(reason="Need to rebase against master") def test_update_team_revoke_environment_access(client, user_session, db, session):
def test_update_team_revoke_environment_access(client, user_session):
application = ApplicationFactory.create() application = ApplicationFactory.create()
owner = application.portfolio.owner owner = application.portfolio.owner
app_role = ApplicationRoleFactory.create( app_role = ApplicationRoleFactory.create(
@ -141,12 +141,13 @@ def test_update_team_revoke_environment_access(client, user_session):
"members-0-permission_sets-perms_env_mgmt": PermissionSets.EDIT_APPLICATION_ENVIRONMENTS, "members-0-permission_sets-perms_env_mgmt": PermissionSets.EDIT_APPLICATION_ENVIRONMENTS,
"members-0-permission_sets-perms_del_env": PermissionSets.DELETE_APPLICATION_ENVIRONMENTS, "members-0-permission_sets-perms_del_env": PermissionSets.DELETE_APPLICATION_ENVIRONMENTS,
"members-0-environment_roles-0-environment_id": environment.id, "members-0-environment_roles-0-environment_id": environment.id,
"members-0-environment_roles-0-role": "", "members-0-environment_roles-0-role": NO_ACCESS,
}, },
) )
assert response.status_code == 302 assert response.status_code == 302
assert env_role.role == CSPRole.TECHNICAL_READ.value env_role_exists = db.exists().where(EnvironmentRole.id == env_role.id)
assert not session.query(env_role_exists).scalar()
def test_create_member(client, user_session): def test_create_member(client, user_session):