mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 18:09:57 -03:30
Merge pull request #9884 from nixocio/ui_issue_9769
Do not allow EE to modify Org Do not allow EE to modify Org. See: #9769 Also: #9874 Reviewed-by: Jake McDermott <yo@jakemcdermott.me> Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
This commit is contained in:
commit
a194dfdbbb
@ -37,6 +37,7 @@ function ExecutionEnvironmentEdit({ executionEnvironment }) {
|
||||
submitError={submitError}
|
||||
onCancel={handleCancel}
|
||||
me={me || {}}
|
||||
isOrgLookupDisabled
|
||||
/>
|
||||
)}
|
||||
</Config>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { func, shape } from 'prop-types';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { func, shape, bool } from 'prop-types';
|
||||
import { Formik, useField, useFormikContext } from 'formik';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Form, FormGroup } from '@patternfly/react-core';
|
||||
import { Form, FormGroup, Tooltip } from '@patternfly/react-core';
|
||||
|
||||
import { ExecutionEnvironmentsAPI } from '../../../api';
|
||||
import CredentialLookup from '../../../components/Lookup/CredentialLookup';
|
||||
@ -22,6 +22,7 @@ function ExecutionEnvironmentFormFields({
|
||||
me,
|
||||
options,
|
||||
executionEnvironment,
|
||||
isOrgLookupDisabled,
|
||||
}) {
|
||||
const [credentialField, credentialMeta, credentialHelpers] = useField(
|
||||
'credential'
|
||||
@ -33,6 +34,8 @@ function ExecutionEnvironmentFormFields({
|
||||
required(i18n._(t`Select a value for this field`), i18n),
|
||||
});
|
||||
|
||||
const isGloballyAvailable = useRef(!organizationField.value);
|
||||
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
const onCredentialChange = useCallback(
|
||||
@ -61,6 +64,30 @@ function ExecutionEnvironmentFormFields({
|
||||
([value, label]) => ({ value, label, key: value })
|
||||
);
|
||||
|
||||
const renderOrganizationLookup = () => {
|
||||
return (
|
||||
<OrganizationLookup
|
||||
helperTextInvalid={organizationMeta.error}
|
||||
isValid={!organizationMeta.touched || !organizationMeta.error}
|
||||
onBlur={() => organizationHelpers.setTouched()}
|
||||
onChange={onOrganizationChange}
|
||||
value={organizationField.value}
|
||||
required={!me.is_superuser}
|
||||
helperText={
|
||||
me?.is_superuser &&
|
||||
((!isOrgLookupDisabled && isGloballyAvailable) ||
|
||||
organizationField.value === null)
|
||||
? i18n._(
|
||||
t`Leave this field blank to make the execution environment globally available.`
|
||||
)
|
||||
: null
|
||||
}
|
||||
autoPopulate={!me?.is_superuser ? !executionEnvironment?.id : null}
|
||||
isDisabled={!!isOrgLookupDisabled && isGloballyAvailable.current}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
@ -107,22 +134,17 @@ function ExecutionEnvironmentFormFields({
|
||||
name="description"
|
||||
type="text"
|
||||
/>
|
||||
<OrganizationLookup
|
||||
helperTextInvalid={organizationMeta.error}
|
||||
isValid={!organizationMeta.touched || !organizationMeta.error}
|
||||
onBlur={() => organizationHelpers.setTouched()}
|
||||
onChange={onOrganizationChange}
|
||||
value={organizationField.value}
|
||||
required={!me.is_superuser}
|
||||
helperText={
|
||||
me?.is_superuser
|
||||
? i18n._(
|
||||
t`Leave this field blank to make the execution environment globally available.`
|
||||
)
|
||||
: null
|
||||
}
|
||||
autoPopulate={!me?.is_superuser ? !executionEnvironment?.id : null}
|
||||
/>
|
||||
{isOrgLookupDisabled && isGloballyAvailable.current ? (
|
||||
<Tooltip
|
||||
content={i18n._(
|
||||
t`Globally available execution environment can not be reassigned to a specific Organization`
|
||||
)}
|
||||
>
|
||||
{renderOrganizationLookup()}
|
||||
</Tooltip>
|
||||
) : (
|
||||
renderOrganizationLookup()
|
||||
)}
|
||||
|
||||
<CredentialLookup
|
||||
label={i18n._(t`Registry credential`)}
|
||||
@ -146,6 +168,7 @@ function ExecutionEnvironmentForm({
|
||||
onCancel,
|
||||
submitError,
|
||||
me,
|
||||
isOrgLookupDisabled,
|
||||
...rest
|
||||
}) {
|
||||
const {
|
||||
@ -191,6 +214,7 @@ function ExecutionEnvironmentForm({
|
||||
me={me}
|
||||
options={options}
|
||||
executionEnvironment={executionEnvironment}
|
||||
isOrgLookupDisabled={isOrgLookupDisabled}
|
||||
{...rest}
|
||||
/>
|
||||
{submitError && <FormSubmitError error={submitError} />}
|
||||
@ -210,11 +234,13 @@ ExecutionEnvironmentForm.propTypes = {
|
||||
onCancel: func.isRequired,
|
||||
onSubmit: func.isRequired,
|
||||
submitError: shape({}),
|
||||
isOrgLookupDisabled: bool,
|
||||
};
|
||||
|
||||
ExecutionEnvironmentForm.defaultProps = {
|
||||
executionEnvironment: {},
|
||||
submitError: null,
|
||||
isOrgLookupDisabled: false,
|
||||
};
|
||||
|
||||
export default withI18n()(ExecutionEnvironmentForm);
|
||||
|
||||
@ -29,6 +29,45 @@ const executionEnvironment = {
|
||||
'/api/v2/execution_environments/16/unified_job_templates/',
|
||||
credential: '/api/v2/credentials/4/',
|
||||
},
|
||||
summary_fields: {
|
||||
organization: {
|
||||
id: 1,
|
||||
name: 'Default',
|
||||
description: '',
|
||||
},
|
||||
credential: {
|
||||
id: 4,
|
||||
name: 'Container Registry',
|
||||
description: '',
|
||||
kind: 'registry',
|
||||
cloud: false,
|
||||
kubernetes: false,
|
||||
credential_type_id: 17,
|
||||
},
|
||||
},
|
||||
created: '2020-09-17T16:06:57.346128Z',
|
||||
modified: '2020-09-17T16:06:57.346147Z',
|
||||
description: 'A simple EE',
|
||||
organization: 1,
|
||||
image: 'https://registry.com/image/container',
|
||||
managed_by_tower: false,
|
||||
credential: 4,
|
||||
};
|
||||
|
||||
const globallyAvailableEE = {
|
||||
id: 17,
|
||||
name: 'GEE',
|
||||
type: 'execution_environment',
|
||||
pull: 'one',
|
||||
url: '/api/v2/execution_environments/17/',
|
||||
related: {
|
||||
created_by: '/api/v2/users/1/',
|
||||
modified_by: '/api/v2/users/1/',
|
||||
activity_stream: '/api/v2/execution_environments/16/activity_stream/',
|
||||
unified_job_templates:
|
||||
'/api/v2/execution_environments/16/unified_job_templates/',
|
||||
credential: '/api/v2/credentials/4/',
|
||||
},
|
||||
summary_fields: {
|
||||
credential: {
|
||||
id: 4,
|
||||
@ -180,4 +219,55 @@ describe('<ExecutionEnvironmentForm/>', () => {
|
||||
wrapper.find('button[aria-label="Cancel"]').invoke('onClick')();
|
||||
expect(onCancel).toBeCalled();
|
||||
});
|
||||
|
||||
test('globally available EE can not have organization reassigned', async () => {
|
||||
let newWrapper;
|
||||
await act(async () => {
|
||||
newWrapper = mountWithContexts(
|
||||
<ExecutionEnvironmentForm
|
||||
onCancel={onCancel}
|
||||
onSubmit={onSubmit}
|
||||
executionEnvironment={globallyAvailableEE}
|
||||
options={mockOptions}
|
||||
me={mockMe}
|
||||
isOrgLookupDisabled
|
||||
/>
|
||||
);
|
||||
});
|
||||
await waitForElement(newWrapper, 'ContentLoading', el => el.length === 0);
|
||||
expect(newWrapper.find('OrganizationLookup').prop('isDisabled')).toEqual(
|
||||
true
|
||||
);
|
||||
expect(newWrapper.find('Tooltip').prop('content')).toEqual(
|
||||
'Globally available execution environment can not be reassigned to a specific Organization'
|
||||
);
|
||||
});
|
||||
|
||||
test('should allow an organization to be re-assigned as globally available EE', async () => {
|
||||
let newWrapper;
|
||||
await act(async () => {
|
||||
newWrapper = mountWithContexts(
|
||||
<ExecutionEnvironmentForm
|
||||
onCancel={onCancel}
|
||||
onSubmit={onSubmit}
|
||||
executionEnvironment={executionEnvironment}
|
||||
options={mockOptions}
|
||||
me={mockMe}
|
||||
isOrgLookupDisabled
|
||||
/>
|
||||
);
|
||||
});
|
||||
await waitForElement(newWrapper, 'ContentLoading', el => el.length === 0);
|
||||
expect(newWrapper.find('OrganizationLookup').prop('isDisabled')).toEqual(
|
||||
false
|
||||
);
|
||||
expect(newWrapper.find('Tooltip').length).toEqual(0);
|
||||
|
||||
await act(async () => {
|
||||
newWrapper.find('OrganizationLookup').invoke('onBlur')();
|
||||
newWrapper.find('OrganizationLookup').invoke('onChange')(null);
|
||||
});
|
||||
newWrapper.update();
|
||||
expect(newWrapper.find('OrganizationLookup').prop('value')).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user