foreman_openscap 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/app/graphql/mutations/oval_policies/create.rb +33 -0
 - data/app/helpers/policies_helper.rb +1 -1
 - data/app/models/concerns/foreman_openscap/data_stream_content.rb +1 -1
 - data/app/models/concerns/foreman_openscap/oval_facet_hostgroup_extensions.rb +1 -0
 - data/app/models/foreman_openscap/arf_report.rb +1 -1
 - data/app/models/foreman_openscap/oval_content.rb +1 -1
 - data/app/services/foreman_openscap/oval/configure.rb +16 -13
 - data/app/services/foreman_openscap/oval/setup_check.rb +1 -1
 - data/lib/foreman_openscap/engine.rb +3 -2
 - data/lib/foreman_openscap/version.rb +1 -1
 - data/webpack/components/EditableInput.js +16 -10
 - data/webpack/components/IndexTable/index.js +7 -2
 - data/webpack/components/LinkButton.js +14 -2
 - data/webpack/components/withLoading.js +3 -1
 - data/webpack/graphql/mutations/createOvalPolicy.gql +22 -0
 - data/webpack/graphql/queries/ovalPolicy.gql +3 -0
 - data/webpack/helpers/formFieldsHelper.js +51 -1
 - data/webpack/helpers/globalIdHelper.js +4 -2
 - data/webpack/helpers/pathsHelper.js +5 -3
 - data/webpack/helpers/toastsHelper.js +3 -0
 - data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js +6 -1
 - data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js +18 -1
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/HostgroupSelect.js +135 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyForm.js +119 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyFormHelpers.js +107 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/OvalPoliciesNew.js +32 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.fixtures.js +147 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.test.js +172 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesNew/index.js +11 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js +2 -2
 - data/webpack/routes/OvalPolicies/OvalPoliciesShow/DetailsTab.js +2 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js +4 -3
 - data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.test.js +27 -0
 - data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js +11 -1
 - data/webpack/routes/routes.js +7 -0
 - data/webpack/testHelper.js +22 -0
 - metadata +12 -2
 
| 
         @@ -0,0 +1,172 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import React from 'react';
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { render, screen } from '@testing-library/react';
         
     | 
| 
      
 3 
     | 
    
         
            +
            import '@testing-library/jest-dom';
         
     | 
| 
      
 4 
     | 
    
         
            +
            import userEvent from '@testing-library/user-event';
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            import OvalPoliciesNew from '../';
         
     | 
| 
      
 7 
     | 
    
         
            +
            import { ovalPoliciesPath } from '../../../../helpers/pathsHelper';
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            import { unpagedMocks as ovalContentMocks } from '../../../OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures';
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            import {
         
     | 
| 
      
 12 
     | 
    
         
            +
              withMockedProvider,
         
     | 
| 
      
 13 
     | 
    
         
            +
              wait,
         
     | 
| 
      
 14 
     | 
    
         
            +
              withRouter,
         
     | 
| 
      
 15 
     | 
    
         
            +
              withRedux,
         
     | 
| 
      
 16 
     | 
    
         
            +
            } from '../../../../testHelper';
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            import {
         
     | 
| 
      
 19 
     | 
    
         
            +
              newPolicyName,
         
     | 
| 
      
 20 
     | 
    
         
            +
              newPolicyDescription,
         
     | 
| 
      
 21 
     | 
    
         
            +
              newPolicyCronline,
         
     | 
| 
      
 22 
     | 
    
         
            +
              newPolicyContentName,
         
     | 
| 
      
 23 
     | 
    
         
            +
              policySuccessMock,
         
     | 
| 
      
 24 
     | 
    
         
            +
              policyValidationMock,
         
     | 
| 
      
 25 
     | 
    
         
            +
              policyPreconditionMock,
         
     | 
| 
      
 26 
     | 
    
         
            +
              policyInvalidHgMock,
         
     | 
| 
      
 27 
     | 
    
         
            +
              hostgroupsMock,
         
     | 
| 
      
 28 
     | 
    
         
            +
              firstHg,
         
     | 
| 
      
 29 
     | 
    
         
            +
              roleAbsent as roleAbsentCheck,
         
     | 
| 
      
 30 
     | 
    
         
            +
              hgWithoutProxy as withoutProxyCheck,
         
     | 
| 
      
 31 
     | 
    
         
            +
            } from './OvalPoliciesNew.fixtures';
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            import * as toasts from '../../../../helpers/toastsHelper';
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            const TestComponent = withRouter(
         
     | 
| 
      
 36 
     | 
    
         
            +
              withRedux(withMockedProvider(OvalPoliciesNew))
         
     | 
| 
      
 37 
     | 
    
         
            +
            );
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            describe('OvalPoliciesNew', () => {
         
     | 
| 
      
 40 
     | 
    
         
            +
              it('should create new OVAL policy', async () => {
         
     | 
| 
      
 41 
     | 
    
         
            +
                const showToast = jest.fn();
         
     | 
| 
      
 42 
     | 
    
         
            +
                jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
         
     | 
| 
      
 43 
     | 
    
         
            +
                const pushMock = jest.fn();
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                render(
         
     | 
| 
      
 46 
     | 
    
         
            +
                  <TestComponent
         
     | 
| 
      
 47 
     | 
    
         
            +
                    mocks={ovalContentMocks.concat(policySuccessMock)}
         
     | 
| 
      
 48 
     | 
    
         
            +
                    history={{
         
     | 
| 
      
 49 
     | 
    
         
            +
                      push: pushMock,
         
     | 
| 
      
 50 
     | 
    
         
            +
                    }}
         
     | 
| 
      
 51 
     | 
    
         
            +
                  />
         
     | 
| 
      
 52 
     | 
    
         
            +
                );
         
     | 
| 
      
 53 
     | 
    
         
            +
                expect(screen.getByText('Loading')).toBeInTheDocument();
         
     | 
| 
      
 54 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 55 
     | 
    
         
            +
                const submitBtn = screen.getByRole('button', { name: 'submit' });
         
     | 
| 
      
 56 
     | 
    
         
            +
                expect(submitBtn).toBeDisabled();
         
     | 
| 
      
 57 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/name/), newPolicyName);
         
     | 
| 
      
 58 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 59 
     | 
    
         
            +
                expect(submitBtn).toBeDisabled();
         
     | 
| 
      
 60 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/cronLine/), 'foo');
         
     | 
