foreman_openscap 8.0.1 → 9.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/app/lib/proxy_api/openscap.rb +11 -0
- data/app/models/concerns/foreman_openscap/data_stream_content.rb +1 -5
- data/app/services/foreman_openscap/client_config/ansible.rb +1 -10
- data/app/validators/foreman_openscap/data_stream_validator.rb +1 -1
- data/config/initializers/inflections.rb +0 -2
- data/config/routes.rb +0 -15
- data/db/migrate/20240313111822_drop_oval.rb +17 -0
- data/lib/foreman_openscap/data_migration.rb +7 -6
- data/lib/foreman_openscap/engine.rb +2 -56
- data/lib/foreman_openscap/version.rb +1 -1
- data/test/factories/compliance_host_factory.rb +0 -12
- data/test/test_plugin_helper.rb +0 -2
- data/test/unit/scap_content_test.rb +2 -3
- data/webpack/components/OpenscapRemediationWizard/ViewSelectedHostsLink.js +2 -2
- data/webpack/components/OpenscapRemediationWizard/steps/ReviewHosts.js +12 -2
- data/webpack/components/OpenscapRemediationWizard/steps/ReviewRemediation.js +7 -4
- data/webpack/global_index.js +0 -4
- metadata +7 -169
- data/app/controllers/api/v2/compliance/oval_contents_controller.rb +0 -72
- data/app/controllers/api/v2/compliance/oval_policies_controller.rb +0 -111
- data/app/controllers/api/v2/compliance/oval_reports_controller.rb +0 -47
- data/app/controllers/concerns/foreman/controller/parameters/oval_content.rb +0 -22
- data/app/controllers/concerns/foreman/controller/parameters/oval_policy.rb +0 -22
- data/app/graphql/mutations/oval_contents/delete.rb +0 -9
- data/app/graphql/mutations/oval_policies/create.rb +0 -33
- data/app/graphql/mutations/oval_policies/delete.rb +0 -9
- data/app/graphql/mutations/oval_policies/update.rb +0 -15
- data/app/graphql/types/cve.rb +0 -17
- data/app/graphql/types/oval_check.rb +0 -11
- data/app/graphql/types/oval_content.rb +0 -19
- data/app/graphql/types/oval_policy.rb +0 -24
- data/app/lib/proxy_api/available_proxy.rb +0 -44
- data/app/models/concerns/foreman_openscap/oval_facet_host_extensions.rb +0 -38
- data/app/models/concerns/foreman_openscap/oval_facet_hostgroup_extensions.rb +0 -31
- data/app/models/foreman_openscap/cve.rb +0 -23
- data/app/models/foreman_openscap/host/oval_facet.rb +0 -14
- data/app/models/foreman_openscap/host_cve.rb +0 -7
- data/app/models/foreman_openscap/hostgroup/oval_facet.rb +0 -14
- data/app/models/foreman_openscap/hostgroup_oval_facet_oval_policy.rb +0 -6
- data/app/models/foreman_openscap/oval_content.rb +0 -28
- data/app/models/foreman_openscap/oval_facet_oval_policy.rb +0 -6
- data/app/models/foreman_openscap/oval_policy.rb +0 -54
- data/app/models/foreman_openscap/oval_status.rb +0 -45
- data/app/services/foreman_openscap/oval/check_collection.rb +0 -45
- data/app/services/foreman_openscap/oval/configure.rb +0 -83
- data/app/services/foreman_openscap/oval/cves.rb +0 -41
- data/app/services/foreman_openscap/oval/setup.rb +0 -93
- data/app/services/foreman_openscap/oval/setup_check.rb +0 -58
- data/app/services/foreman_openscap/oval/sync_oval_contents.rb +0 -42
- data/app/views/api/v2/compliance/oval_contents/base.json.rabl +0 -6
- data/app/views/api/v2/compliance/oval_contents/create.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_contents/destroy.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_contents/index.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_contents/show.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_contents/sync.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_contents/sync_result.json.rabl +0 -11
- data/app/views/api/v2/compliance/oval_contents/update.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_policies/create.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_policies/index.json.rabl +0 -3
- data/app/views/api/v2/compliance/oval_policies/main.json.rabl +0 -15
- data/app/views/api/v2/compliance/oval_policies/show.json.rabl +0 -3
- data/app/views/job_templates/run_oval_scans.erb +0 -24
- data/locale/cs_CZ/foreman_openscap.edit.po +0 -1863
- data/locale/cs_CZ/foreman_openscap.po.time_stamp +0 -0
- data/locale/de/foreman_openscap.edit.po +0 -1873
- data/locale/de/foreman_openscap.po.time_stamp +0 -0
- data/locale/en/foreman_openscap.edit.po +0 -1863
- data/locale/en/foreman_openscap.po.time_stamp +0 -0
- data/locale/en_GB/foreman_openscap.edit.po +0 -1863
- data/locale/en_GB/foreman_openscap.po.time_stamp +0 -0
- data/locale/es/foreman_openscap.edit.po +0 -1868
- data/locale/es/foreman_openscap.po.time_stamp +0 -0
- data/locale/fr/foreman_openscap.edit.po +0 -1874
- data/locale/fr/foreman_openscap.po.time_stamp +0 -0
- data/locale/gl/foreman_openscap.edit.po +0 -1863
- data/locale/gl/foreman_openscap.po.time_stamp +0 -0
- data/locale/it/foreman_openscap.edit.po +0 -1865
- data/locale/it/foreman_openscap.po.time_stamp +0 -0
- data/locale/ja/foreman_openscap.edit.po +0 -1869
- data/locale/ja/foreman_openscap.po.time_stamp +0 -0
- data/locale/ka/foreman_openscap.edit.po +0 -1863
- data/locale/ka/foreman_openscap.po.time_stamp +0 -0
- data/locale/ko/foreman_openscap.edit.po +0 -1863
- data/locale/ko/foreman_openscap.po.time_stamp +0 -0
- data/locale/pt_BR/foreman_openscap.edit.po +0 -1873
- data/locale/pt_BR/foreman_openscap.po.time_stamp +0 -0
- data/locale/ru/foreman_openscap.edit.po +0 -1867
- data/locale/ru/foreman_openscap.po.time_stamp +0 -0
- data/locale/sv_SE/foreman_openscap.edit.po +0 -1863
- data/locale/sv_SE/foreman_openscap.po.time_stamp +0 -0
- data/locale/zh_CN/foreman_openscap.edit.po +0 -1868
- data/locale/zh_CN/foreman_openscap.po.time_stamp +0 -0
- data/locale/zh_TW/foreman_openscap.edit.po +0 -1864
- data/locale/zh_TW/foreman_openscap.po.time_stamp +0 -0
- data/test/factories/oval_content_factory.rb +0 -7
- data/test/factories/oval_policy_factory.rb +0 -9
- data/test/fixtures/cve_fixtures.rb +0 -104
- data/test/functional/api/v2/compliance/oval_contents_controller_test.rb +0 -39
- data/test/functional/api/v2/compliance/oval_policies_controller_test.rb +0 -141
- data/test/functional/api/v2/compliance/oval_reports_controller_test.rb +0 -32
- data/test/graphql/mutations/oval_policies/delete_mutation_test.rb +0 -63
- data/test/graphql/queries/oval_content_query_test.rb +0 -29
- data/test/graphql/queries/oval_contents_query_test.rb +0 -35
- data/test/graphql/queries/oval_policies_query_test.rb +0 -35
- data/test/unit/oval_host_test.rb +0 -45
- data/test/unit/oval_policy_test.rb +0 -133
- data/test/unit/oval_status_test.rb +0 -47
- data/test/unit/services/oval/cves_test.rb +0 -81
- data/test/unit/services/oval/setup_check_test.rb +0 -37
- data/test/unit/services/oval/setup_test.rb +0 -87
- data/webpack/graphql/mutations/createOvalPolicy.gql +0 -22
- data/webpack/graphql/mutations/deleteOvalContent.gql +0 -9
- data/webpack/graphql/mutations/deleteOvalPolicy.gql +0 -9
- data/webpack/graphql/mutations/updateOvalPolicy.gql +0 -14
- data/webpack/graphql/queries/currentUserAttributes.gql +0 -11
- data/webpack/graphql/queries/cves.gql +0 -23
- data/webpack/graphql/queries/hostgroups.gql +0 -14
- data/webpack/graphql/queries/ovalContent.gql +0 -8
- data/webpack/graphql/queries/ovalContents.gql +0 -19
- data/webpack/graphql/queries/ovalPolicies.gql +0 -20
- data/webpack/graphql/queries/ovalPolicy.gql +0 -29
- data/webpack/helpers/pathsHelper.js +0 -29
- data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js +0 -71
- data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js +0 -83
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.fixtures.js +0 -105
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.test.js +0 -124
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js +0 -127
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.test.js +0 -89
- data/webpack/routes/OvalContents/OvalContentsIndex/index.js +0 -13
- data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.js +0 -138
- data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.scss +0 -3
- data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNewHelper.js +0 -73
- data/webpack/routes/OvalContents/OvalContentsNew/__tests__/OvalContentsNew.test.js +0 -104
- data/webpack/routes/OvalContents/OvalContentsNew/index.js +0 -13
- data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.js +0 -62
- data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.test.js +0 -45
- data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShowHelper.js +0 -0
- data/webpack/routes/OvalContents/OvalContentsShow/index.js +0 -35
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesIndex.js +0 -62
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js +0 -74
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.fixtures.js +0 -101
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.test.js +0 -117
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js +0 -111
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js +0 -81
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js +0 -13
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/HostgroupSelect.js +0 -135
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyForm.js +0 -119
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyFormHelpers.js +0 -107
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/OvalPoliciesNew.js +0 -32
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.fixtures.js +0 -147
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.test.js +0 -172
- data/webpack/routes/OvalPolicies/OvalPoliciesNew/index.js +0 -11
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js +0 -49
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js +0 -63
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/DetailsTab.js +0 -87
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTab.js +0 -49
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTable.js +0 -38
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShow.js +0 -82
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js +0 -117
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.fixtures.js +0 -48
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.test.js +0 -202
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js +0 -124
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.test.js +0 -172
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/index.js +0 -39
- data/webpack/routes/routes.js +0 -49
@@ -1,111 +0,0 @@
|
|
1
|
-
import policiesQuery from '../../../../graphql/queries/ovalPolicies.gql';
|
2
|
-
import { ovalPoliciesPath } from '../../../../helpers/pathsHelper';
|
3
|
-
import {
|
4
|
-
mockFactory,
|
5
|
-
admin,
|
6
|
-
intruder,
|
7
|
-
userFactory,
|
8
|
-
} from '../../../../testHelper';
|
9
|
-
|
10
|
-
const policiesMockFactory = mockFactory('ovalPolicies', policiesQuery);
|
11
|
-
|
12
|
-
export const pushMock = jest.fn();
|
13
|
-
|
14
|
-
export const pageParamsHistoryMock = {
|
15
|
-
location: {
|
16
|
-
search: '?page=2&perPage=5',
|
17
|
-
pathname: ovalPoliciesPath,
|
18
|
-
},
|
19
|
-
push: pushMock,
|
20
|
-
};
|
21
|
-
|
22
|
-
const viewer = userFactory('viewer', [
|
23
|
-
{
|
24
|
-
__typename: 'Permission',
|
25
|
-
id: 'MDE6UGVybWlzc2lvbi0yOTY=',
|
26
|
-
name: 'view_oval_policies',
|
27
|
-
},
|
28
|
-
]);
|
29
|
-
|
30
|
-
const firstPolicy = (meta = { canDestroy: true }) => ({
|
31
|
-
__typename: 'ForemanOpenscap::OvalPolicy',
|
32
|
-
id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTE=',
|
33
|
-
name: 'first policy',
|
34
|
-
meta,
|
35
|
-
ovalContent: { name: 'first content' },
|
36
|
-
});
|
37
|
-
const secondPolicy = (meta = { canDestroy: true }) => ({
|
38
|
-
__typename: 'ForemanOpenscap::OvalPolicy',
|
39
|
-
id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTQw',
|
40
|
-
name: 'second policy',
|
41
|
-
meta,
|
42
|
-
ovalContent: { name: 'second content' },
|
43
|
-
});
|
44
|
-
const policiesData = {
|
45
|
-
totalCount: 2,
|
46
|
-
nodes: [firstPolicy(), secondPolicy()],
|
47
|
-
};
|
48
|
-
|
49
|
-
export const mocks = policiesMockFactory(
|
50
|
-
{ first: 20, last: 20 },
|
51
|
-
policiesData,
|
52
|
-
{ currentUser: admin }
|
53
|
-
);
|
54
|
-
export const pageParamsMocks = policiesMockFactory(
|
55
|
-
{ first: 10, last: 5 },
|
56
|
-
{
|
57
|
-
totalCount: 7,
|
58
|
-
nodes: [
|
59
|
-
{
|
60
|
-
__typename: 'ForemanOpenscap::OvalPolicy',
|
61
|
-
id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTQx',
|
62
|
-
name: 'sixth policy',
|
63
|
-
meta: { canDestroy: true },
|
64
|
-
ovalContent: { name: 'sixth content' },
|
65
|
-
},
|
66
|
-
{
|
67
|
-
__typename: 'ForemanOpenscap::OvalPolicy',
|
68
|
-
id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTQy',
|
69
|
-
name: 'seventh policy',
|
70
|
-
meta: { canDestroy: true },
|
71
|
-
ovalContent: { name: 'seventh content' },
|
72
|
-
},
|
73
|
-
],
|
74
|
-
},
|
75
|
-
{ currentUser: admin }
|
76
|
-
);
|
77
|
-
|
78
|
-
export const emptyMocks = policiesMockFactory(
|
79
|
-
{ first: 20, last: 20 },
|
80
|
-
{ totalCount: 0, nodes: [] },
|
81
|
-
{ currentUser: admin }
|
82
|
-
);
|
83
|
-
export const errorMocks = policiesMockFactory(
|
84
|
-
{ first: 20, last: 20 },
|
85
|
-
{ totalCount: 0, nodes: [] },
|
86
|
-
{
|
87
|
-
errors: [{ message: 'Something very bad happened.', path: 'base' }],
|
88
|
-
currentUser: admin,
|
89
|
-
}
|
90
|
-
);
|
91
|
-
export const viewerMocks = policiesMockFactory(
|
92
|
-
{ first: 20, last: 20 },
|
93
|
-
policiesData,
|
94
|
-
{ currentUser: viewer }
|
95
|
-
);
|
96
|
-
export const unauthorizedMocks = policiesMockFactory(
|
97
|
-
{ first: 20, last: 20 },
|
98
|
-
policiesData,
|
99
|
-
{ currentUser: intruder }
|
100
|
-
);
|
101
|
-
export const noDeleteMocks = policiesMockFactory(
|
102
|
-
{ first: 20, last: 20 },
|
103
|
-
{
|
104
|
-
totalCount: 2,
|
105
|
-
nodes: [
|
106
|
-
firstPolicy({ canDestroy: false }),
|
107
|
-
secondPolicy({ canDestroy: false }),
|
108
|
-
],
|
109
|
-
},
|
110
|
-
{ currentUser: admin }
|
111
|
-
);
|
@@ -1,81 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { render, screen, waitFor } from '@testing-library/react';
|
3
|
-
import '@testing-library/jest-dom';
|
4
|
-
|
5
|
-
import {
|
6
|
-
withMockedProvider,
|
7
|
-
withRouter,
|
8
|
-
withRedux,
|
9
|
-
tick,
|
10
|
-
historyMock,
|
11
|
-
} from '../../../../testHelper';
|
12
|
-
|
13
|
-
import {
|
14
|
-
mocks,
|
15
|
-
emptyMocks,
|
16
|
-
errorMocks,
|
17
|
-
viewerMocks,
|
18
|
-
unauthorizedMocks,
|
19
|
-
} from './OvalPoliciesIndex.fixtures';
|
20
|
-
|
21
|
-
import OvalPoliciesIndex from '../index';
|
22
|
-
|
23
|
-
const TestComponent = withRouter(
|
24
|
-
withRedux(withMockedProvider(OvalPoliciesIndex))
|
25
|
-
);
|
26
|
-
|
27
|
-
describe('OvalPoliciesIndex', () => {
|
28
|
-
it('should load page', async () => {
|
29
|
-
render(<TestComponent history={historyMock} mocks={mocks} />);
|
30
|
-
expect(screen.getByText('Loading')).toBeInTheDocument();
|
31
|
-
await waitFor(tick);
|
32
|
-
expect(screen.getByText('first policy')).toBeInTheDocument();
|
33
|
-
expect(screen.getByText('second policy')).toBeInTheDocument();
|
34
|
-
expect(screen.getByText('first content')).toBeInTheDocument();
|
35
|
-
expect(screen.getByText('second content')).toBeInTheDocument();
|
36
|
-
|
37
|
-
expect(screen.getByText('first policy').closest('a')).toHaveAttribute(
|
38
|
-
'href',
|
39
|
-
'/experimental/compliance/oval_policies/1'
|
40
|
-
);
|
41
|
-
expect(screen.getByText('second policy').closest('a')).toHaveAttribute(
|
42
|
-
'href',
|
43
|
-
'/experimental/compliance/oval_policies/40'
|
44
|
-
);
|
45
|
-
});
|
46
|
-
it('should show empty state', async () => {
|
47
|
-
render(<TestComponent history={historyMock} mocks={emptyMocks} />);
|
48
|
-
expect(screen.getByText('Loading')).toBeInTheDocument();
|
49
|
-
await waitFor(tick);
|
50
|
-
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
51
|
-
expect(screen.getByText('No OVAL Policies found')).toBeInTheDocument();
|
52
|
-
});
|
53
|
-
it('should show errors', async () => {
|
54
|
-
render(<TestComponent history={historyMock} mocks={errorMocks} />);
|
55
|
-
expect(screen.getByText('Loading')).toBeInTheDocument();
|
56
|
-
await waitFor(tick);
|
57
|
-
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
58
|
-
expect(
|
59
|
-
screen.getByText('Something very bad happened.')
|
60
|
-
).toBeInTheDocument();
|
61
|
-
expect(screen.getByText('Error!')).toBeInTheDocument();
|
62
|
-
});
|
63
|
-
it('should load page for user with permissions', async () => {
|
64
|
-
render(<TestComponent history={historyMock} mocks={viewerMocks} />);
|
65
|
-
await waitFor(tick);
|
66
|
-
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
67
|
-
expect(screen.getByText('first policy')).toBeInTheDocument();
|
68
|
-
});
|
69
|
-
it('should not load page for user without permissions', async () => {
|
70
|
-
render(<TestComponent history={historyMock} mocks={unauthorizedMocks} />);
|
71
|
-
await waitFor(tick);
|
72
|
-
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
73
|
-
expect(screen.queryByText('first policy')).not.toBeInTheDocument();
|
74
|
-
expect(
|
75
|
-
screen.getByText(
|
76
|
-
'You are not authorized to view the page. Request the following permissions from administrator: view_oval_policies.'
|
77
|
-
)
|
78
|
-
).toBeInTheDocument();
|
79
|
-
expect(screen.getByText('Permission denied')).toBeInTheDocument();
|
80
|
-
});
|
81
|
-
});
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { useDispatch } from 'react-redux';
|
3
|
-
import { showToast } from '../../../helpers/toastHelper';
|
4
|
-
|
5
|
-
import OvalPoliciesIndex from './OvalPoliciesIndex';
|
6
|
-
|
7
|
-
const WrappedOvalPoliciesIndex = props => {
|
8
|
-
const dispatch = useDispatch();
|
9
|
-
|
10
|
-
return <OvalPoliciesIndex {...props} showToast={showToast(dispatch)} />;
|
11
|
-
};
|
12
|
-
|
13
|
-
export default WrappedOvalPoliciesIndex;
|
@@ -1,135 +0,0 @@
|
|
1
|
-
import React, { useState } from 'react';
|
2
|
-
import PropTypes from 'prop-types';
|
3
|
-
import { useLazyQuery } from '@apollo/client';
|
4
|
-
import { translate as __, sprintf } from 'foremanReact/common/I18n';
|
5
|
-
import {
|
6
|
-
Select,
|
7
|
-
SelectOption,
|
8
|
-
SelectVariant,
|
9
|
-
FormGroup,
|
10
|
-
} from '@patternfly/react-core';
|
11
|
-
import { ExclamationCircleIcon } from '@patternfly/react-icons';
|
12
|
-
import hostgroupsQuery from '../../../graphql/queries/hostgroups.gql';
|
13
|
-
|
14
|
-
const HostgroupSelect = ({
|
15
|
-
selected,
|
16
|
-
setSelected,
|
17
|
-
hgsError,
|
18
|
-
showError,
|
19
|
-
setShowError,
|
20
|
-
}) => {
|
21
|
-
const [isOpen, setIsOpen] = useState(false);
|
22
|
-
|
23
|
-
const [typingTimeout, setTypingTimeout] = useState(null);
|
24
|
-
|
25
|
-
const [fetchHostgroups, { loading, data, error }] = useLazyQuery(
|
26
|
-
hostgroupsQuery
|
27
|
-
);
|
28
|
-
const results = data?.hostgroups?.nodes ? data.hostgroups.nodes : [];
|
29
|
-
|
30
|
-
const onSelect = (event, selection) => {
|
31
|
-
if (selected.find(item => item.name === selection)) {
|
32
|
-
setSelected(selected.filter(item => item.name !== selection));
|
33
|
-
} else {
|
34
|
-
const hg = results.find(item => item.name === selection);
|
35
|
-
setSelected([...selected, hg]);
|
36
|
-
}
|
37
|
-
};
|
38
|
-
|
39
|
-
const onClear = () => {
|
40
|
-
if (showError) {
|
41
|
-
setShowError(false);
|
42
|
-
}
|
43
|
-
setSelected([]);
|
44
|
-
};
|
45
|
-
|
46
|
-
const onInputChange = value => {
|
47
|
-
if (showError) {
|
48
|
-
setShowError(false);
|
49
|
-
}
|
50
|
-
if (typingTimeout) {
|
51
|
-
clearTimeout(typingTimeout);
|
52
|
-
}
|
53
|
-
const variables = { search: `name ~ ${value}` };
|
54
|
-
setTypingTimeout(setTimeout(() => fetchHostgroups({ variables }), 500));
|
55
|
-
};
|
56
|
-
|
57
|
-
const shouldValidate = (err, shouldShowError) => {
|
58
|
-
if (shouldShowError) {
|
59
|
-
return err ? 'error' : 'success';
|
60
|
-
}
|
61
|
-
return 'noval';
|
62
|
-
};
|
63
|
-
|
64
|
-
const prepareOptions = fetchedResults => {
|
65
|
-
if (loading) {
|
66
|
-
return [
|
67
|
-
<SelectOption isDisabled key={0}>
|
68
|
-
{__('Loading...')}
|
69
|
-
</SelectOption>,
|
70
|
-
];
|
71
|
-
}
|
72
|
-
|
73
|
-
if (error) {
|
74
|
-
return [
|
75
|
-
<SelectOption isDisabled key={0}>
|
76
|
-
{sprintf('Failed to fetch hostgroups, cause: %s', error.message)}
|
77
|
-
</SelectOption>,
|
78
|
-
];
|
79
|
-
}
|
80
|
-
|
81
|
-
if (fetchedResults.length > 20) {
|
82
|
-
return [
|
83
|
-
<SelectOption isDisabled key={0}>
|
84
|
-
{sprintf(
|
85
|
-
'You have %s hostgroups to display. Please refine your search.',
|
86
|
-
fetchedResults.length
|
87
|
-
)}
|
88
|
-
</SelectOption>,
|
89
|
-
];
|
90
|
-
}
|
91
|
-
|
92
|
-
return fetchedResults.map((hg, idx) => (
|
93
|
-
<SelectOption key={hg.id} value={hg.name} />
|
94
|
-
));
|
95
|
-
};
|
96
|
-
|
97
|
-
return (
|
98
|
-
<FormGroup
|
99
|
-
label={__('Hostgroups')}
|
100
|
-
helperTextInvalidIcon={<ExclamationCircleIcon />}
|
101
|
-
helperTextInvalid={showError && hgsError}
|
102
|
-
validated={shouldValidate(hgsError, showError)}
|
103
|
-
>
|
104
|
-
<Select
|
105
|
-
variant={SelectVariant.typeaheadMulti}
|
106
|
-
typeAheadAriaLabel="Select a hostgroup"
|
107
|
-
placeholderText={__('Type a hostgroup name...')}
|
108
|
-
onToggle={() => setIsOpen(!isOpen)}
|
109
|
-
onSelect={onSelect}
|
110
|
-
onClear={onClear}
|
111
|
-
selections={selected.map(item => item.name)}
|
112
|
-
isOpen={isOpen}
|
113
|
-
onTypeaheadInputChanged={onInputChange}
|
114
|
-
validated={shouldValidate(hgsError, showError)}
|
115
|
-
>
|
116
|
-
{prepareOptions(results)}
|
117
|
-
</Select>
|
118
|
-
</FormGroup>
|
119
|
-
);
|
120
|
-
};
|
121
|
-
|
122
|
-
HostgroupSelect.propTypes = {
|
123
|
-
selected: PropTypes.array,
|
124
|
-
setSelected: PropTypes.func.isRequired,
|
125
|
-
hgsError: PropTypes.string,
|
126
|
-
showError: PropTypes.bool.isRequired,
|
127
|
-
setShowError: PropTypes.func.isRequired,
|
128
|
-
};
|
129
|
-
|
130
|
-
HostgroupSelect.defaultProps = {
|
131
|
-
selected: [],
|
132
|
-
hgsError: '',
|
133
|
-
};
|
134
|
-
|
135
|
-
export default HostgroupSelect;
|
@@ -1,119 +0,0 @@
|
|
1
|
-
import React, { useState } from 'react';
|
2
|
-
import PropTypes from 'prop-types';
|
3
|
-
import { Formik, Field as FormikField } from 'formik';
|
4
|
-
import { useMutation } from '@apollo/client';
|
5
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
-
import { Button, Form as PfForm, ActionGroup } from '@patternfly/react-core';
|
7
|
-
|
8
|
-
import createOvalPolicy from '../../../graphql/mutations/createOvalPolicy.gql';
|
9
|
-
|
10
|
-
import {
|
11
|
-
TextField,
|
12
|
-
TextAreaField,
|
13
|
-
SelectField,
|
14
|
-
} from '../../../helpers/formFieldsHelper';
|
15
|
-
import HostgroupSelect from './HostgroupSelect';
|
16
|
-
import withLoading from '../../../components/withLoading';
|
17
|
-
|
18
|
-
import { ovalPoliciesPath } from '../../../helpers/pathsHelper';
|
19
|
-
import LinkButton from '../../../components/LinkButton';
|
20
|
-
|
21
|
-
import {
|
22
|
-
createValidationSchema,
|
23
|
-
onSubmit,
|
24
|
-
initialValues,
|
25
|
-
} from './NewOvalPolicyFormHelpers';
|
26
|
-
|
27
|
-
const NewOvalPolicyForm = ({ history, showToast, ovalContents }) => {
|
28
|
-
const [callMutation] = useMutation(createOvalPolicy);
|
29
|
-
|
30
|
-
const [assignedHgs, setAssignedHgs] = useState([]);
|
31
|
-
const [hgsShowError, setHgsShowError] = useState(false);
|
32
|
-
const [hgsError, setHgsError] = useState('');
|
33
|
-
|
34
|
-
const onHgsError = error => {
|
35
|
-
setHgsShowError(true);
|
36
|
-
setHgsError(error);
|
37
|
-
};
|
38
|
-
|
39
|
-
return (
|
40
|
-
<Formik
|
41
|
-
onSubmit={onSubmit(
|
42
|
-
history,
|
43
|
-
showToast,
|
44
|
-
callMutation,
|
45
|
-
assignedHgs,
|
46
|
-
onHgsError
|
47
|
-
)}
|
48
|
-
initialValues={initialValues}
|
49
|
-
validationSchema={createValidationSchema()}
|
50
|
-
>
|
51
|
-
{formProps => (
|
52
|
-
<PfForm>
|
53
|
-
<FormikField
|
54
|
-
name="name"
|
55
|
-
component={TextField}
|
56
|
-
label={__('Name')}
|
57
|
-
isRequired
|
58
|
-
/>
|
59
|
-
<FormikField
|
60
|
-
name="description"
|
61
|
-
component={TextAreaField}
|
62
|
-
label={__('Description')}
|
63
|
-
/>
|
64
|
-
<FormikField
|
65
|
-
name="cronLine"
|
66
|
-
component={TextField}
|
67
|
-
label={__('Schedule')}
|
68
|
-
isRequired
|
69
|
-
/>
|
70
|
-
<FormikField
|
71
|
-
name="ovalContentId"
|
72
|
-
component={SelectField}
|
73
|
-
selectItems={ovalContents}
|
74
|
-
label={__('OVAL Content')}
|
75
|
-
isRequired
|
76
|
-
blankLabel={__('Choose OVAL Content')}
|
77
|
-
/>
|
78
|
-
<HostgroupSelect
|
79
|
-
selected={assignedHgs}
|
80
|
-
setSelected={setAssignedHgs}
|
81
|
-
showError={hgsShowError}
|
82
|
-
setShowError={setHgsShowError}
|
83
|
-
hgsError={hgsError}
|
84
|
-
isDisabled={formProps.isSubmitting}
|
85
|
-
/>
|
86
|
-
<ActionGroup>
|
87
|
-
<Button
|
88
|
-
variant="primary"
|
89
|
-
onClick={formProps.handleSubmit}
|
90
|
-
isDisabled={
|
91
|
-
!formProps.isValid ||
|
92
|
-
formProps.isSubmitting ||
|
93
|
-
(hgsShowError && hgsError)
|
94
|
-
}
|
95
|
-
aria-label="submit"
|
96
|
-
>
|
97
|
-
{__('Submit')}
|
98
|
-
</Button>
|
99
|
-
<LinkButton
|
100
|
-
path={ovalPoliciesPath}
|
101
|
-
btnVariant="link"
|
102
|
-
btnText={__('Cancel')}
|
103
|
-
btnAriaLabel="cancel"
|
104
|
-
isDisabled={formProps.isSubmitting}
|
105
|
-
/>
|
106
|
-
</ActionGroup>
|
107
|
-
</PfForm>
|
108
|
-
)}
|
109
|
-
</Formik>
|
110
|
-
);
|
111
|
-
};
|
112
|
-
|
113
|
-
NewOvalPolicyForm.propTypes = {
|
114
|
-
history: PropTypes.object.isRequired,
|
115
|
-
showToast: PropTypes.func.isRequired,
|
116
|
-
ovalContents: PropTypes.array.isRequired,
|
117
|
-
};
|
118
|
-
|
119
|
-
export default withLoading(NewOvalPolicyForm);
|
@@ -1,107 +0,0 @@
|
|
1
|
-
import * as Yup from 'yup';
|
2
|
-
import { translate as __, sprintf } from 'foremanReact/common/I18n';
|
3
|
-
|
4
|
-
import { ovalPoliciesPath } from '../../../helpers/pathsHelper';
|
5
|
-
import { decodeId, decodeModelId } from '../../../helpers/globalIdHelper';
|
6
|
-
|
7
|
-
export const createValidationSchema = () => {
|
8
|
-
const cantBeBlank = __("can't be blank");
|
9
|
-
|
10
|
-
return Yup.object().shape({
|
11
|
-
name: Yup.string().required(cantBeBlank),
|
12
|
-
ovalContentId: Yup.string().required(cantBeBlank),
|
13
|
-
cronLine: Yup.string().test(
|
14
|
-
'is-cron',
|
15
|
-
__('is not a valid cronline'),
|
16
|
-
value => value && value.trim().split(' ').length === 5
|
17
|
-
),
|
18
|
-
});
|
19
|
-
};
|
20
|
-
|
21
|
-
const partitionById = (array, name) => {
|
22
|
-
const res = array.reduce(
|
23
|
-
(memo, item) => {
|
24
|
-
if (item.id === name) {
|
25
|
-
memo.left.push(item);
|
26
|
-
} else {
|
27
|
-
memo.right.push(item);
|
28
|
-
}
|
29
|
-
return memo;
|
30
|
-
},
|
31
|
-
{ left: [], right: [] }
|
32
|
-
);
|
33
|
-
return [res.left, res.right];
|
34
|
-
};
|
35
|
-
|
36
|
-
const checksToMessage = checks =>
|
37
|
-
checks.reduce((memo, check) => [...memo, check.failMsg], []).join(' ');
|
38
|
-
|
39
|
-
export const onSubmit = (
|
40
|
-
history,
|
41
|
-
showToast,
|
42
|
-
callMutation,
|
43
|
-
assignedHgs,
|
44
|
-
setHgsError
|
45
|
-
) => (values, actions) => {
|
46
|
-
const onCompleted = response => {
|
47
|
-
const failedChecks = response.data.createOvalPolicy.checkCollection.filter(
|
48
|
-
check => check.result === 'fail'
|
49
|
-
);
|
50
|
-
if (failedChecks.length === 0) {
|
51
|
-
history.push(ovalPoliciesPath);
|
52
|
-
showToast({
|
53
|
-
type: 'success',
|
54
|
-
message: __('OVAL Policy succesfully created.'),
|
55
|
-
});
|
56
|
-
} else {
|
57
|
-
actions.setSubmitting(false);
|
58
|
-
|
59
|
-
const [validationChecks, withoutValidationChecks] = partitionById(
|
60
|
-
failedChecks,
|
61
|
-
'oval_policy_errors'
|
62
|
-
);
|
63
|
-
|
64
|
-
const [hgChecks, remainingChecks] = partitionById(
|
65
|
-
withoutValidationChecks,
|
66
|
-
'hostgroups_without_proxy'
|
67
|
-
);
|
68
|
-
if (validationChecks.length === 1) {
|
69
|
-
actions.setErrors(validationChecks[0].errors);
|
70
|
-
}
|
71
|
-
if (hgChecks.length > 0) {
|
72
|
-
setHgsError(checksToMessage(hgChecks));
|
73
|
-
}
|
74
|
-
if (remainingChecks.length > 0) {
|
75
|
-
showToast({
|
76
|
-
type: 'error',
|
77
|
-
message: checksToMessage(remainingChecks),
|
78
|
-
});
|
79
|
-
}
|
80
|
-
}
|
81
|
-
};
|
82
|
-
|
83
|
-
const onError = response => {
|
84
|
-
showToast({
|
85
|
-
type: 'error',
|
86
|
-
message: sprintf(__('Failed to create OVAL Policy: %s'), response.error),
|
87
|
-
});
|
88
|
-
actions.setSubmitting(false);
|
89
|
-
};
|
90
|
-
|
91
|
-
const hostgroupIds = assignedHgs.map(decodeModelId);
|
92
|
-
const variables = {
|
93
|
-
...values,
|
94
|
-
ovalContentId: decodeId(values.ovalContentId),
|
95
|
-
period: 'custom',
|
96
|
-
hostgroupIds,
|
97
|
-
};
|
98
|
-
// eslint-disable-next-line promise/prefer-await-to-then
|
99
|
-
callMutation({ variables }).then(onCompleted, onError);
|
100
|
-
};
|
101
|
-
|
102
|
-
export const initialValues = {
|
103
|
-
name: '',
|
104
|
-
description: '',
|
105
|
-
ovalContentId: '',
|
106
|
-
cronLine: '',
|
107
|
-
};
|
@@ -1,32 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { useQuery } from '@apollo/client';
|
3
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
-
import IndexLayout from '../../../components/IndexLayout';
|
5
|
-
|
6
|
-
import ovalContentsQuery from '../../../graphql/queries/ovalContents.gql';
|
7
|
-
import NewOvalPolicyForm from './NewOvalPolicyForm';
|
8
|
-
|
9
|
-
const OvalPoliciesNew = props => {
|
10
|
-
const useFetchFn = () => useQuery(ovalContentsQuery);
|
11
|
-
|
12
|
-
const renameData = data => ({
|
13
|
-
ovalContents: data.ovalContents.nodes,
|
14
|
-
});
|
15
|
-
|
16
|
-
return (
|
17
|
-
<IndexLayout pageTitle={__('Create OVAL Policy')}>
|
18
|
-
<NewOvalPolicyForm
|
19
|
-
fetchFn={useFetchFn}
|
20
|
-
renameData={renameData}
|
21
|
-
resultPath="ovalContents.nodes"
|
22
|
-
emptyStateTitle={__('No OVAL Content found')}
|
23
|
-
emptyStateBody={__(
|
24
|
-
'OVAL Content is required to create OVAL Policy. Please create one before proceeding.'
|
25
|
-
)}
|
26
|
-
{...props}
|
27
|
-
/>
|
28
|
-
</IndexLayout>
|
29
|
-
);
|
30
|
-
};
|
31
|
-
|
32
|
-
export default OvalPoliciesNew;
|