Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIU-2951: ECS - Prevent editing of specific shadow user data #2560

Merged
merged 5 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
* Add auto focus to textarea on staff and patron info modal. Fixes UIU-2932.
* ECS - Filter users by "User Type". Refs UIU-2943.
* Users App: Consume {{FormattedDate}} and {{FormattedTime}} via stripes-component. Refs UIU-1860.
* ECS - Prevent editing of specific shadow user data. Refs UIU-2951.

## [9.0.0](https://github.com/folio-org/ui-users/tree/v9.0.0) (2023-02-20)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v8.1.0...v9.0.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const EditContactInfo = ({
addressTypes,
preferredContactTypeId,
intl,
disabled,
}) => {
const contactTypeOptions = (contactTypes || []).map(g => {
return (
Expand Down Expand Up @@ -64,6 +65,7 @@ const EditContactInfo = ({
component={TextField}
required
fullWidth
disabled={disabled}
/>
</Col>
<Col xs={12} md={3}>
Expand All @@ -73,6 +75,7 @@ const EditContactInfo = ({
id="adduser_phone"
component={TextField}
fullWidth
disabled={disabled}
/>
</Col>
<Col xs={12} md={3}>
Expand All @@ -82,6 +85,7 @@ const EditContactInfo = ({
id="adduser_mobilePhone"
component={TextField}
fullWidth
disabled={disabled}
/>
</Col>
<Col xs={12} md={3}>
Expand All @@ -93,6 +97,7 @@ const EditContactInfo = ({
fullWidth
aria-required="true"
required
disabled={disabled}
defaultValue={selectedContactTypeId}
>
<FormattedMessage id="ui-users.contact.selectContactType">
Expand All @@ -108,6 +113,7 @@ const EditContactInfo = ({
fieldComponents={addressFields}
canDelete
formType="final-form"
disabled={disabled}
/>
</Accordion>
);
Expand All @@ -120,6 +126,7 @@ EditContactInfo.propTypes = {
addressTypes: PropTypes.arrayOf(PropTypes.object),
preferredContactTypeId: PropTypes.string,
intl: PropTypes.object.isRequired,
disabled: PropTypes.bool,
};

export default injectIntl(EditContactInfo);
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { screen } from '@folio/jest-config-stripes/testing-library/react';
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';
import { Form } from 'react-final-form';

import '__mock__/stripesComponents.mock';
import { screen } from '@folio/jest-config-stripes/testing-library/react';
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';

import renderWithRouter from 'helpers/renderWithRouter';
import EditContactInfo from './EditContactInfo';

jest.unmock('@folio/stripes/components');

const onSubmit = jest.fn();

const arrayMutators = {
Expand All @@ -28,7 +29,8 @@ const renderEditContactInfo = (props) => {
<EditContactInfo {...props} />
</>
);
renderWithRouter(

return renderWithRouter(
<Form
id="form-user"
mutators={{
Expand Down Expand Up @@ -71,9 +73,21 @@ describe('Render Edit contact Information component', () => {
renderEditContactInfo(props);
expect(screen.getByText('AddressEditList')).toBeInTheDocument();
});

it('Must be rendered', async () => {
renderEditContactInfo(props);
await userEvent.type(document.querySelector('[id="adduser_email"]'), '[email protected]');
expect(document.querySelector('[id="adduser_email"]').value).toBe('[email protected]');

const emailInput = screen.getByRole('textbox', { name: /email/i });

await userEvent.type(emailInput, '[email protected]');
expect(emailInput.value).toBe('[email protected]');
});

it('should render with disabled fields', () => {
renderEditContactInfo({ ...props, disabled: true });

expect(screen.getByRole('textbox', { name: /email/i })).toBeDisabled();
expect(screen.getByRole('textbox', { name: /mobilePhone/i })).toBeDisabled();
expect(screen.getByLabelText('ui-users.contact.phone')).toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@
&:focus {
outline: none;
}

&:disabled {
color: var(--checkable-disabled-fill);
cursor: not-allowed;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CreateResetPasswordControl extends React.Component {
POST: PropTypes.func.isRequired,
}).isRequired,
}).isRequired,
disabled: PropTypes.bool,
};

static manifest = Object.freeze({
Expand Down Expand Up @@ -111,6 +112,8 @@ class CreateResetPasswordControl extends React.Component {
};

render() {
const { disabled } = this.props;

return (
<Col
xs={12}
Expand All @@ -123,6 +126,7 @@ class CreateResetPasswordControl extends React.Component {
type="button"
className={css.resetPasswordButton}
onClick={this.handleLinkClick}
disabled={disabled}
>
<FormattedMessage id="ui-users.extended.sendResetPassword" />
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jest.unmock('@folio/stripes/smart-components');

const renderCreateResetPasswordControl = (props) => renderWithRouter(<CreateResetPasswordControl {...props} />);

const propData = (postMock) => {
const propData = (postMock, disabled = false) => {
return {
email: '[email protected]',
name: 'sample',
Expand All @@ -22,6 +22,7 @@ const propData = (postMock) => {
POST: postMock,
}
},
disabled,
};
};

Expand All @@ -42,6 +43,13 @@ describe('CreateResetPasswordControl component', () => {
await waitFor(() => userEvent.click(screen.getByText('ui-users.extended.sendResetPassword')));
await waitFor(() => expect(screen.getByText('ui-users.extended.copyLink')).toBeInTheDocument());
});
it('should link be disabled', () => {
const mockFunc = jest.fn(() => new Promise((resolve, _) => {
resolve({ ok: true, link: 'bl-users/password-reset/link' });
}));
renderCreateResetPasswordControl(propData(mockFunc, true));
expect(screen.getByText('ui-users.extended.sendResetPassword')).toBeDisabled();
});
/* Can be uncommented after the createResetpasswordControl modal logic is reworked. Should add an assertion at the end after the results */
// it('If it redirects after POST fails', async () => {
// const mockFunc = jest.fn(() => new Promise((_, reject) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
FormattedMessage,
useIntl,
} from 'react-intl';
import PropTypes from 'prop-types';
import { Field } from 'react-final-form';
import { FieldArray } from 'react-final-form-arrays';

Expand All @@ -15,7 +16,7 @@ import { departmentsShape } from '../../../../shapes';

import css from './DepartmentsNameEdit.css';

const DepartmentsNameEdit = ({ departments }) => {
const DepartmentsNameEdit = ({ departments, disabled }) => {
const { formatMessage } = useIntl();
const defaultDepartment = {
label: formatMessage({ id: 'ui-users.extended.department.default' }),
Expand All @@ -35,10 +36,13 @@ const DepartmentsNameEdit = ({ departments }) => {
component={RepeatableField}
name="departments"
onAdd={fields => fields.push()}
canRemove={!disabled}
canAdd={!disabled}
renderField={field => (
<Field
component={Select}
name={field}
disabled={disabled}
dataOptions={[defaultDepartment, ...formattedDepartments]}
/>
)}
Expand All @@ -47,6 +51,9 @@ const DepartmentsNameEdit = ({ departments }) => {
);
};

DepartmentsNameEdit.propTypes = { departments: departmentsShape };
DepartmentsNameEdit.propTypes = {
departments: departmentsShape,
disabled: PropTypes.bool
};

export default DepartmentsNameEdit;
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';
import renderWithRouter from 'helpers/renderWithRouter';
import DepartmentsNameEdit from './DepartmentsNameEdit';
import '__mock__/stripesSmartComponent.mock';

jest.unmock('@folio/stripes/components');
jest.unmock('@folio/stripes/smart-components');

const onSubmit = jest.fn();

Expand Down Expand Up @@ -63,3 +63,10 @@ describe('Given DepartmentsNameEdit', () => {
expect(screen.queryByPlaceholderText(/ui-users.extended.department.default/i));
});
});

describe('Given DepartmentsNameEdit with disabled: true', () => {
it('should add button to be disabled', async () => {
renderDepartmentsNameEdit({ ...props, disabled: true });
expect(screen.getByRole('button')).toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class EditExtendedInfo extends Component {
change: PropTypes.func.isRequired,
values: PropTypes.object,
uniquenessValidator: PropTypes.object,
disabled: PropTypes.bool,
};

buildAccordionHeader = () => {
Expand Down Expand Up @@ -83,6 +84,7 @@ class EditExtendedInfo extends Component {
departments,
change,
uniquenessValidator,
disabled,
} = this.props;

const accordionHeader = this.buildAccordionHeader();
Expand Down Expand Up @@ -110,6 +112,7 @@ class EditExtendedInfo extends Component {
name="enrollmentDate"
id="adduser_enrollmentdate"
validate={validateMinDate('ui-users.errors.extended.dateEnrolled')}
disabled={disabled}
/>
</Col>
<Col
Expand All @@ -122,6 +125,7 @@ class EditExtendedInfo extends Component {
id="adduser_externalsystemid"
component={TextField}
fullWidth
disabled={disabled}
/>
</Col>
<Col
Expand All @@ -136,6 +140,7 @@ class EditExtendedInfo extends Component {
id="adduser_dateofbirth"
timeZone="UTC"
backendDateStandard="YYYY-MM-DD"
disabled={disabled}
validate={validateMinDate('ui-users.errors.personal.dateOfBirth')}
/>
</Col>
Expand All @@ -161,6 +166,7 @@ class EditExtendedInfo extends Component {
defaultDeliveryAddressTypeId={defaultDeliveryAddressTypeId}
deliveryAvailable={deliveryAvailable}
setFieldValue={change}
disabled={disabled}
/>
</Row>
</Col>
Expand All @@ -170,7 +176,7 @@ class EditExtendedInfo extends Component {
xs={12}
md={3}
>
<DepartmentsNameEdit departments={departments} />
<DepartmentsNameEdit departments={departments} disabled={disabled} />
</Col>
)
: null
Expand All @@ -188,6 +194,7 @@ class EditExtendedInfo extends Component {
component={TextField}
fullWidth
validStylesEnabled
disabled={disabled}
validate={asyncValidateField('username', username, uniquenessValidator)}
/>
</Col>
Expand All @@ -199,6 +206,7 @@ class EditExtendedInfo extends Component {
email={userEmail}
name={userFirstName}
username={username}
disabled={disabled}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { screen } from '@folio/jest-config-stripes/testing-library/react';
import { Form } from 'react-final-form';
import PropTypes from 'prop-types';

import '__mock__/stripesComponents.mock';

import renderWithRouter from 'helpers/renderWithRouter';
import EditExtendedInfo from './EditExtendedInfo';

jest.unmock('@folio/stripes/components');

const onSubmit = jest.fn();

const arrayMutators = {
Expand All @@ -28,7 +28,8 @@ const renderEditExtendedInfo = (props) => {
<EditExtendedInfo {...props} />
</>
);
renderWithRouter(

return renderWithRouter(
<Form
id="form-user"
mutators={{
Expand Down Expand Up @@ -120,4 +121,8 @@ describe('Render Extended User Information component', () => {
renderEditExtendedInfo(props);
expect(screen.getByText('[email protected]')).toBeInTheDocument();
});
it('should fields to be disabled', () => {
renderEditExtendedInfo({ ...props, disabled: true });
expect(screen.getAllByRole('textbox')[0]).toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class RequestPreferencesEdit extends Component {
setFieldValue: PropTypes.func.isRequired,
defaultDeliveryAddressTypeId: nullOrStringIsRequiredTypeValidator,
intl: PropTypes.object.isRequired,
disabled: PropTypes.bool,
}

componentDidUpdate(prevProps) {
Expand Down Expand Up @@ -76,7 +77,7 @@ class RequestPreferencesEdit extends Component {
}

renderServicePointSelect() {
const { servicePoints, intl } = this.props;
const { servicePoints, intl, disabled } = this.props;

const options = servicePoints.map(servicePoint => ({
value: servicePoint.id,
Expand All @@ -92,6 +93,7 @@ class RequestPreferencesEdit extends Component {
label={<FormattedMessage id="ui-users.requests.defaultPickupServicePoint" />}
dataOptions={resultOptions}
component={Select}
disabled={disabled}
parse={this.defaultServicePointFieldParser}
/>
);
Expand Down Expand Up @@ -174,6 +176,7 @@ class RequestPreferencesEdit extends Component {
render() {
const {
deliveryAvailable,
disabled,
} = this.props;

return (
Expand Down Expand Up @@ -209,6 +212,7 @@ class RequestPreferencesEdit extends Component {
label={<FormattedMessage id="ui-users.requests.delivery" />}
component={Checkbox}
type="checkbox"
disabled={disabled}
/>
</Col>
</Row>
Expand Down
Loading
Loading