| 
      
 61 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/description/), newPolicyDescription);
         
     | 
| 
      
 62 
     | 
    
         
            +
                userEvent.selectOptions(
         
     | 
| 
      
 63 
     | 
    
         
            +
                  screen.getByLabelText(/ovalContentId/),
         
     | 
| 
      
 64 
     | 
    
         
            +
                  newPolicyContentName
         
     | 
| 
      
 65 
     | 
    
         
            +
                );
         
     | 
| 
      
 66 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 67 
     | 
    
         
            +
                expect(screen.getByText('is not a valid cronline')).toBeInTheDocument();
         
     | 
| 
      
 68 
     | 
    
         
            +
                expect(submitBtn).toBeDisabled();
         
     | 
| 
      
 69 
     | 
    
         
            +
                userEvent.clear(screen.getByLabelText(/cronLine/));
         
     | 
| 
      
 70 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/cronLine/), newPolicyCronline);
         
     | 
| 
      
 71 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 72 
     | 
    
         
            +
                expect(
         
     | 
| 
      
 73 
     | 
    
         
            +
                  screen.queryByText('is not a valid cronline')
         
     | 
| 
      
 74 
     | 
    
         
            +
                ).not.toBeInTheDocument();
         
     | 
| 
      
 75 
     | 
    
         
            +
                expect(submitBtn).not.toBeDisabled();
         
     | 
| 
      
 76 
     | 
    
         
            +
                userEvent.click(submitBtn);
         
     | 
| 
      
 77 
     | 
    
         
            +
                await wait(2);
         
     | 
| 
      
 78 
     | 
    
         
            +
                expect(pushMock).toHaveBeenCalledWith(ovalPoliciesPath);
         
     | 
| 
      
 79 
     | 
    
         
            +
                expect(showToast).toHaveBeenCalledWith({
         
     | 
| 
      
 80 
     | 
    
         
            +
                  type: 'success',
         
     | 
| 
      
 81 
     | 
    
         
            +
                  message: 'OVAL Policy succesfully created.',
         
     | 
| 
      
 82 
     | 
    
         
            +
                });
         
     | 
| 
      
 83 
     | 
    
         
            +
              });
         
     | 
| 
      
 84 
     | 
    
         
            +
              it('should not create new policy on validation error', async () => {
         
     | 
| 
      
 85 
     | 
    
         
            +
                const showToast = jest.fn();
         
     | 
| 
      
 86 
     | 
    
         
            +
                jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
         
     | 
| 
      
 87 
     | 
    
         
            +
                const pushMock = jest.fn();
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                render(
         
     | 
| 
      
 90 
     | 
    
         
            +
                  <TestComponent
         
     | 
| 
      
 91 
     | 
    
         
            +
                    mocks={ovalContentMocks.concat(policyValidationMock)}
         
     | 
| 
      
 92 
     | 
    
         
            +
                    history={{
         
     | 
| 
      
 93 
     | 
    
         
            +
                      push: pushMock,
         
     | 
| 
      
 94 
     | 
    
         
            +
                    }}
         
     | 
| 
      
 95 
     | 
    
         
            +
                  />
         
     | 
| 
      
 96 
     | 
    
         
            +
                );
         
     | 
| 
      
 97 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 98 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/name/), newPolicyName);
         
     | 
