foreman_openscap 8.0.2 → 9.0.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/README.md +0 -1
- data/app/services/foreman_openscap/client_config/ansible.rb +1 -10
- 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/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/webpack/global_index.js +0 -4
- metadata +7 -168
- 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/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,147 +0,0 @@
|
|
|
1
|
-
import createOvalPolicy from '../../../../graphql/mutations/createOvalPolicy.gql';
|
|
2
|
-
import hostgroupsQuery from '../../../../graphql/queries/hostgroups.gql';
|
|
3
|
-
|
|
4
|
-
import { mockFactory, admin } from '../../../../testHelper';
|
|
5
|
-
import { decodeId } from '../../../../helpers/globalIdHelper';
|
|
6
|
-
import { ovalContents } from '../../../OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures';
|
|
7
|
-
|
|
8
|
-
export const newPolicyName = 'test policy';
|
|
9
|
-
export const newPolicyDescription = 'random description';
|
|
10
|
-
export const newPolicyCronline = '5 5 5 5 5';
|
|
11
|
-
export const newPolicyContentName = ovalContents.nodes[1].name;
|
|
12
|
-
export const newPolicyContentId = ovalContents.nodes[1].id;
|
|
13
|
-
const hostgroupId = 3;
|
|
14
|
-
|
|
15
|
-
const createPolicyMockFactory = mockFactory(
|
|
16
|
-
'createOvalPolicy',
|
|
17
|
-
createOvalPolicy
|
|
18
|
-
);
|
|
19
|
-
const hostgroupsMockFactory = mockFactory('hostgroups', hostgroupsQuery);
|
|
20
|
-
|
|
21
|
-
const foremanAnsiblePresent = {
|
|
22
|
-
id: 'foreman_ansible_present',
|
|
23
|
-
errors: null,
|
|
24
|
-
failMsg: null,
|
|
25
|
-
result: 'pass',
|
|
26
|
-
};
|
|
27
|
-
const rolePresent = {
|
|
28
|
-
id: 'foreman_scap_client_role_present',
|
|
29
|
-
errors: null,
|
|
30
|
-
failMsg: null,
|
|
31
|
-
result: 'pass',
|
|
32
|
-
};
|
|
33
|
-
const roleVarsPresent = {
|
|
34
|
-
id: 'foreman_scap_client_vars_present',
|
|
35
|
-
errors: null,
|
|
36
|
-
failMsg: null,
|
|
37
|
-
result: 'pass',
|
|
38
|
-
};
|
|
39
|
-
const serverVarOverriden = {
|
|
40
|
-
id: 'foreman_scap_client_server_overriden',
|
|
41
|
-
errors: null,
|
|
42
|
-
failMsg: null,
|
|
43
|
-
result: 'pass',
|
|
44
|
-
};
|
|
45
|
-
const portVarOverriden = {
|
|
46
|
-
id: 'foreman_scap_client_port_overriden',
|
|
47
|
-
errors: null,
|
|
48
|
-
failMsg: null,
|
|
49
|
-
result: 'pass',
|
|
50
|
-
};
|
|
51
|
-
const policiesVarOverriden = {
|
|
52
|
-
id: 'foreman_scap_client_policies_overriden',
|
|
53
|
-
errors: null,
|
|
54
|
-
failMsg: null,
|
|
55
|
-
result: 'pass',
|
|
56
|
-
};
|
|
57
|
-
const policyErrors = {
|
|
58
|
-
id: 'oval_policy_errors',
|
|
59
|
-
errors: { name: 'has already been taken' },
|
|
60
|
-
failMsg: null,
|
|
61
|
-
result: 'fail',
|
|
62
|
-
};
|
|
63
|
-
export const hgWithoutProxy = {
|
|
64
|
-
id: 'hostgroups_without_proxy',
|
|
65
|
-
errors: null,
|
|
66
|
-
failMsg: 'Assign openscap_proxy to first hostgroup before proceeding.',
|
|
67
|
-
result: 'fail',
|
|
68
|
-
};
|
|
69
|
-
export const roleAbsent = {
|
|
70
|
-
id: 'foreman_scap_client_role_present',
|
|
71
|
-
errors: null,
|
|
72
|
-
failMsg:
|
|
73
|
-
'theforeman.foreman_scap_client Ansible Role not found, please import it before running this action again.',
|
|
74
|
-
result: 'fail',
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const varChecks = [
|
|
78
|
-
roleVarsPresent,
|
|
79
|
-
serverVarOverriden,
|
|
80
|
-
portVarOverriden,
|
|
81
|
-
policiesVarOverriden,
|
|
82
|
-
];
|
|
83
|
-
const checkCollectionPass = [foremanAnsiblePresent, rolePresent, ...varChecks];
|
|
84
|
-
const checkCollectionPreconditionFail = [
|
|
85
|
-
foremanAnsiblePresent,
|
|
86
|
-
roleAbsent,
|
|
87
|
-
...varChecks.map(check => ({ ...check, result: 'skip' })),
|
|
88
|
-
];
|
|
89
|
-
const ovalPolicy = {
|
|
90
|
-
name: newPolicyName,
|
|
91
|
-
id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTcw',
|
|
92
|
-
period: 'custom',
|
|
93
|
-
cronLine: newPolicyCronline,
|
|
94
|
-
hostgroups: {
|
|
95
|
-
nodes: [],
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const policyCreateSuccess = {
|
|
100
|
-
checkCollection: checkCollectionPass,
|
|
101
|
-
ovalPolicy,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const baseVariables = {
|
|
105
|
-
name: newPolicyName,
|
|
106
|
-
description: '',
|
|
107
|
-
ovalContentId: decodeId(newPolicyContentId),
|
|
108
|
-
cronLine: newPolicyCronline,
|
|
109
|
-
hostgroupIds: [],
|
|
110
|
-
period: 'custom',
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export const firstHg = {
|
|
114
|
-
id: 'MDE6SG9zdGdyb3VwLTM=',
|
|
115
|
-
name: 'first hostgroup',
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const successVariables = {
|
|
119
|
-
...baseVariables,
|
|
120
|
-
description: newPolicyDescription,
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export const policySuccessMock = createPolicyMockFactory(
|
|
124
|
-
successVariables,
|
|
125
|
-
policyCreateSuccess
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
export const policyValidationMock = createPolicyMockFactory(baseVariables, {
|
|
129
|
-
checkCollection: [...checkCollectionPass, policyErrors],
|
|
130
|
-
ovalPolicy,
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
export const policyPreconditionMock = createPolicyMockFactory(baseVariables, {
|
|
134
|
-
checkCollection: checkCollectionPreconditionFail,
|
|
135
|
-
ovalPolicy,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
export const policyInvalidHgMock = createPolicyMockFactory(
|
|
139
|
-
{ ...baseVariables, hostgroupIds: [hostgroupId] },
|
|
140
|
-
{ checkCollection: [...checkCollectionPass, hgWithoutProxy], ovalPolicy }
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
export const hostgroupsMock = hostgroupsMockFactory(
|
|
144
|
-
{ search: `name ~ first` },
|
|
145
|
-
{ totalCount: 2, nodes: [firstHg] },
|
|
146
|
-
{ currentUser: admin }
|
|
147
|
-
);
|
|
@@ -1,172 +0,0 @@
|
|
|
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/toastHelper';
|
|
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
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useDispatch } from 'react-redux';
|
|
3
|
-
|
|
4
|
-
import { showToast } from '../../../helpers/toastHelper';
|
|
5
|
-
import OvalPoliciesNew from './OvalPoliciesNew';
|
|
6
|
-
|
|
7
|
-
const WrappedOvalPoliciesNew = props => (
|
|
8
|
-
<OvalPoliciesNew {...props} showToast={showToast(useDispatch())} />
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
export default WrappedOvalPoliciesNew;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
4
|
-
|
|
5
|
-
import { useQuery } from '@apollo/client';
|
|
6
|
-
|
|
7
|
-
import CvesTable from './CvesTable';
|
|
8
|
-
|
|
9
|
-
import cves from '../../../graphql/queries/cves.gql';
|
|
10
|
-
import {
|
|
11
|
-
useParamsToVars,
|
|
12
|
-
useCurrentPagination,
|
|
13
|
-
} from '../../../helpers/pageParamsHelper';
|
|
14
|
-
|
|
15
|
-
const CvesTab = props => {
|
|
16
|
-
const useFetchFn = componentProps =>
|
|
17
|
-
useQuery(cves, {
|
|
18
|
-
variables: {
|
|
19
|
-
search: `oval_policy_id = ${componentProps.match.params.id}`,
|
|
20
|
-
...useParamsToVars(componentProps.history),
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const renameData = data => ({
|
|
25
|
-
cves: data.cves.nodes,
|
|
26
|
-
totalCount: data.cves.totalCount,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const pagination = useCurrentPagination(props.history);
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<CvesTable
|
|
33
|
-
{...props}
|
|
34
|
-
fetchFn={useFetchFn}
|
|
35
|
-
renameData={renameData}
|
|
36
|
-
resultPath="cves.nodes"
|
|
37
|
-
pagination={pagination}
|
|
38
|
-
emptyStateTitle={__('No CVEs found.')}
|
|
39
|
-
permissions={['view_oval_policies']}
|
|
40
|
-
/>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
CvesTab.propTypes = {
|
|
45
|
-
match: PropTypes.object.isRequired,
|
|
46
|
-
history: PropTypes.object.isRequired,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export default CvesTab;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
4
|
-
|
|
5
|
-
import { linkCell } from '../../../helpers/tableHelper';
|
|
6
|
-
import { hostsPath } from '../../../helpers/pathsHelper';
|
|
7
|
-
import { decodeModelId } from '../../../helpers/globalIdHelper';
|
|
8
|
-
import { addSearch } from '../../../helpers/pageParamsHelper';
|
|
9
|
-
|
|
10
|
-
import withLoading from '../../../components/withLoading';
|
|
11
|
-
import IndexTable from '../../../components/IndexTable';
|
|
12
|
-
|
|
13
|
-
const CvesTable = props => {
|
|
14
|
-
const columns = [
|
|
15
|
-
{ title: __('Ref Id') },
|
|
16
|
-
{ title: __('Has Errata?') },
|
|
17
|
-
{ title: __('Hosts Count') },
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
const cveRefId = cve => (
|
|
21
|
-
<a href={cve.refUrl} rel="noopener noreferrer" target="_blank">
|
|
22
|
-
{cve.refId}
|
|
23
|
-
</a>
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const hostCount = cve =>
|
|
27
|
-
linkCell(
|
|
28
|
-
addSearch(hostsPath, { search: `cve_id = ${decodeModelId(cve)}` }),
|
|
29
|
-
cve.hosts.nodes.length
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const rows = props.cves.map(cve => ({
|
|
33
|
-
cells: [
|
|
34
|
-
{ title: cveRefId(cve) },
|
|
35
|
-
{ title: cve.hasErrata ? __('Yes') : __('No') },
|
|
36
|
-
{ title: hostCount(cve) },
|
|
37
|
-
],
|
|
38
|
-
cve,
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
|
-
const actions = [];
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<IndexTable
|
|
45
|
-
columns={columns}
|
|
46
|
-
rows={rows}
|
|
47
|
-
actions={actions}
|
|
48
|
-
pagination={props.pagination}
|
|
49
|
-
totalCount={props.totalCount}
|
|
50
|
-
history={props.history}
|
|
51
|
-
ariaTableLabel={__('Table of CVEs for OVAL policy')}
|
|
52
|
-
/>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
CvesTable.propTypes = {
|
|
57
|
-
cves: PropTypes.array.isRequired,
|
|
58
|
-
pagination: PropTypes.object.isRequired,
|
|
59
|
-
totalCount: PropTypes.number.isRequired,
|
|
60
|
-
history: PropTypes.object.isRequired,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export default withLoading(CvesTable);
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { useMutation } from '@apollo/client';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
TextList,
|
|
7
|
-
TextContent,
|
|
8
|
-
TextArea,
|
|
9
|
-
TextListItem,
|
|
10
|
-
TextListVariants,
|
|
11
|
-
TextListItemVariants,
|
|
12
|
-
TextInput,
|
|
13
|
-
} from '@patternfly/react-core';
|
|
14
|
-
|
|
15
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
16
|
-
|
|
17
|
-
import EditableInput from '../../../components/EditableInput';
|
|
18
|
-
|
|
19
|
-
import { onAttrUpdate, policySchedule } from './OvalPoliciesShowHelper';
|
|
20
|
-
import updateOvalPolicyMutation from '../../../graphql/mutations/updateOvalPolicy.gql';
|
|
21
|
-
|
|
22
|
-
const DetailsTab = props => {
|
|
23
|
-
const { policy, showToast } = props;
|
|
24
|
-
|
|
25
|
-
const [callMutation] = useMutation(updateOvalPolicyMutation);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<TextContent className="pf-u-pt-md">
|
|
29
|
-
<TextList component={TextListVariants.dl}>
|
|
30
|
-
<TextListItem component={TextListItemVariants.dt}>
|
|
31
|
-
{__('Name')}
|
|
32
|
-
</TextListItem>
|
|
33
|
-
<TextListItem
|
|
34
|
-
aria-label="label text value"
|
|
35
|
-
component={TextListItemVariants.dd}
|
|
36
|
-
className="foreman-spaced-list"
|
|
37
|
-
>
|
|
38
|
-
<EditableInput
|
|
39
|
-
value={policy.name}
|
|
40
|
-
onConfirm={onAttrUpdate('name', policy, callMutation, showToast)}
|
|
41
|
-
component={TextInput}
|
|
42
|
-
attrName="name"
|
|
43
|
-
allowed={policy.meta.canEdit}
|
|
44
|
-
/>
|
|
45
|
-
</TextListItem>
|
|
46
|
-
<TextListItem component={TextListItemVariants.dt}>
|
|
47
|
-
{__('Period')}
|
|
48
|
-
</TextListItem>
|
|
49
|
-
<TextListItem
|
|
50
|
-
aria-label="label text value"
|
|
51
|
-
component={TextListItemVariants.dd}
|
|
52
|
-
className="foreman-spaced-list"
|
|
53
|
-
>
|
|
54
|
-
{policySchedule(policy)}
|
|
55
|
-
</TextListItem>
|
|
56
|
-
<TextListItem component={TextListItemVariants.dt}>
|
|
57
|
-
{__('Description')}
|
|
58
|
-
</TextListItem>
|
|
59
|
-
<TextListItem
|
|
60
|
-
aria-label="label text value"
|
|
61
|
-
component={TextListItemVariants.dd}
|
|
62
|
-
className="foreman-spaced-list"
|
|
63
|
-
>
|
|
64
|
-
<EditableInput
|
|
65
|
-
value={policy.description}
|
|
66
|
-
onConfirm={onAttrUpdate(
|
|
67
|
-
'description',
|
|
68
|
-
policy,
|
|
69
|
-
callMutation,
|
|
70
|
-
showToast
|
|
71
|
-
)}
|
|
72
|
-
component={TextArea}
|
|
73
|
-
attrName="description"
|
|
74
|
-
allowed={policy.meta.canEdit}
|
|
75
|
-
/>
|
|
76
|
-
</TextListItem>
|
|
77
|
-
</TextList>
|
|
78
|
-
</TextContent>
|
|
79
|
-
);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
DetailsTab.propTypes = {
|
|
83
|
-
policy: PropTypes.object.isRequired,
|
|
84
|
-
showToast: PropTypes.func.isRequired,
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
export default DetailsTab;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
4
|
-
|
|
5
|
-
import { useQuery } from '@apollo/client';
|
|
6
|
-
|
|
7
|
-
import HostgroupsTable from './HostgroupsTable';
|
|
8
|
-
|
|
9
|
-
import hostgroups from '../../../graphql/queries/hostgroups.gql';
|
|
10
|
-
import {
|
|
11
|
-
useParamsToVars,
|
|
12
|
-
useCurrentPagination,
|
|
13
|
-
} from '../../../helpers/pageParamsHelper';
|
|
14
|
-
|
|
15
|
-
const HostgroupsTab = props => {
|
|
16
|
-
const useFetchFn = componentProps =>
|
|
17
|
-
useQuery(hostgroups, {
|
|
18
|
-
variables: {
|
|
19
|
-
search: `oval_policy_id = ${componentProps.match.params.id}`,
|
|
20
|
-
...useParamsToVars(componentProps.history),
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const renameData = data => ({
|
|
25
|
-
hostgroups: data.hostgroups.nodes,
|
|
26
|
-
totalCount: data.hostgroups.totalCount,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const pagination = useCurrentPagination(props.history);
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<HostgroupsTable
|
|
33
|
-
{...props}
|
|
34
|
-
fetchFn={useFetchFn}
|
|
35
|
-
renameData={renameData}
|
|
36
|
-
resultPath="hostgroups.nodes"
|
|
37
|
-
pagination={pagination}
|
|
38
|
-
emptyStateTitle={__('No Hostgroups found.')}
|
|
39
|
-
permissions={['view_hostgroups']}
|
|
40
|
-
/>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
HostgroupsTab.propTypes = {
|
|
45
|
-
match: PropTypes.object.isRequired,
|
|
46
|
-
history: PropTypes.object.isRequired,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export default HostgroupsTab;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
4
|
-
|
|
5
|
-
import withLoading from '../../../components/withLoading';
|
|
6
|
-
import IndexTable from '../../../components/IndexTable';
|
|
7
|
-
|
|
8
|
-
const CvesTable = props => {
|
|
9
|
-
const columns = [{ title: __('Name') }];
|
|
10
|
-
|
|
11
|
-
const rows = props.hostgroups.map(hostgroup => ({
|
|
12
|
-
cells: [{ title: hostgroup.name }],
|
|
13
|
-
hostgroup,
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
const actions = [];
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<IndexTable
|
|
20
|
-
columns={columns}
|
|
21
|
-
rows={rows}
|
|
22
|
-
actions={actions}
|
|
23
|
-
pagination={props.pagination}
|
|
24
|
-
totalCount={props.totalCount}
|
|
25
|
-
history={props.history}
|
|
26
|
-
ariaTableLabel={__('Table of hostgroups for OVAL policy')}
|
|
27
|
-
/>
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
CvesTable.propTypes = {
|
|
32
|
-
hostgroups: PropTypes.array.isRequired,
|
|
33
|
-
pagination: PropTypes.object.isRequired,
|
|
34
|
-
totalCount: PropTypes.number.isRequired,
|
|
35
|
-
history: PropTypes.object.isRequired,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export default withLoading(CvesTable);
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Link } from 'react-router-dom';
|
|
4
|
-
import { Helmet } from 'react-helmet';
|
|
5
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
6
|
-
import {
|
|
7
|
-
Button,
|
|
8
|
-
Grid,
|
|
9
|
-
GridItem,
|
|
10
|
-
Text,
|
|
11
|
-
TextVariants,
|
|
12
|
-
Tabs,
|
|
13
|
-
Tab,
|
|
14
|
-
TabTitleText,
|
|
15
|
-
} from '@patternfly/react-core';
|
|
16
|
-
|
|
17
|
-
import withLoading from '../../../components/withLoading';
|
|
18
|
-
import CvesTab from './CvesTab';
|
|
19
|
-
import HostgroupsTab from './HostgroupsTab';
|
|
20
|
-
import DetailsTab from './DetailsTab';
|
|
21
|
-
|
|
22
|
-
import { newJobFormPath } from './OvalPoliciesShowHelper';
|
|
23
|
-
import { resolvePath } from '../../../helpers/pathsHelper';
|
|
24
|
-
|
|
25
|
-
const OvalPoliciesShow = props => {
|
|
26
|
-
const { policy, match, history } = props;
|
|
27
|
-
const activeTab = match.params.tab ? match.params.tab : 'details';
|
|
28
|
-
|
|
29
|
-
const handleTabSelect = (event, value) => {
|
|
30
|
-
history.push(
|
|
31
|
-
resolvePath(match.path, { ':id': match.params.id, ':tab?': value })
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<React.Fragment>
|
|
37
|
-
<Helmet>
|
|
38
|
-
<title>{`${policy.name} | OVAL Policy`}</title>
|
|
39
|
-
</Helmet>
|
|
40
|
-
<Grid className="scap-page-grid">
|
|
41
|
-
<GridItem span={10}>
|
|
42
|
-
<Text component={TextVariants.h1}>{policy.name}</Text>
|
|
43
|
-
</GridItem>
|
|
44
|
-
<GridItem span={2}>
|
|
45
|
-
<Link to={newJobFormPath(policy, match.params.id)}>
|
|
46
|
-
<Button variant="secondary">{__('Scan All Hostgroups')}</Button>
|
|
47
|
-
</Link>
|
|
48
|
-
</GridItem>
|
|
49
|
-
<GridItem span={12}>
|
|
50
|
-
<Tabs mountOnEnter activeKey={activeTab} onSelect={handleTabSelect}>
|
|
51
|
-
<Tab
|
|
52
|
-
eventKey="details"
|
|
53
|
-
title={<TabTitleText>{__('Details')}</TabTitleText>}
|
|
54
|
-
>
|
|
55
|
-
<DetailsTab {...props} />
|
|
56
|
-
</Tab>
|
|
57
|
-
<Tab
|
|
58
|
-
eventKey="cves"
|
|
59
|
-
title={<TabTitleText>{__('CVEs')}</TabTitleText>}
|
|
60
|
-
>
|
|
61
|
-
<CvesTab {...props} />
|
|
62
|
-
</Tab>
|
|
63
|
-
<Tab
|
|
64
|
-
eventKey="hostgroups"
|
|
65
|
-
title={<TabTitleText>{__('Hostgroups')}</TabTitleText>}
|
|
66
|
-
>
|
|
67
|
-
<HostgroupsTab {...props} />
|
|
68
|
-
</Tab>
|
|
69
|
-
</Tabs>
|
|
70
|
-
</GridItem>
|
|
71
|
-
</Grid>
|
|
72
|
-
</React.Fragment>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
OvalPoliciesShow.propTypes = {
|
|
77
|
-
match: PropTypes.object.isRequired,
|
|
78
|
-
history: PropTypes.object.isRequired,
|
|
79
|
-
policy: PropTypes.object.isRequired,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export default withLoading(OvalPoliciesShow);
|