foreman_openscap 4.3.1 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/compliance/arf_reports_controller.rb +0 -6
- data/app/controllers/api/v2/compliance/oval_policies_controller.rb +1 -1
- data/app/graphql/mutations/oval_contents/delete.rb +9 -0
- data/app/graphql/mutations/oval_policies/delete.rb +9 -0
- data/app/graphql/mutations/oval_policies/update.rb +15 -0
- data/app/graphql/types/oval_check.rb +11 -0
- data/app/graphql/types/oval_content.rb +2 -0
- data/app/graphql/types/oval_policy.rb +3 -0
- data/app/helpers/arf_report_dashboard_helper.rb +2 -4
- data/app/helpers/compliance_hosts_helper.rb +1 -1
- data/app/helpers/policies_helper.rb +1 -1
- data/app/models/concerns/foreman_openscap/host_extensions.rb +0 -6
- data/app/models/concerns/foreman_openscap/oval_facet_hostgroup_extensions.rb +15 -0
- data/app/models/foreman_openscap/oval_content.rb +2 -0
- data/app/services/foreman_openscap/client_config/base.rb +1 -0
- data/app/services/foreman_openscap/client_config/puppet.rb +6 -2
- data/app/services/foreman_openscap/oval/configure.rb +1 -1
- data/app/services/foreman_openscap/oval/setup.rb +5 -5
- data/app/services/foreman_openscap/oval/setup_check.rb +5 -2
- data/app/views/api/v2/compliance/oval_contents/destroy.json.rabl +3 -0
- data/app/views/arf_reports/_metrics.html.erb +4 -4
- data/app/views/compliance_hosts/show.html.erb +4 -6
- data/app/views/dashboard/_compliance_reports_breakdown_widget.html.erb +4 -3
- data/app/views/policy_dashboard/_policy_chart_widget.html.erb +3 -2
- data/db/migrate/20200117135424_migrate_port_overrides_to_int.rb +2 -1
- data/db/migrate/20201202110213_update_puppet_port_param_type.rb +2 -1
- data/db/migrate/20210819143316_drop_unused_tables.rb +6 -0
- data/lib/foreman_openscap/engine.rb +5 -7
- data/lib/foreman_openscap/version.rb +1 -1
- data/package.json +3 -6
- data/test/functional/api/v2/compliance/oval_reports_controller_test.rb +1 -1
- data/test/functional/api/v2/compliance/policies_controller_test.rb +2 -0
- data/test/graphql/mutations/oval_policies/delete_mutation_test.rb +63 -0
- data/test/graphql/queries/oval_content_query_test.rb +29 -0
- data/test/helpers/arf_report_dashboard_helper_test.rb +9 -10
- data/test/helpers/policy_dashboard_helper_test.rb +1 -1
- data/test/test_plugin_helper.rb +9 -4
- data/test/unit/policy_test.rb +1 -1
- data/test/unit/services/config_name_service_test.rb +1 -0
- data/test/unit/services/hostgroup_overrider_test.rb +2 -1
- data/test/unit/services/lookup_key_overrider_test.rb +4 -1
- data/test/unit/services/oval/setup_check_test.rb +37 -0
- data/webpack/components/ConfirmModal.js +63 -0
- data/webpack/components/ConfirmModal.scss +3 -0
- data/webpack/components/EditableInput.js +157 -0
- data/webpack/components/EditableInput.scss +3 -0
- data/webpack/components/EmptyState.js +12 -3
- data/webpack/components/IndexLayout.js +11 -4
- data/webpack/components/IndexTable/index.js +17 -18
- data/webpack/components/LinkButton.js +26 -0
- data/webpack/components/withDeleteModal.js +51 -0
- data/webpack/components/withLoading.js +41 -4
- data/webpack/graphql/mutations/deleteOvalContent.gql +9 -0
- data/webpack/graphql/mutations/deleteOvalPolicy.gql +9 -0
- data/webpack/graphql/mutations/updateOvalPolicy.gql +14 -0
- data/webpack/graphql/queries/currentUserAttributes.gql +11 -0
- data/webpack/graphql/queries/cves.gql +5 -0
- data/webpack/graphql/queries/hostgroups.gql +14 -0
- data/webpack/graphql/queries/ovalContent.gql +8 -0
- data/webpack/graphql/queries/ovalContents.gql +8 -0
- data/webpack/graphql/queries/ovalPolicies.gql +8 -0
- data/webpack/graphql/queries/ovalPolicy.gql +5 -0
- data/webpack/helpers/formFieldsHelper.js +63 -0
- data/webpack/helpers/mutationHelper.js +68 -0
- data/webpack/helpers/pathsHelper.js +5 -0
- data/webpack/helpers/permissionsHelper.js +42 -0
- data/webpack/helpers/toastHelper.js +3 -0
- data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js +26 -0
- data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js +50 -5
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.fixtures.js +105 -0
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.test.js +124 -0
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js +93 -77
- data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.test.js +53 -6
- data/webpack/routes/OvalContents/OvalContentsIndex/index.js +7 -1
- data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.js +138 -0
- data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.scss +3 -0
- data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNewHelper.js +73 -0
- data/webpack/routes/OvalContents/OvalContentsNew/__tests__/OvalContentsNew.test.js +104 -0
- data/webpack/routes/OvalContents/OvalContentsNew/index.js +13 -0
- data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.js +62 -0
- data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.test.js +45 -0
- data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShowHelper.js +0 -0
- data/webpack/routes/OvalContents/OvalContentsShow/index.js +35 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesIndex.js +18 -2
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js +16 -3
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.fixtures.js +101 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.test.js +117 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js +71 -21
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js +34 -2
- data/webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js +7 -1
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js +1 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/DetailsTab.js +85 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTab.js +49 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTable.js +38 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShow.js +15 -12
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js +77 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.fixtures.js +48 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.test.js +175 -0
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js +40 -4
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.test.js +64 -4
- data/webpack/routes/OvalPolicies/OvalPoliciesShow/index.js +4 -0
- data/webpack/routes/routes.js +14 -0
- data/webpack/testHelper.js +42 -2
- metadata +53 -7
@@ -0,0 +1,175 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
4
|
+
import '@testing-library/jest-dom';
|
5
|
+
import userEvent from '@testing-library/user-event';
|
6
|
+
|
7
|
+
import OvalPoliciesShow from '../';
|
8
|
+
import {
|
9
|
+
historyMock,
|
10
|
+
ovalPolicyId,
|
11
|
+
policyDetailMock,
|
12
|
+
ovalPolicy,
|
13
|
+
} from './OvalPoliciesShow.fixtures';
|
14
|
+
import {
|
15
|
+
policyUpdateMock,
|
16
|
+
policyUpdateErrorMock,
|
17
|
+
policyUpdateValidationMock,
|
18
|
+
updatedName,
|
19
|
+
} from './OvalPoliciesEdit.fixtures';
|
20
|
+
import { ovalPoliciesShowPath } from '../../../../helpers/pathsHelper';
|
21
|
+
|
22
|
+
import {
|
23
|
+
withMockedProvider,
|
24
|
+
tick,
|
25
|
+
withRouter,
|
26
|
+
withRedux,
|
27
|
+
} from '../../../../testHelper';
|
28
|
+
|
29
|
+
import * as toasts from '../../../../helpers/toastHelper';
|
30
|
+
|
31
|
+
const TestComponent = withRouter(
|
32
|
+
withRedux(withMockedProvider(OvalPoliciesShow))
|
33
|
+
);
|
34
|
+
|
35
|
+
describe('OvalPoliciesShow', () => {
|
36
|
+
it('should open and close inline edit for name', async () => {
|
37
|
+
render(
|
38
|
+
<TestComponent
|
39
|
+
history={historyMock}
|
40
|
+
match={{
|
41
|
+
params: { id: ovalPolicyId, tab: 'details' },
|
42
|
+
path: ovalPoliciesShowPath,
|
43
|
+
}}
|
44
|
+
mocks={policyDetailMock}
|
45
|
+
/>
|
46
|
+
);
|
47
|
+
await waitFor(tick);
|
48
|
+
userEvent.click(screen.getByRole('button', { name: 'edit name' }));
|
49
|
+
userEvent.clear(screen.getByLabelText(/name text input/));
|
50
|
+
userEvent.type(screen.getByLabelText(/name text input/), 'foo');
|
51
|
+
expect(screen.getByLabelText(/name text input/)).toHaveAttribute(
|
52
|
+
'value',
|
53
|
+
'foo'
|
54
|
+
);
|
55
|
+
userEvent.click(
|
56
|
+
screen.getByRole('button', { name: 'cancel editing name' })
|
57
|
+
);
|
58
|
+
expect(screen.queryByText('foo')).not.toBeInTheDocument();
|
59
|
+
});
|
60
|
+
it('should update policy name', async () => {
|
61
|
+
const showToast = jest.fn();
|
62
|
+
jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
|
63
|
+
|
64
|
+
const { container } = render(
|
65
|
+
<TestComponent
|
66
|
+
history={historyMock}
|
67
|
+
match={{
|
68
|
+
params: { id: ovalPolicyId, tab: 'details' },
|
69
|
+
path: ovalPoliciesShowPath,
|
70
|
+
}}
|
71
|
+
mocks={policyDetailMock.concat(policyUpdateMock)}
|
72
|
+
/>
|
73
|
+
);
|
74
|
+
await waitFor(tick);
|
75
|
+
const editBtn = screen.getByRole('button', { name: 'edit name' });
|
76
|
+
expect(editBtn).toBeInTheDocument();
|
77
|
+
expect(
|
78
|
+
screen.queryByRole('button', { name: 'submit name' })
|
79
|
+
).not.toBeInTheDocument();
|
80
|
+
|
81
|
+
userEvent.click(editBtn);
|
82
|
+
expect(
|
83
|
+
screen.queryByRole('button', { name: 'edit name' })
|
84
|
+
).not.toBeInTheDocument();
|
85
|
+
const inputField = screen.getByLabelText(/name text input/);
|
86
|
+
const submitBtn = screen.getByRole('button', { name: 'submit name' });
|
87
|
+
const cancelBtn = screen.getByRole('button', {
|
88
|
+
name: 'cancel editing name',
|
89
|
+
});
|
90
|
+
|
91
|
+
userEvent.clear(inputField);
|
92
|
+
userEvent.type(inputField, updatedName);
|
93
|
+
userEvent.click(submitBtn);
|
94
|
+
expect(inputField).toBeDisabled();
|
95
|
+
expect(submitBtn).toBeDisabled();
|
96
|
+
expect(cancelBtn).toBeDisabled();
|
97
|
+
const spinner = container.querySelector('#edit-name-spinner');
|
98
|
+
expect(spinner).toBeInTheDocument();
|
99
|
+
await waitFor(tick);
|
100
|
+
expect(showToast).toHaveBeenCalledWith({
|
101
|
+
type: 'success',
|
102
|
+
message: 'OVAL policy was successfully updated.',
|
103
|
+
});
|
104
|
+
|
105
|
+
expect(inputField).not.toBeInTheDocument();
|
106
|
+
expect(editBtn).toBeInTheDocument();
|
107
|
+
expect(cancelBtn).not.toBeInTheDocument();
|
108
|
+
expect(
|
109
|
+
screen.queryByRole('button', { name: 'submit name' })
|
110
|
+
).not.toBeInTheDocument();
|
111
|
+
await waitFor(tick);
|
112
|
+
expect(screen.getAllByText(updatedName).pop()).toBeInTheDocument();
|
113
|
+
});
|
114
|
+
it('should show unexpected errors', async () => {
|
115
|
+
const showToast = jest.fn();
|
116
|
+
jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
|
117
|
+
|
118
|
+
render(
|
119
|
+
<TestComponent
|
120
|
+
history={historyMock}
|
121
|
+
match={{
|
122
|
+
params: { id: ovalPolicyId, tab: 'details' },
|
123
|
+
path: ovalPoliciesShowPath,
|
124
|
+
}}
|
125
|
+
mocks={policyDetailMock.concat(policyUpdateErrorMock)}
|
126
|
+
/>
|
127
|
+
);
|
128
|
+
await waitFor(tick);
|
129
|
+
const editBtn = screen.getByRole('button', { name: 'edit name' });
|
130
|
+
userEvent.click(editBtn);
|
131
|
+
const inputField = screen.getByLabelText(/name text input/);
|
132
|
+
userEvent.clear(inputField);
|
133
|
+
userEvent.type(inputField, updatedName);
|
134
|
+
userEvent.click(screen.getByRole('button', { name: 'submit name' }));
|
135
|
+
await waitFor(tick);
|
136
|
+
expect(showToast).toHaveBeenCalledWith({
|
137
|
+
type: 'error',
|
138
|
+
message:
|
139
|
+
'There was a following error when updating OVAL policy: This is an unexpected failure.',
|
140
|
+
});
|
141
|
+
expect(inputField).toBeInTheDocument();
|
142
|
+
expect(inputField).not.toBeDisabled();
|
143
|
+
expect(screen.getByText(ovalPolicy.name)).toBeInTheDocument();
|
144
|
+
});
|
145
|
+
it('should show validation errors', async () => {
|
146
|
+
const showToast = jest.fn();
|
147
|
+
jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
|
148
|
+
|
149
|
+
const { container } = render(
|
150
|
+
<TestComponent
|
151
|
+
history={historyMock}
|
152
|
+
match={{
|
153
|
+
params: { id: ovalPolicyId, tab: 'details' },
|
154
|
+
path: ovalPoliciesShowPath,
|
155
|
+
}}
|
156
|
+
mocks={policyDetailMock.concat(policyUpdateValidationMock)}
|
157
|
+
/>
|
158
|
+
);
|
159
|
+
await waitFor(tick);
|
160
|
+
const editBtn = screen.getByRole('button', { name: 'edit name' });
|
161
|
+
userEvent.click(editBtn);
|
162
|
+
const inputField = screen.getByLabelText(/name text input/);
|
163
|
+
userEvent.clear(inputField);
|
164
|
+
userEvent.type(inputField, updatedName);
|
165
|
+
userEvent.click(screen.getByRole('button', { name: 'submit name' }));
|
166
|
+
await waitFor(tick);
|
167
|
+
expect(inputField).toBeInTheDocument();
|
168
|
+
expect(inputField).not.toBeDisabled();
|
169
|
+
expect(
|
170
|
+
container.querySelector('#edit-name-spinner')
|
171
|
+
).not.toBeInTheDocument();
|
172
|
+
expect(screen.getByText(ovalPolicy.name)).toBeInTheDocument();
|
173
|
+
expect(screen.getByText('has already been taken')).toBeInTheDocument();
|
174
|
+
});
|
175
|
+
});
|
@@ -1,11 +1,14 @@
|
|
1
|
-
import { mockFactory } from '../../../../testHelper';
|
1
|
+
import { mockFactory, admin, intruder } from '../../../../testHelper';
|
2
2
|
import ovalPolicyQuery from '../../../../graphql/queries/ovalPolicy.gql';
|
3
3
|
import cvesQuery from '../../../../graphql/queries/cves.gql';
|
4
|
+
import hostgroupsQuery from '../../../../graphql/queries/hostgroups.gql';
|
4
5
|
|
5
6
|
const policyDetailMockFactory = mockFactory('ovalPolicy', ovalPolicyQuery);
|
6
7
|
const cvesMockFactory = mockFactory('cves', cvesQuery);
|
8
|
+
const hostgroupsMockFactory = mockFactory('hostgroups', hostgroupsQuery);
|
7
9
|
|
8
|
-
const ovalPolicy = {
|
10
|
+
export const ovalPolicy = {
|
11
|
+
__typename: 'ForemanOpenscap::OvalPolicy',
|
9
12
|
id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTM=',
|
10
13
|
name: 'Third policy',
|
11
14
|
period: 'weekly',
|
@@ -51,6 +54,20 @@ const cvesResult = {
|
|
51
54
|
],
|
52
55
|
};
|
53
56
|
|
57
|
+
const hostgroupsResult = {
|
58
|
+
totalCount: 2,
|
59
|
+
nodes: [
|
60
|
+
{
|
61
|
+
id: 'MDE6SG9zdGdyb3VwLTQ=',
|
62
|
+
name: 'first hostgroup',
|
63
|
+
},
|
64
|
+
{
|
65
|
+
id: 'MDE6SG9zdGdyb3VwLTEy',
|
66
|
+
name: 'second hostgroup',
|
67
|
+
},
|
68
|
+
],
|
69
|
+
};
|
70
|
+
|
54
71
|
export const ovalPolicyId = 3;
|
55
72
|
|
56
73
|
export const pushMock = jest.fn();
|
@@ -70,9 +87,28 @@ export const historyWithSearch = {
|
|
70
87
|
|
71
88
|
export const policyDetailMock = policyDetailMockFactory(
|
72
89
|
{ id: ovalPolicy.id },
|
73
|
-
ovalPolicy
|
90
|
+
ovalPolicy,
|
91
|
+
{ currentUser: admin }
|
74
92
|
);
|
93
|
+
|
94
|
+
export const policyUnauthorizedMock = policyDetailMockFactory(
|
95
|
+
{ id: ovalPolicy.id },
|
96
|
+
ovalPolicy,
|
97
|
+
{ currentUser: intruder }
|
98
|
+
);
|
99
|
+
|
75
100
|
export const policyCvesMock = cvesMockFactory(
|
76
101
|
{ search: `oval_policy_id = ${ovalPolicyId}`, first: 5, last: 5 },
|
77
|
-
cvesResult
|
102
|
+
cvesResult,
|
103
|
+
{ currentUser: admin }
|
104
|
+
);
|
105
|
+
export const policyHostgroupsMock = hostgroupsMockFactory(
|
106
|
+
{ search: `oval_policy_id = ${ovalPolicyId}`, first: 5, last: 5 },
|
107
|
+
hostgroupsResult,
|
108
|
+
{ currentUser: admin }
|
109
|
+
);
|
110
|
+
export const policyHostgroupsDeniedMock = hostgroupsMockFactory(
|
111
|
+
{ search: `oval_policy_id = ${ovalPolicyId}`, first: 5, last: 5 },
|
112
|
+
{ totalCount: 0, nodes: [] },
|
113
|
+
{ currentUser: intruder }
|
78
114
|
);
|
@@ -12,17 +12,27 @@ import {
|
|
12
12
|
resolvePath,
|
13
13
|
} from '../../../../helpers/pathsHelper';
|
14
14
|
|
15
|
-
import {
|
15
|
+
import {
|
16
|
+
withRedux,
|
17
|
+
withMockedProvider,
|
18
|
+
tick,
|
19
|
+
withRouter,
|
20
|
+
} from '../../../../testHelper';
|
16
21
|
import {
|
17
22
|
policyDetailMock,
|
18
23
|
historyMock,
|
19
24
|
historyWithSearch,
|
20
25
|
pushMock,
|
21
26
|
policyCvesMock,
|
27
|
+
policyHostgroupsMock,
|
28
|
+
policyHostgroupsDeniedMock,
|
22
29
|
ovalPolicyId,
|
30
|
+
policyUnauthorizedMock,
|
23
31
|
} from './OvalPoliciesShow.fixtures';
|
24
32
|
|
25
|
-
const TestComponent =
|
33
|
+
const TestComponent = withRedux(
|
34
|
+
withRouter(withMockedProvider(OvalPoliciesShow))
|
35
|
+
);
|
26
36
|
|
27
37
|
describe('OvalPoliciesShow', () => {
|
28
38
|
it('should load details by default and handle tab change', async () => {
|
@@ -36,7 +46,7 @@ describe('OvalPoliciesShow', () => {
|
|
36
46
|
expect(screen.getByText('Loading')).toBeInTheDocument();
|
37
47
|
await waitFor(tick);
|
38
48
|
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
39
|
-
expect(screen.
|
49
|
+
expect(screen.getAllByText('Third policy').pop()).toBeInTheDocument();
|
40
50
|
expect(screen.getByText('Weekly, on tuesday')).toBeInTheDocument();
|
41
51
|
expect(screen.getByText('A very strict policy')).toBeInTheDocument();
|
42
52
|
const activeTabHeader = container.querySelector(
|
@@ -67,6 +77,22 @@ describe('OvalPoliciesShow', () => {
|
|
67
77
|
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
68
78
|
expect(screen.getByText('Weekly, on tuesday')).toBeInTheDocument();
|
69
79
|
});
|
80
|
+
it('should not load the page when user does not have permissions', async () => {
|
81
|
+
render(
|
82
|
+
<TestComponent
|
83
|
+
history={historyMock}
|
84
|
+
match={{ params: { id: ovalPolicyId }, path: ovalPoliciesShowPath }}
|
85
|
+
mocks={policyUnauthorizedMock}
|
86
|
+
/>
|
87
|
+
);
|
88
|
+
await waitFor(tick);
|
89
|
+
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
90
|
+
expect(
|
91
|
+
screen.getByText(
|
92
|
+
'You are not authorized to view the page. Request the following permissions from administrator: view_oval_policies.'
|
93
|
+
)
|
94
|
+
).toBeInTheDocument();
|
95
|
+
});
|
70
96
|
it('should load CVEs tab when specified in URL', async () => {
|
71
97
|
const mocks = policyDetailMock.concat(policyCvesMock);
|
72
98
|
render(
|
@@ -88,7 +114,7 @@ describe('OvalPoliciesShow', () => {
|
|
88
114
|
it('should have button for scanning all hostgroups', async () => {
|
89
115
|
const btnText = 'Scan All Hostgroups';
|
90
116
|
|
91
|
-
const WithProvider = withMockedProvider(OvalPoliciesShow);
|
117
|
+
const WithProvider = withRedux(withMockedProvider(OvalPoliciesShow));
|
92
118
|
const history = createMemoryHistory();
|
93
119
|
history.push = jest.fn();
|
94
120
|
|
@@ -109,4 +135,38 @@ describe('OvalPoliciesShow', () => {
|
|
109
135
|
'/job_invocations/new?feature=foreman_openscap_run_oval_scans&host_ids=hostgroup_id+%5E+%284+10+12+11%29&inputs%5Boval_policies%5D=3'
|
110
136
|
);
|
111
137
|
});
|
138
|
+
it('should load hostgroups tab when specified in URL', async () => {
|
139
|
+
const mocks = policyDetailMock.concat(policyHostgroupsMock);
|
140
|
+
render(
|
141
|
+
<TestComponent
|
142
|
+
history={historyWithSearch}
|
143
|
+
match={{
|
144
|
+
params: { id: ovalPolicyId, tab: 'hostgroups' },
|
145
|
+
path: ovalPoliciesShowPath,
|
146
|
+
}}
|
147
|
+
mocks={mocks}
|
148
|
+
/>
|
149
|
+
);
|
150
|
+
expect(screen.getByText('Loading')).toBeInTheDocument();
|
151
|
+
await waitFor(tick);
|
152
|
+
await waitFor(tick);
|
153
|
+
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
154
|
+
expect(screen.getByText('first hostgroup')).toBeInTheDocument();
|
155
|
+
});
|
156
|
+
it('should not show hostgroups for a user without permissions', async () => {
|
157
|
+
const mocks = policyDetailMock.concat(policyHostgroupsDeniedMock);
|
158
|
+
render(
|
159
|
+
<TestComponent
|
160
|
+
history={historyWithSearch}
|
161
|
+
match={{
|
162
|
+
params: { id: ovalPolicyId, tab: 'hostgroups' },
|
163
|
+
path: ovalPoliciesShowPath,
|
164
|
+
}}
|
165
|
+
mocks={mocks}
|
166
|
+
/>
|
167
|
+
);
|
168
|
+
await waitFor(tick);
|
169
|
+
await waitFor(tick);
|
170
|
+
expect(screen.getByText('Permission denied')).toBeInTheDocument();
|
171
|
+
});
|
112
172
|
});
|
@@ -1,8 +1,10 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import { useQuery } from '@apollo/client';
|
4
|
+
import { useDispatch } from 'react-redux';
|
4
5
|
|
5
6
|
import { translate as __ } from 'foremanReact/common/I18n';
|
7
|
+
import { showToast } from '../../../helpers/toastHelper';
|
6
8
|
|
7
9
|
import OvalPoliciesShow from './OvalPoliciesShow';
|
8
10
|
import { encodeId } from '../../../helpers/globalIdHelper';
|
@@ -24,6 +26,8 @@ const WrappedOvalPoliciesShow = props => {
|
|
24
26
|
renameData={renameData}
|
25
27
|
resultPath="ovalPolicy"
|
26
28
|
emptyStateTitle={__('No OVAL Policy found')}
|
29
|
+
permissions={['view_oval_policies']}
|
30
|
+
showToast={showToast(useDispatch())}
|
27
31
|
/>
|
28
32
|
);
|
29
33
|
};
|
data/webpack/routes/routes.js
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import OvalContentsIndex from './OvalContents/OvalContentsIndex';
|
3
|
+
import OvalContentsShow from './OvalContents/OvalContentsShow';
|
4
|
+
import OvalContentsNew from './OvalContents/OvalContentsNew';
|
3
5
|
import OvalPoliciesIndex from './OvalPolicies/OvalPoliciesIndex';
|
4
6
|
import OvalPoliciesShow from './OvalPolicies/OvalPoliciesShow';
|
5
7
|
|
6
8
|
import {
|
7
9
|
ovalContentsPath,
|
10
|
+
ovalContentsShowPath,
|
11
|
+
ovalContentsNewPath,
|
8
12
|
ovalPoliciesPath,
|
9
13
|
ovalPoliciesShowPath,
|
10
14
|
} from '../helpers/pathsHelper';
|
@@ -15,6 +19,16 @@ export default [
|
|
15
19
|
render: props => <OvalContentsIndex {...props} />,
|
16
20
|
exact: true,
|
17
21
|
},
|
22
|
+
{
|
23
|
+
path: ovalContentsNewPath,
|
24
|
+
render: props => <OvalContentsNew {...props} />,
|
25
|
+
exact: true,
|
26
|
+
},
|
27
|
+
{
|
28
|
+
path: ovalContentsShowPath,
|
29
|
+
render: props => <OvalContentsShow {...props} />,
|
30
|
+
exact: true,
|
31
|
+
},
|
18
32
|
{
|
19
33
|
path: ovalPoliciesPath,
|
20
34
|
render: props => <OvalPoliciesIndex {...props} />,
|
data/webpack/testHelper.js
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { Provider } from 'react-redux';
|
3
|
+
import store from 'foremanReact/redux';
|
2
4
|
import { MockedProvider } from '@apollo/react-testing';
|
3
5
|
import { MemoryRouter } from 'react-router-dom';
|
4
6
|
import { getForemanContext } from 'foremanReact/Root/Context/ForemanContext';
|
5
7
|
|
8
|
+
export const withRedux = Component => props => (
|
9
|
+
<Provider store={store}>
|
10
|
+
<Component {...props} />
|
11
|
+
</Provider>
|
12
|
+
);
|
13
|
+
|
6
14
|
export const withRouter = Component => props => (
|
7
15
|
<MemoryRouter>
|
8
16
|
<Component {...props} />
|
@@ -24,7 +32,7 @@ export const withMockedProvider = Component => props => {
|
|
24
32
|
|
25
33
|
return (
|
26
34
|
<ForemanContext.Provider value={ctx}>
|
27
|
-
<MockedProvider mocks={mocks}
|
35
|
+
<MockedProvider mocks={mocks}>
|
28
36
|
<Component {...rest} />
|
29
37
|
</MockedProvider>
|
30
38
|
</ForemanContext.Provider>
|
@@ -40,10 +48,38 @@ export const historyMock = {
|
|
40
48
|
},
|
41
49
|
};
|
42
50
|
|
51
|
+
export const admin = {
|
52
|
+
__typename: 'User',
|
53
|
+
id: 'MDE6VXNlci00',
|
54
|
+
login: 'admin',
|
55
|
+
admin: true,
|
56
|
+
permissions: {
|
57
|
+
nodes: [],
|
58
|
+
},
|
59
|
+
};
|
60
|
+
|
61
|
+
export const userFactory = (login, permissions = []) => ({
|
62
|
+
__typename: 'User',
|
63
|
+
id: 'MDE6VXNlci01',
|
64
|
+
login,
|
65
|
+
admin: false,
|
66
|
+
permissions: {
|
67
|
+
nodes: permissions,
|
68
|
+
},
|
69
|
+
});
|
70
|
+
|
71
|
+
export const intruder = userFactory('intruder', [
|
72
|
+
{
|
73
|
+
__typename: 'Permission',
|
74
|
+
id: 'MDE6UGVybWlzc2lvbi0x',
|
75
|
+
name: 'view_architectures',
|
76
|
+
},
|
77
|
+
]);
|
78
|
+
|
43
79
|
export const mockFactory = (resultName, query) => (
|
44
80
|
variables,
|
45
81
|
modelResults,
|
46
|
-
errors = []
|
82
|
+
{ errors = [], currentUser = null } = {}
|
47
83
|
) => {
|
48
84
|
const mock = {
|
49
85
|
request: {
|
@@ -60,5 +96,9 @@ export const mockFactory = (resultName, query) => (
|
|
60
96
|
if (errors.length !== 0) {
|
61
97
|
mock.result.errors = errors;
|
62
98
|
}
|
99
|
+
|
100
|
+
if (currentUser) {
|
101
|
+
mock.result.data.currentUser = currentUser;
|
102
|
+
}
|
63
103
|
return [mock];
|
64
104
|
};
|
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:
|
4
|
+
version: 5.1.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
|
+
date: 2021-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -72,7 +72,11 @@ files:
|
|
72
72
|
- app/controllers/policy_dashboard_controller.rb
|
73
73
|
- app/controllers/scap_contents_controller.rb
|
74
74
|
- app/controllers/tailoring_files_controller.rb
|
75
|
+
- app/graphql/mutations/oval_contents/delete.rb
|
76
|
+
- app/graphql/mutations/oval_policies/delete.rb
|
77
|
+
- app/graphql/mutations/oval_policies/update.rb
|
75
78
|
- app/graphql/types/cve.rb
|
79
|
+
- app/graphql/types/oval_check.rb
|
76
80
|
- app/graphql/types/oval_content.rb
|
77
81
|
- app/graphql/types/oval_policy.rb
|
78
82
|
- app/helpers/arf_report_dashboard_helper.rb
|
@@ -152,6 +156,7 @@ files:
|
|
152
156
|
- app/views/api/v2/compliance/common/_org.json.rabl
|
153
157
|
- app/views/api/v2/compliance/oval_contents/base.json.rabl
|
154
158
|
- app/views/api/v2/compliance/oval_contents/create.json.rabl
|
159
|
+
- app/views/api/v2/compliance/oval_contents/destroy.json.rabl
|
155
160
|
- app/views/api/v2/compliance/oval_contents/index.json.rabl
|
156
161
|
- app/views/api/v2/compliance/oval_contents/show.json.rabl
|
157
162
|
- app/views/api/v2/compliance/oval_contents/sync.json.rabl
|
@@ -300,6 +305,7 @@ files:
|
|
300
305
|
- db/migrate/20201217130800_add_has_errata_to_cve.rb
|
301
306
|
- db/migrate/20201217161511_add_url_to_oval_content.rb
|
302
307
|
- db/migrate/20210409095625_add_oval_policy_reference_to_cve.rb
|
308
|
+
- db/migrate/20210819143316_drop_unused_tables.rb
|
303
309
|
- db/seeds.d/75-job_templates.rb
|
304
310
|
- db/seeds.d/openscap_feature.rb
|
305
311
|
- db/seeds.d/openscap_policy_notification.rb
|
@@ -386,6 +392,8 @@ files:
|
|
386
392
|
- test/functional/arf_reports_controller_test.rb
|
387
393
|
- test/functional/openscap_proxies_controller_test.rb
|
388
394
|
- test/functional/tailoring_files_controller_test.rb
|
395
|
+
- test/graphql/mutations/oval_policies/delete_mutation_test.rb
|
396
|
+
- test/graphql/queries/oval_content_query_test.rb
|
389
397
|
- test/graphql/queries/oval_contents_query_test.rb
|
390
398
|
- test/graphql/queries/oval_policies_query_test.rb
|
391
399
|
- test/helpers/arf_report_dashboard_helper_test.rb
|
@@ -409,15 +417,21 @@ files:
|
|
409
417
|
- test/unit/services/hostgroup_overrider_test.rb
|
410
418
|
- test/unit/services/lookup_key_overrider_test.rb
|
411
419
|
- test/unit/services/oval/cves_test.rb
|
420
|
+
- test/unit/services/oval/setup_check_test.rb
|
412
421
|
- test/unit/services/oval/setup_test.rb
|
413
422
|
- test/unit/services/report_dashboard/data_test.rb
|
414
423
|
- test/unit/services/tailoring_files_proxy_check_test.rb
|
415
424
|
- test/unit/tailoring_file_test.rb
|
425
|
+
- webpack/components/ConfirmModal.js
|
426
|
+
- webpack/components/ConfirmModal.scss
|
427
|
+
- webpack/components/EditableInput.js
|
428
|
+
- webpack/components/EditableInput.scss
|
416
429
|
- webpack/components/EmptyState.js
|
417
430
|
- webpack/components/IndexLayout.js
|
418
431
|
- webpack/components/IndexLayout.scss
|
419
432
|
- webpack/components/IndexTable/IndexTableHelper.js
|
420
433
|
- webpack/components/IndexTable/index.js
|
434
|
+
- webpack/components/LinkButton.js
|
421
435
|
- webpack/components/RuleSeverity/RuleSeverity.scss
|
422
436
|
- webpack/components/RuleSeverity/RuleSeverity.test.js
|
423
437
|
- webpack/components/RuleSeverity/__snapshots__/RuleSeverity.test.js.snap
|
@@ -427,32 +441,61 @@ files:
|
|
427
441
|
- webpack/components/RuleSeverity/i_severity-med.svg
|
428
442
|
- webpack/components/RuleSeverity/i_unknown.svg
|
429
443
|
- webpack/components/RuleSeverity/index.js
|
444
|
+
- webpack/components/withDeleteModal.js
|
430
445
|
- webpack/components/withLoading.js
|
431
446
|
- webpack/global_index.js
|
447
|
+
- webpack/graphql/mutations/deleteOvalContent.gql
|
448
|
+
- webpack/graphql/mutations/deleteOvalPolicy.gql
|
449
|
+
- webpack/graphql/mutations/updateOvalPolicy.gql
|
450
|
+
- webpack/graphql/queries/currentUserAttributes.gql
|
432
451
|
- webpack/graphql/queries/cves.gql
|
452
|
+
- webpack/graphql/queries/hostgroups.gql
|
453
|
+
- webpack/graphql/queries/ovalContent.gql
|
433
454
|
- webpack/graphql/queries/ovalContents.gql
|
434
455
|
- webpack/graphql/queries/ovalPolicies.gql
|
435
456
|
- webpack/graphql/queries/ovalPolicy.gql
|
436
457
|
- webpack/helpers/commonHelper.js
|
458
|
+
- webpack/helpers/formFieldsHelper.js
|
437
459
|
- webpack/helpers/globalIdHelper.js
|
460
|
+
- webpack/helpers/mutationHelper.js
|
438
461
|
- webpack/helpers/pageParamsHelper.js
|
439
462
|
- webpack/helpers/pathsHelper.js
|
463
|
+
- webpack/helpers/permissionsHelper.js
|
440
464
|
- webpack/helpers/tableHelper.js
|
465
|
+
- webpack/helpers/toastHelper.js
|
441
466
|
- webpack/index.js
|
442
467
|
- webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js
|
443
468
|
- webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js
|
469
|
+
- webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.fixtures.js
|
470
|
+
- webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.test.js
|
444
471
|
- webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js
|
445
472
|
- webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.test.js
|
446
473
|
- webpack/routes/OvalContents/OvalContentsIndex/index.js
|
474
|
+
- webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.js
|
475
|
+
- webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.scss
|
476
|
+
- webpack/routes/OvalContents/OvalContentsNew/OvalContentsNewHelper.js
|
477
|
+
- webpack/routes/OvalContents/OvalContentsNew/__tests__/OvalContentsNew.test.js
|
478
|
+
- webpack/routes/OvalContents/OvalContentsNew/index.js
|
479
|
+
- webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.js
|
480
|
+
- webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.test.js
|
481
|
+
- webpack/routes/OvalContents/OvalContentsShow/OvalContentsShowHelper.js
|
482
|
+
- webpack/routes/OvalContents/OvalContentsShow/index.js
|
447
483
|
- webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesIndex.js
|
448
484
|
- webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js
|
485
|
+
- webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.fixtures.js
|
486
|
+
- webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.test.js
|
449
487
|
- webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js
|
450
488
|
- webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js
|
451
489
|
- webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js
|
452
490
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js
|
453
491
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js
|
492
|
+
- webpack/routes/OvalPolicies/OvalPoliciesShow/DetailsTab.js
|
493
|
+
- webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTab.js
|
494
|
+
- webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTable.js
|
454
495
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShow.js
|
455
496
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js
|
497
|
+
- webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.fixtures.js
|
498
|
+
- webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.test.js
|
456
499
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js
|
457
500
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.test.js
|
458
501
|
- webpack/routes/OvalPolicies/OvalPoliciesShow/index.js
|
@@ -500,7 +543,6 @@ test_files:
|
|
500
543
|
- test/files/tailoring_files/ssg-firefox-ds-tailoring-2.xml
|
501
544
|
- test/files/tailoring_files/ssg-firefox-ds-tailoring.xml
|
502
545
|
- test/files/oval_contents/ansible-2.9.oval.xml.bz2
|
503
|
-
- test/functional/api/v2/compliance/policies_controller_test.rb
|
504
546
|
- test/functional/api/v2/compliance/scap_content_profiles_controller_test.rb
|
505
547
|
- test/functional/api/v2/compliance/scap_contents_controller_test.rb
|
506
548
|
- test/functional/api/v2/compliance/tailoring_files_controller_test.rb
|
@@ -508,6 +550,7 @@ test_files:
|
|
508
550
|
- test/functional/api/v2/compliance/oval_contents_controller_test.rb
|
509
551
|
- test/functional/api/v2/compliance/oval_policies_controller_test.rb
|
510
552
|
- test/functional/api/v2/compliance/oval_reports_controller_test.rb
|
553
|
+
- test/functional/api/v2/compliance/policies_controller_test.rb
|
511
554
|
- test/functional/api/v2/hosts_controller_test.rb
|
512
555
|
- test/functional/arf_reports_controller_test.rb
|
513
556
|
- test/functional/openscap_proxies_controller_test.rb
|
@@ -524,19 +567,22 @@ test_files:
|
|
524
567
|
- test/unit/openscap_host_test.rb
|
525
568
|
- test/unit/policy_mailer_test.rb
|
526
569
|
- test/unit/scap_content_test.rb
|
527
|
-
- test/unit/services/config_name_service_test.rb
|
528
|
-
- test/unit/services/hostgroup_overrider_test.rb
|
529
|
-
- test/unit/services/lookup_key_overrider_test.rb
|
530
570
|
- test/unit/services/report_dashboard/data_test.rb
|
531
571
|
- test/unit/services/tailoring_files_proxy_check_test.rb
|
532
572
|
- test/unit/services/oval/cves_test.rb
|
533
573
|
- test/unit/services/oval/setup_test.rb
|
574
|
+
- test/unit/services/oval/setup_check_test.rb
|
575
|
+
- test/unit/services/config_name_service_test.rb
|
576
|
+
- test/unit/services/lookup_key_overrider_test.rb
|
577
|
+
- test/unit/services/hostgroup_overrider_test.rb
|
534
578
|
- test/unit/tailoring_file_test.rb
|
535
|
-
- test/unit/policy_test.rb
|
536
579
|
- test/unit/oval_host_test.rb
|
537
580
|
- test/unit/oval_policy_test.rb
|
538
581
|
- test/unit/oval_status_test.rb
|
582
|
+
- test/unit/policy_test.rb
|
539
583
|
- test/fixtures/cve_fixtures.rb
|
540
584
|
- test/graphql/queries/oval_contents_query_test.rb
|
541
585
|
- test/graphql/queries/oval_policies_query_test.rb
|
586
|
+
- test/graphql/queries/oval_content_query_test.rb
|
587
|
+
- test/graphql/mutations/oval_policies/delete_mutation_test.rb
|
542
588
|
- test/test_plugin_helper.rb
|