| 
      
 99 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/cronLine/), newPolicyCronline);
         
     | 
| 
      
 100 
     | 
    
         
            +
                userEvent.selectOptions(
         
     | 
| 
      
 101 
     | 
    
         
            +
                  screen.getByLabelText(/ovalContentId/),
         
     | 
| 
      
 102 
     | 
    
         
            +
                  newPolicyContentName
         
     | 
| 
      
 103 
     | 
    
         
            +
                );
         
     | 
| 
      
 104 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 105 
     | 
    
         
            +
                userEvent.click(screen.getByRole('button', { name: 'submit' }));
         
     | 
| 
      
 106 
     | 
    
         
            +
                await wait(2);
         
     | 
| 
      
 107 
     | 
    
         
            +
                expect(pushMock).not.toHaveBeenCalled();
         
     | 
| 
      
 108 
     | 
    
         
            +
                expect(showToast).not.toHaveBeenCalled();
         
     | 
| 
      
 109 
     | 
    
         
            +
                expect(screen.getByText('has already been taken')).toBeInTheDocument();
         
     | 
| 
      
 110 
     | 
    
         
            +
              });
         
     | 
| 
      
 111 
     | 
    
         
            +
              it('should not create policy on preconditions error', async () => {
         
     | 
| 
      
 112 
     | 
    
         
            +
                const showToast = jest.fn();
         
     | 
| 
      
 113 
     | 
    
         
            +
                jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
         
     | 
| 
      
 114 
     | 
    
         
            +
                const pushMock = jest.fn();
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                render(
         
     | 
| 
      
 117 
     | 
    
         
            +
                  <TestComponent
         
     | 
| 
      
 118 
     | 
    
         
            +
                    mocks={ovalContentMocks.concat(policyPreconditionMock)}
         
     | 
| 
      
 119 
     | 
    
         
            +
                    history={{
         
     | 
| 
      
 120 
     | 
    
         
            +
                      push: pushMock,
         
     | 
| 
      
 121 
     | 
    
         
            +
                    }}
         
     | 
| 
      
 122 
     | 
    
         
            +
                  />
         
     | 
| 
      
 123 
     | 
    
         
            +
                );
         
     | 
| 
      
 124 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 125 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/name/), newPolicyName);
         
     | 
| 
      
 126 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/cronLine/), newPolicyCronline);
         
     | 
| 
      
 127 
     | 
    
         
            +
                userEvent.selectOptions(
         
     | 
| 
      
 128 
     | 
    
         
            +
                  screen.getByLabelText(/ovalContentId/),
         
     | 
| 
      
 129 
     | 
    
         
            +
                  newPolicyContentName
         
     | 
| 
      
 130 
     | 
    
         
            +
                );
         
     | 
| 
      
 131 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 132 
     | 
    
         
            +
                userEvent.click(screen.getByRole('button', { name: 'submit' }));
         
     | 
| 
      
 133 
     | 
    
         
            +
                await wait(2);
         
     | 
| 
      
 134 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 135 
     | 
    
         
            +
                expect(pushMock).not.toHaveBeenCalled();
         
     | 
| 
      
 136 
     | 
    
         
            +
                expect(showToast).toHaveBeenCalledWith({
         
     | 
| 
      
 137 
     | 
    
         
            +
                  type: 'error',
         
     | 
| 
      
 138 
     | 
    
         
            +
                  message: roleAbsentCheck.failMsg,
         
     | 
| 
      
 139 
     | 
    
         
            +
                });
         
     | 
| 
      
 140 
     | 
    
         
            +
              });
         
     | 
| 
      
 141 
     | 
    
         
            +
              it('should show hostgroup errros', async () => {
         
     | 
| 
      
 142 
     | 
    
         
            +
                const showToast = jest.fn();
         
     | 
| 
      
 143 
     | 
    
         
            +
                jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
         
     | 
| 
      
 144 
     | 
    
         
            +
                const pushMock = jest.fn();
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                render(
         
     | 
| 
      
 147 
     | 
    
         
            +
                  <TestComponent
         
     | 
| 
      
 148 
     | 
    
         
            +
                    mocks={ovalContentMocks
         
     | 
| 
      
 149 
     | 
    
         
            +
                      .concat(policyInvalidHgMock)
         
     | 
| 
      
 150 
     | 
    
         
            +
                      .concat(hostgroupsMock)}
         
     | 
| 
      
 151 
     | 
    
         
            +
                    history={{
         
     | 
| 
      
 152 
     | 
    
         
            +
                      push: pushMock,
         
     | 
| 
      
 153 
     | 
    
         
            +
                    }}
         
     | 
| 
      
 154 
     | 
    
         
            +
                  />
         
     | 
| 
      
 155 
     | 
    
         
            +
                );
         
     | 
| 
      
 156 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 157 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/name/), newPolicyName);
         
     | 
| 
      
 158 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/cronLine/), newPolicyCronline);
         
     | 
| 
      
 159 
     | 
    
         
            +
                userEvent.selectOptions(
         
     | 
| 
      
 160 
     | 
    
         
            +
                  screen.getByLabelText(/ovalContentId/),
         
     | 
| 
      
 161 
     | 
    
         
            +
                  newPolicyContentName
         
     | 
| 
      
 162 
     | 
    
         
            +
                );
         
     | 
| 
      
 163 
     | 
    
         
            +
                userEvent.type(screen.getByLabelText(/hostgroup/), 'first');
         
     | 
| 
      
 164 
     | 
    
         
            +
                await wait(500);
         
     | 
| 
      
 165 
     | 
    
         
            +
                userEvent.click(screen.getByText(firstHg.name));
         
     | 
| 
      
 166 
     | 
    
         
            +
                await wait();
         
     | 
| 
      
 167 
     | 
    
         
            +
                userEvent.click(screen.getByRole('button', { name: 'submit' }));
         
     | 
| 
      
 168 
     | 
    
         
            +
                await wait(2);
         
     | 
| 
      
 169 
     | 
    
         
            +
                expect(pushMock).not.toHaveBeenCalled();
         
     | 
| 
      
 170 
     | 
    
         
            +
                expect(screen.getByText(withoutProxyCheck.failMsg)).toBeInTheDocument();
         
     | 
| 
      
 171 
     | 
    
         
            +
              });
         
     | 
| 
      
 172 
     | 
    
         
            +
            });
         
     | 
| 
         @@ -0,0 +1,11 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import React from 'react';
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { useDispatch } from 'react-redux';
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            import { showToast } from '../../../helpers/toastsHelper';
         
     | 
| 
      
 5 
     | 
    
         
            +
            import OvalPoliciesNew from './OvalPoliciesNew';
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            const WrappedOvalPoliciesNew = props => (
         
     | 
| 
      
 8 
     | 
    
         
            +
              <OvalPoliciesNew {...props} showToast={showToast(useDispatch())} />
         
     | 
| 
      
 9 
     | 
    
         
            +
            );
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            export default WrappedOvalPoliciesNew;
         
     | 
| 
         @@ -4,7 +4,7 @@ import { translate as __ } from 'foremanReact/common/I18n'; 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            import { linkCell } from '../../../helpers/tableHelper';
         
     | 
| 
       6 
6 
     | 
    
         
             
            import { hostsPath } from '../../../helpers/pathsHelper';
         
     | 
| 
       7 
     | 
    
         
            -
            import {  
     | 
| 
      
 7 
     | 
    
         
            +
            import { decodeModelId } from '../../../helpers/globalIdHelper';
         
     | 
| 
       8 
8 
     | 
    
         
             
            import { addSearch } from '../../../helpers/pageParamsHelper';
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            import withLoading from '../../../components/withLoading';
         
     | 
| 
         @@ -25,7 +25,7 @@ const CvesTable = props => { 
     | 
|
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
              const hostCount = cve =>
         
     | 
| 
       27 
27 
     | 
    
         
             
                linkCell(
         
     | 
| 
       28 
     | 
    
         
            -
                  addSearch(hostsPath, { search: `cve_id = ${ 
     | 
| 
      
 28 
     | 
    
         
            +
                  addSearch(hostsPath, { search: `cve_id = ${decodeModelId(cve)}` }),
         
     | 
| 
       29 
29 
     | 
    
         
             
                  cve.hosts.nodes.length
         
     | 
| 
       30 
30 
     | 
    
         
             
                );
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
         @@ -40,6 +40,7 @@ const DetailsTab = props => { 
     | 
|
| 
       40 
40 
     | 
    
         
             
                        onConfirm={onAttrUpdate('name', policy, callMutation, showToast)}
         
     | 
| 
       41 
41 
     | 
    
         
             
                        component={TextInput}
         
     | 
| 
       42 
42 
     | 
    
         
             
                        attrName="name"
         
     | 
| 
      
 43 
     | 
    
         
            +
                        allowed={policy.meta.canEdit}
         
     | 
| 
       43 
44 
     | 
    
         
             
                      />
         
     | 
| 
       44 
45 
     | 
    
         
             
                    </TextListItem>
         
     | 
| 
       45 
46 
     | 
    
         
             
                    <TextListItem component={TextListItemVariants.dt}>
         
     | 
| 
         @@ -70,6 +71,7 @@ const DetailsTab = props => { 
     | 
|
| 
       70 
71 
     | 
    
         
             
                        )}
         
     | 
| 
       71 
72 
     | 
    
         
             
                        component={TextArea}
         
     | 
| 
       72 
73 
     | 
    
         
             
                        attrName="description"
         
     | 
| 
      
 74 
     | 
    
         
            +
                        allowed={policy.meta.canEdit}
         
     | 
| 
       73 
75 
     | 
    
         
             
                      />
         
     | 
| 
       74 
76 
     | 
    
         
             
                    </TextListItem>
         
     | 
| 
       75 
77 
     | 
    
         
             
                  </TextList>
         
     | 
| 
         @@ -1,6 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            import { translate as __, sprintf } from 'foremanReact/common/I18n';
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            import { decodeId } from '../../../helpers/globalIdHelper';
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { decodeModelId } from '../../../helpers/globalIdHelper';
         
     | 
| 
       4 
3 
     | 
    
         
             
            import { addSearch } from '../../../helpers/pageParamsHelper';
         
     | 
| 
       5 
4 
     | 
    
         
             
            import { newJobPath } from '../../../helpers/pathsHelper';
         
     | 
| 
       6 
5 
     | 
    
         | 
| 
         @@ -19,7 +18,9 @@ export const policySchedule = policy => { 
     | 
|
| 
       19 
18 
     | 
    
         | 
| 
       20 
19 
     | 
    
         
             
            const targetingScopedSearchQuery = policy => {
         
     | 
| 
       21 
20 
     | 
    
         
             
              const hgIds = policy.hostgroups.nodes.reduce((memo, hg) => {
         
     | 
| 
       22 
     | 
    
         
            -
                const ids = [ 
     | 
| 
      
 21 
     | 
    
         
            +
                const ids = [decodeModelId(hg)].concat(
         
     | 
| 
      
 22 
     | 
    
         
            +
                  hg.descendants.nodes.map(decodeModelId)
         
     | 
| 
      
 23 
     | 
    
         
            +
                );
         
     | 
| 
       23 
24 
     | 
    
         
             
                return ids.reduce(
         
     | 
| 
       24 
25 
     | 
    
         
             
                  (acc, id) => (acc.includes(id) ? acc : [...acc, id]),
         
     | 
| 
       25 
26 
     | 
    
         
             
                  memo
         
     | 
| 
         @@ -9,6 +9,7 @@ import { 
     | 
|
| 
       9 
9 
     | 
    
         
             
              historyMock,
         
     | 
| 
       10 
10 
     | 
    
         
             
              ovalPolicyId,
         
     | 
| 
       11 
11 
     | 
    
         
             
              policyDetailMock,
         
     | 
| 
      
 12 
     | 
    
         
            +
              policyEditPermissionsMock,
         
     | 
| 
       12 
13 
     | 
    
         
             
              ovalPolicy,
         
     | 
| 
       13 
14 
     | 
    
         
             
            } from './OvalPoliciesShow.fixtures';
         
     | 
| 
       14 
15 
     | 
    
         
             
            import {
         
     | 
| 
         @@ -171,5 +172,31 @@ describe('OvalPoliciesShow', () => { 
     | 
|
| 
       171 
172 
     | 
    
         
             
                ).not.toBeInTheDocument();
         
     | 
| 
       172 
173 
     | 
    
         
             
                expect(screen.getByText(ovalPolicy.name)).toBeInTheDocument();
         
     | 
| 
       173 
174 
     | 
    
         
             
                expect(screen.getByText('has already been taken')).toBeInTheDocument();
         
     | 
| 
      
 175 
     | 
    
         
            +
                userEvent.click(
         
     | 
| 
      
 176 
     | 
    
         
            +
                  screen.getByRole('button', { name: 'cancel editing name' })
         
     | 
| 
      
 177 
     | 
    
         
            +
                );
         
     | 
| 
      
 178 
     | 
    
         
            +
                userEvent.click(editBtn);
         
     | 
| 
      
 179 
     | 
    
         
            +
                expect(
         
     | 
| 
      
 180 
     | 
    
         
            +
                  screen.queryByText('has already been taken')
         
     | 
| 
      
 181 
     | 
    
         
            +
                ).not.toBeInTheDocument();
         
     | 
| 
      
 182 
     | 
    
         
            +
              });
         
     | 
| 
      
 183 
     | 
    
         
            +
              it('should not show edit btns when user is not allowed to edit', async () => {
         
     | 
| 
      
 184 
     | 
    
         
            +
                render(
         
     | 
| 
      
 185 
     | 
    
         
            +
                  <TestComponent
         
     | 
| 
      
 186 
     | 
    
         
            +
                    history={historyMock}
         
     | 
| 
      
 187 
     | 
    
         
            +
                    match={{
         
     | 
| 
      
 188 
     | 
    
         
            +
                      params: { id: ovalPolicyId, tab: 'details' },
         
     | 
| 
      
 189 
     | 
    
         
            +
                      path: ovalPoliciesShowPath,
         
     | 
| 
      
 190 
     | 
    
         
            +
                    }}
         
     | 
| 
      
 191 
     | 
    
         
            +
                    mocks={policyEditPermissionsMock}
         
     | 
| 
      
 192 
     | 
    
         
            +
                  />
         
     | 
| 
      
 193 
     | 
    
         
            +
                );
         
     | 
| 
      
 194 
     | 
    
         
            +
                await waitFor(tick);
         
     | 
| 
      
 195 
     | 
    
         
            +
                expect(
         
     | 
| 
      
 196 
     | 
    
         
            +
                  screen.queryByRole('button', { name: 'edit name' })
         
     | 
| 
      
 197 
     | 
    
         
            +
                ).not.toBeInTheDocument();
         
     | 
| 
      
 198 
     | 
    
         
            +
                expect(
         
     | 
| 
      
 199 
     | 
    
         
            +
                  screen.queryByRole('button', { name: 'edit description' })
         
     | 
| 
      
 200 
     | 
    
         
            +
                ).not.toBeInTheDocument();
         
     | 
| 
       174 
201 
     | 
    
         
             
              });
         
     | 
| 
       175 
202 
     | 
    
         
             
            });
         
     | 
| 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            import { mockFactory, admin, intruder } from '../../../../testHelper';
         
     | 
| 
      
 1 
     | 
    
         
            +
            import { mockFactory, admin, intruder, viewer } from '../../../../testHelper';
         
     | 
| 
       2 
2 
     | 
    
         
             
            import ovalPolicyQuery from '../../../../graphql/queries/ovalPolicy.gql';
         
     | 
| 
       3 
3 
     | 
    
         
             
            import cvesQuery from '../../../../graphql/queries/cves.gql';
         
     | 
| 
       4 
4 
     | 
    
         
             
            import hostgroupsQuery from '../../../../graphql/queries/hostgroups.gql';
         
     | 
| 
         @@ -16,6 +16,9 @@ export const ovalPolicy = { 
     | 
|
| 
       16 
16 
     | 
    
         
             
              weekday: 'tuesday',
         
     | 
| 
       17 
17 
     | 
    
         
             
              dayOfMonth: null,
         
     | 
| 
       18 
18 
     | 
    
         
             
              description: 'A very strict policy',
         
     | 
| 
      
 19 
     | 
    
         
            +
              meta: {
         
     | 
| 
      
 20 
     | 
    
         
            +
                canEdit: true,
         
     | 
| 
      
 21 
     | 
    
         
            +
              },
         
     | 
| 
       19 
22 
     | 
    
         
             
              hostgroups: {
         
     | 
| 
       20 
23 
     | 
    
         
             
                nodes: [
         
     | 
| 
       21 
24 
     | 
    
         
             
                  {
         
     | 
| 
         @@ -33,6 +36,8 @@ export const ovalPolicy = { 
     | 
|
| 
       33 
36 
     | 
    
         
             
              },
         
     | 
| 
       34 
37 
     | 
    
         
             
            };
         
     | 
| 
       35 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
            const noEditPolicy = { ...ovalPolicy, meta: { canEdit: false } };
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
       36 
41 
     | 
    
         
             
            const cvesResult = {
         
     | 
| 
       37 
42 
     | 
    
         
             
              totalCount: 1,
         
     | 
| 
       38 
43 
     | 
    
         
             
              nodes: [
         
     | 
| 
         @@ -112,3 +117,8 @@ export const policyHostgroupsDeniedMock = hostgroupsMockFactory( 
     | 
|
| 
       112 
117 
     | 
    
         
             
              { totalCount: 0, nodes: [] },
         
     | 
| 
       113 
118 
     | 
    
         
             
              { currentUser: intruder }
         
     | 
| 
       114 
119 
     | 
    
         
             
            );
         
     | 
| 
      
 120 
     | 
    
         
            +
            export const policyEditPermissionsMock = policyDetailMockFactory(
         
     | 
| 
      
 121 
     | 
    
         
            +
              { id: ovalPolicy.id },
         
     | 
| 
      
 122 
     | 
    
         
            +
              noEditPolicy,
         
     | 
| 
      
 123 
     | 
    
         
            +
              { currentUser: viewer }
         
     | 
| 
      
 124 
     | 
    
         
            +
            );
         
     | 
    
        data/webpack/routes/routes.js
    CHANGED
    
    | 
         @@ -3,6 +3,7 @@ import OvalContentsIndex from './OvalContents/OvalContentsIndex'; 
     | 
|
| 
       3 
3 
     | 
    
         
             
            import OvalContentsShow from './OvalContents/OvalContentsShow';
         
     | 
| 
       4 
4 
     | 
    
         
             
            import OvalContentsNew from './OvalContents/OvalContentsNew';
         
     | 
| 
       5 
5 
     | 
    
         
             
            import OvalPoliciesIndex from './OvalPolicies/OvalPoliciesIndex';
         
     | 
| 
      
 6 
     | 
    
         
            +
            import OvalPoliciesNew from './OvalPolicies/OvalPoliciesNew';
         
     | 
| 
       6 
7 
     | 
    
         
             
            import OvalPoliciesShow from './OvalPolicies/OvalPoliciesShow';
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
            import {
         
     | 
| 
         @@ -11,6 +12,7 @@ import { 
     | 
|
| 
       11 
12 
     | 
    
         
             
              ovalContentsNewPath,
         
     | 
| 
       12 
13 
     | 
    
         
             
              ovalPoliciesPath,
         
     | 
| 
       13 
14 
     | 
    
         
             
              ovalPoliciesShowPath,
         
     | 
| 
      
 15 
     | 
    
         
            +
              ovalPoliciesNewPath,
         
     | 
| 
       14 
16 
     | 
    
         
             
            } from '../helpers/pathsHelper';
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
       16 
18 
     | 
    
         
             
            export default [
         
     | 
| 
         @@ -34,6 +36,11 @@ export default [ 
     | 
|
| 
       34 
36 
     | 
    
         
             
                render: props => <OvalPoliciesIndex {...props} />,
         
     | 
| 
       35 
37 
     | 
    
         
             
                exact: true,
         
     | 
| 
       36 
38 
     | 
    
         
             
              },
         
     | 
| 
      
 39 
     | 
    
         
            +
              {
         
     | 
| 
      
 40 
     | 
    
         
            +
                path: ovalPoliciesNewPath,
         
     | 
| 
      
 41 
     | 
    
         
            +
                render: props => <OvalPoliciesNew {...props} />,
         
     | 
| 
      
 42 
     | 
    
         
            +
                exact: true,
         
     | 
| 
      
 43 
     | 
    
         
            +
              },
         
     | 
| 
       37 
44 
     | 
    
         
             
              {
         
     | 
| 
       38 
45 
     | 
    
         
             
                path: ovalPoliciesShowPath,
         
     | 
| 
       39 
46 
     | 
    
         
             
                render: props => <OvalPoliciesShow {...props} />,
         
     | 
    
        data/webpack/testHelper.js
    CHANGED
    
    | 
         @@ -4,6 +4,7 @@ import store from 'foremanReact/redux'; 
     | 
|
| 
       4 
4 
     | 
    
         
             
            import { MockedProvider } from '@apollo/react-testing';
         
     | 
| 
       5 
5 
     | 
    
         
             
            import { MemoryRouter } from 'react-router-dom';
         
     | 
| 
       6 
6 
     | 
    
         
             
            import { getForemanContext } from 'foremanReact/Root/Context/ForemanContext';
         
     | 
| 
      
 7 
     | 
    
         
            +
            import { waitFor } from '@testing-library/react';
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
            export const withRedux = Component => props => (
         
     | 
| 
       9 
10 
     | 
    
         
             
              <Provider store={store}>
         
     | 
| 
         @@ -42,6 +43,14 @@ export const withMockedProvider = Component => props => { 
     | 
|
| 
       42 
43 
     | 
    
         
             
            // use to resolve async mock requests for apollo MockedProvider
         
     | 
| 
       43 
44 
     | 
    
         
             
            export const tick = () => new Promise(resolve => setTimeout(resolve, 0));
         
     | 
| 
       44 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
            export const wait = async (tickCount = 1) => {
         
     | 
| 
      
 47 
     | 
    
         
            +
              for (let i = 1; i < tickCount; i++) {
         
     | 
| 
      
 48 
     | 
    
         
            +
                // eslint-disable-next-line no-await-in-loop
         
     | 
| 
      
 49 
     | 
    
         
            +
                await waitFor(tick);
         
     | 
| 
      
 50 
     | 
    
         
            +
              }
         
     | 
| 
      
 51 
     | 
    
         
            +
              return waitFor(tick);
         
     | 
| 
      
 52 
     | 
    
         
            +
            };
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
       45 
54 
     | 
    
         
             
            export const historyMock = {
         
     | 
| 
       46 
55 
     | 
    
         
             
              location: {
         
     | 
| 
       47 
56 
     | 
    
         
             
                search: '',
         
     | 
| 
         @@ -76,6 +85,19 @@ export const intruder = userFactory('intruder', [ 
     | 
|
| 
       76 
85 
     | 
    
         
             
              },
         
     | 
| 
       77 
86 
     | 
    
         
             
            ]);
         
     | 
| 
       78 
87 
     | 
    
         | 
| 
      
 88 
     | 
    
         
            +
            export const viewer = userFactory('viewer', [
         
     | 
| 
      
 89 
     | 
    
         
            +
              {
         
     | 
| 
      
 90 
     | 
    
         
            +
                __typename: 'Permission',
         
     | 
| 
      
 91 
     | 
    
         
            +
                id: 'MDE6UGVybWlzc2lvbi0yOTY=',
         
     | 
| 
      
 92 
     | 
    
         
            +
                name: 'view_oval_contents',
         
     | 
| 
      
 93 
     | 
    
         
            +
              },
         
     | 
| 
      
 94 
     | 
    
         
            +
              {
         
     | 
| 
      
 95 
     | 
    
         
            +
                __typename: 'Permission',
         
     | 
| 
      
 96 
     | 
    
         
            +
                id: 'MDE6UGVybWlzc2lvbi0yNzU=',
         
     | 
| 
      
 97 
     | 
    
         
            +
                name: 'view_oval_policies',
         
     | 
| 
      
 98 
     | 
    
         
            +
              },
         
     | 
| 
      
 99 
     | 
    
         
            +
            ]);
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
       79 
101 
     | 
    
         
             
            export const mockFactory = (resultName, query) => (
         
     | 
| 
       80 
102 
     | 
    
         
             
              variables,
         
     | 
| 
       81 
103 
     | 
    
         
             
              modelResults,
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: foreman_openscap
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 5. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 5.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - slukasik@redhat.com
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2021-11- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-11-29 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake
         
     | 
| 
         @@ -73,6 +73,7 @@ files: 
     | 
|
| 
       73 
73 
     | 
    
         
             
            - app/controllers/scap_contents_controller.rb
         
     | 
| 
       74 
74 
     | 
    
         
             
            - app/controllers/tailoring_files_controller.rb
         
     | 
| 
       75 
75 
     | 
    
         
             
            - app/graphql/mutations/oval_contents/delete.rb
         
     | 
| 
      
 76 
     | 
    
         
            +
            - app/graphql/mutations/oval_policies/create.rb
         
     | 
| 
       76 
77 
     | 
    
         
             
            - app/graphql/mutations/oval_policies/delete.rb
         
     | 
| 
       77 
78 
     | 
    
         
             
            - app/graphql/mutations/oval_policies/update.rb
         
     | 
| 
       78 
79 
     | 
    
         
             
            - app/graphql/types/cve.rb
         
     | 
| 
         @@ -444,6 +445,7 @@ files: 
     | 
|
| 
       444 
445 
     | 
    
         
             
            - webpack/components/withDeleteModal.js
         
     | 
| 
       445 
446 
     | 
    
         
             
            - webpack/components/withLoading.js
         
     | 
| 
       446 
447 
     | 
    
         
             
            - webpack/global_index.js
         
     | 
| 
      
 448 
     | 
    
         
            +
            - webpack/graphql/mutations/createOvalPolicy.gql
         
     | 
| 
       447 
449 
     | 
    
         
             
            - webpack/graphql/mutations/deleteOvalContent.gql
         
     | 
| 
       448 
450 
     | 
    
         
             
            - webpack/graphql/mutations/deleteOvalPolicy.gql
         
     | 
| 
       449 
451 
     | 
    
         
             
            - webpack/graphql/mutations/updateOvalPolicy.gql
         
     | 
| 
         @@ -463,6 +465,7 @@ files: 
     | 
|
| 
       463 
465 
     | 
    
         
             
            - webpack/helpers/permissionsHelper.js
         
     | 
| 
       464 
466 
     | 
    
         
             
            - webpack/helpers/tableHelper.js
         
     | 
| 
       465 
467 
     | 
    
         
             
            - webpack/helpers/toastHelper.js
         
     | 
| 
      
 468 
     | 
    
         
            +
            - webpack/helpers/toastsHelper.js
         
     | 
| 
       466 
469 
     | 
    
         
             
            - webpack/index.js
         
     | 
| 
       467 
470 
     | 
    
         
             
            - webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js
         
     | 
| 
       468 
471 
     | 
    
         
             
            - webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js
         
     | 
| 
         @@ -487,6 +490,13 @@ files: 
     | 
|
| 
       487 
490 
     | 
    
         
             
            - webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js
         
     | 
| 
       488 
491 
     | 
    
         
             
            - webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js
         
     | 
| 
       489 
492 
     | 
    
         
             
            - webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js
         
     | 
| 
      
 493 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/HostgroupSelect.js
         
     | 
| 
      
 494 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyForm.js
         
     | 
| 
      
 495 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyFormHelpers.js
         
     | 
| 
      
 496 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/OvalPoliciesNew.js
         
     | 
| 
      
 497 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.fixtures.js
         
     | 
| 
      
 498 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.test.js
         
     | 
| 
      
 499 
     | 
    
         
            +
            - webpack/routes/OvalPolicies/OvalPoliciesNew/index.js
         
     | 
| 
       490 
500 
     | 
    
         
             
            - webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js
         
     | 
| 
       491 
501 
     | 
    
         
             
            - webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js
         
     | 
| 
       492 
502 
     | 
    
         
             
            - webpack/routes/OvalPolicies/OvalPoliciesShow/DetailsTab.js
         
     |