foreman_openscap 4.3.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/compliance/arf_reports_controller.rb +0 -6
  3. data/app/controllers/api/v2/compliance/oval_policies_controller.rb +1 -1
  4. data/app/helpers/arf_report_dashboard_helper.rb +2 -4
  5. data/app/helpers/compliance_hosts_helper.rb +1 -1
  6. data/app/helpers/policies_helper.rb +1 -1
  7. data/app/services/foreman_openscap/client_config/base.rb +1 -0
  8. data/app/services/foreman_openscap/client_config/puppet.rb +6 -2
  9. data/app/views/api/v2/compliance/oval_contents/destroy.json.rabl +3 -0
  10. data/app/views/arf_reports/_metrics.html.erb +4 -4
  11. data/app/views/compliance_hosts/show.html.erb +4 -6
  12. data/app/views/dashboard/_compliance_reports_breakdown_widget.html.erb +4 -3
  13. data/app/views/policy_dashboard/_policy_chart_widget.html.erb +3 -2
  14. data/db/migrate/20200117135424_migrate_port_overrides_to_int.rb +2 -1
  15. data/db/migrate/20201202110213_update_puppet_port_param_type.rb +2 -1
  16. data/lib/foreman_openscap/engine.rb +0 -7
  17. data/lib/foreman_openscap/version.rb +1 -1
  18. data/package.json +48 -0
  19. data/test/functional/api/v2/compliance/oval_reports_controller_test.rb +1 -1
  20. data/test/functional/api/v2/compliance/policies_controller_test.rb +2 -0
  21. data/test/helpers/arf_report_dashboard_helper_test.rb +9 -10
  22. data/test/helpers/policy_dashboard_helper_test.rb +1 -1
  23. data/test/test_plugin_helper.rb +9 -4
  24. data/test/unit/policy_test.rb +1 -1
  25. data/test/unit/services/config_name_service_test.rb +1 -0
  26. data/test/unit/services/hostgroup_overrider_test.rb +2 -1
  27. data/test/unit/services/lookup_key_overrider_test.rb +4 -1
  28. data/webpack/components/EmptyState.js +73 -0
  29. data/webpack/components/IndexLayout.js +35 -0
  30. data/webpack/components/IndexLayout.scss +3 -0
  31. data/webpack/components/IndexTable/IndexTableHelper.js +9 -0
  32. data/webpack/components/IndexTable/index.js +65 -0
  33. data/webpack/components/RuleSeverity/RuleSeverity.scss +3 -0
  34. data/webpack/components/RuleSeverity/RuleSeverity.test.js +13 -0
  35. data/webpack/components/RuleSeverity/__snapshots__/RuleSeverity.test.js.snap +41 -0
  36. data/webpack/components/RuleSeverity/i_severity-critical.svg +61 -0
  37. data/webpack/components/RuleSeverity/i_severity-high.svg +61 -0
  38. data/webpack/components/RuleSeverity/i_severity-low.svg +62 -0
  39. data/webpack/components/RuleSeverity/i_severity-med.svg +62 -0
  40. data/webpack/components/RuleSeverity/i_unknown.svg +33 -0
  41. data/webpack/components/RuleSeverity/index.js +33 -0
  42. data/webpack/components/withLoading.js +87 -0
  43. data/webpack/global_index.js +5 -0
  44. data/webpack/graphql/queries/currentUserAttributes.gql +11 -0
  45. data/webpack/graphql/queries/cves.gql +23 -0
  46. data/webpack/graphql/queries/ovalContents.gql +16 -0
  47. data/webpack/graphql/queries/ovalPolicies.gql +17 -0
  48. data/webpack/graphql/queries/ovalPolicy.gql +26 -0
  49. data/webpack/helpers/commonHelper.js +1 -0
  50. data/webpack/helpers/globalIdHelper.js +13 -0
  51. data/webpack/helpers/pageParamsHelper.js +31 -0
  52. data/webpack/helpers/pathsHelper.js +22 -0
  53. data/webpack/helpers/permissionsHelper.js +42 -0
  54. data/webpack/helpers/tableHelper.js +9 -0
  55. data/webpack/index.js +8 -0
  56. data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js +46 -0
  57. data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js +46 -0
  58. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js +120 -0
  59. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.test.js +101 -0
  60. data/webpack/routes/OvalContents/OvalContentsIndex/index.js +7 -0
  61. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesIndex.js +47 -0
  62. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js +44 -0
  63. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js +95 -0
  64. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js +98 -0
  65. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js +7 -0
  66. data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js +49 -0
  67. data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js +63 -0
  68. data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShow.js +78 -0
  69. data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js +39 -0
  70. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js +87 -0
  71. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.test.js +129 -0
  72. data/webpack/routes/OvalPolicies/OvalPoliciesShow/index.js +36 -0
  73. data/webpack/routes/routes.js +28 -0
  74. data/webpack/testHelper.js +96 -0
  75. metadata +56 -7
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ viewBox="0 0 110 130" style="enable-background:new 0 0 110 130;" xml:space="preserve">
5
+ <style type="text/css">
6
+ .st0{fill:#CCCCCC;}
7
+ .st1{fill:#FFFFFF;}
8
+ </style>
9
+ <path class="st0" d="M96.6,130H13c-7.2,0-13-5.9-13-13l0,0c0-7.2,5.9-13,13-13h83.6c7.2,0,13,5.9,13,13l0,0
10
+ C109.7,124.1,103.8,130,96.6,130z M96.6,95.4H13c-7.2,0-13-5.9-13-13l0,0c0-7.2,5.9-13,13-13h83.6c7.2,0,13,5.9,13,13l0,0
11
+ C109.7,89.5,103.8,95.4,96.6,95.4z M97,60.2H13.4c-7.2,0-13-5.9-13-13l0,0c0-7.2,5.9-13,13-13H97c7.2,0,13,5.9,13,13l0,0
12
+ C110,54.4,104.1,60.2,97,60.2z M96.6,26.1H13c-7.2,0-13-5.9-13-13l0,0C0,5.9,5.9,0,13,0h83.6c7.2,0,13,5.9,13,13l0,0
13
+ C109.7,20.2,103.8,26.1,96.6,26.1z"/>
14
+ <path class="st0" d="M53.3,123.4c-4.6,0-8.5-1.6-11.6-4.6c-3.2-3.1-4.8-7-4.8-11.5s1.6-8.4,4.8-11.5c1-1,2.1-1.8,3.3-2.5h-4.9v-8.7
15
+ c0-4.9,0.7-9.3,2.1-13.3c1.4-4,3.3-7.3,5.5-9.8c1.9-2.1,4.1-4.3,6.3-6.3c2.2-2,4.3-3.8,6.2-5.3c1.4-1.1,2.5-2.5,3.5-4.2
16
+ c0.9-1.6,1.3-3.2,1.3-5c0-2.7-0.8-4.7-2.5-6.3c-1.7-1.7-4.2-2.5-7.6-2.5c-4.2,0-7.3,1.2-9.4,3.5c-2.3,2.5-3.4,6.1-3.4,10.9V51H15.6
17
+ v-4.5c0-12.2,3.7-22,10.9-29.2c7.2-7.1,16.7-10.8,28.4-10.8c11.3,0,20.3,3.2,26.8,9.6c6.5,6.4,9.8,14.7,9.8,24.7
18
+ c0,4.4-0.7,8.5-2.2,12.1c-1.5,3.6-3.4,6.6-5.6,8.9c-1.9,1.9-3.9,3.8-6.1,5.9c-2.1,2-4.1,3.8-6,5.5c-1.4,1.2-2.6,2.9-3.6,4.9
19
+ c-1,2-1.4,4.2-1.4,6.7v8.5h-4.8c1.2,0.7,2.3,1.6,3.4,2.6c3.2,3.2,4.7,7,4.7,11.4c0,4.5-1.6,8.4-4.8,11.5
20
+ C61.8,121.9,57.9,123.4,53.3,123.4z"/>
21
+ <path class="st1" d="M54.8,11.1c10.1,0,18,2.8,23.6,8.3c5.6,5.6,8.4,12.7,8.4,21.5c0,3.9-0.6,7.4-1.9,10.4c-1.2,3.1-2.8,5.5-4.6,7.4
22
+ c-1.8,1.8-3.8,3.8-6,5.7c-2.1,2-4.1,3.8-6,5.4c-1.8,1.6-3.4,3.8-4.6,6.3c-1.2,2.6-1.9,5.5-1.9,8.6v4H44.6v-4.2
23
+ c0-4.4,0.6-8.3,1.9-11.8c1.2-3.5,2.8-6.2,4.6-8.3c1.8-2,3.8-4,6-6c2.1-1.9,4.1-3.6,6-5.1c1.8-1.4,3.4-3.3,4.6-5.5
24
+ c1.2-2.2,1.9-4.6,1.9-7.2c0-3.9-1.3-7.1-3.9-9.5c-2.6-2.5-6.2-3.7-10.7-3.7c-5.5,0-9.7,1.7-12.7,5c-3,3.3-4.5,8-4.5,13.9H20.1
25
+ c0-11,3.2-19.7,9.5-26C36,14.2,44.4,11.1,54.8,11.1 M53.3,95.7c3.4,0,6.2,1.1,8.5,3.4c2.3,2.3,3.4,5,3.4,8.2c0,3.3-1.1,6-3.4,8.3
26
+ c-2.3,2.2-5.1,3.4-8.5,3.4c-3.4,0-6.2-1.1-8.5-3.4c-2.3-2.2-3.4-5-3.4-8.3c0-3.3,1.1-6,3.4-8.3C47.1,96.8,50,95.7,53.3,95.7
27
+ M54.8,2.1C42,2.1,31.4,6.1,23.3,14.1c-8.1,8-12.2,18.9-12.2,32.4v9h9h17.4h9v-9c0-3.6,0.7-6.3,2.2-7.9c0.8-0.9,2.3-2.1,6.1-2.1
28
+ c2.1,0,3.7,0.4,4.5,1.2c0.5,0.5,1.1,1.2,1.1,3c0,1.1-0.2,2-0.7,2.9c-0.7,1.2-1.4,2.1-2.3,2.8c-2,1.6-4.2,3.4-6.5,5.5
29
+ c-2.3,2.1-4.6,4.3-6.6,6.6c-2.6,2.9-4.8,6.7-6.4,11.3c-1.6,4.4-2.4,9.4-2.4,14.8v4.2v7.5c-2.1,3.2-3.1,7-3.1,11
30
+ c0,5.7,2.1,10.8,6.1,14.7c4,3.9,9.1,5.9,14.8,5.9c5.7,0,10.8-2,14.8-5.9c4-3.9,6.1-9,6.1-14.7c0-4.1-1.1-7.9-3.3-11.1v-7.3v-4
31
+ c0-1.8,0.3-3.4,1-4.7c0.7-1.5,1.6-2.7,2.5-3.5c1.9-1.7,4-3.6,6.1-5.6c2.2-2,4.3-4,6.2-6c2.7-2.7,4.9-6.2,6.6-10.4
32
+ c1.7-4.1,2.5-8.8,2.5-13.8c0-11.2-3.7-20.6-11.1-27.8C77.5,5.7,67.4,2.1,54.8,2.1L54.8,2.1z"/>
33
+ </svg>
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import SeverityCritical from './i_severity-critical.svg';
5
+ import SeverityHigh from './i_severity-high.svg';
6
+ import SeverityMedium from './i_severity-med.svg';
7
+ import SeverityLow from './i_severity-low.svg';
8
+ import SeverityUnknown from './i_unknown.svg';
9
+
10
+ import './RuleSeverity.scss';
11
+
12
+ const RuleSeverity = props => {
13
+ const propsMapping = {
14
+ low: { alt: 'Low Serverity', src: SeverityLow },
15
+ medium: { alt: 'Medium Serverity', src: SeverityMedium },
16
+ high: { alt: 'High Serverity', src: SeverityHigh },
17
+ critical: {
18
+ alt: 'Critical Serverity',
19
+ src: SeverityCritical,
20
+ },
21
+ unknown: { alt: 'Unknown Serverity', src: SeverityUnknown },
22
+ };
23
+
24
+ const imgProps = propsMapping[props.severity] || propsMapping.unknown;
25
+ // eslint-disable-next-line jsx-a11y/alt-text
26
+ return <img {...imgProps} className="severity-img" />;
27
+ };
28
+
29
+ RuleSeverity.propTypes = {
30
+ severity: PropTypes.string.isRequired,
31
+ };
32
+
33
+ export default RuleSeverity;
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import Loading from 'foremanReact/components/Loading';
5
+ import {
6
+ permissionCheck,
7
+ permissionDeniedMsg,
8
+ } from '../helpers/permissionsHelper';
9
+
10
+ import EmptyState from './EmptyState';
11
+
12
+ const errorStateTitle = __('Error!');
13
+ const emptyStateBody = '';
14
+
15
+ const pluckData = (data, path) => {
16
+ const split = path.split('.');
17
+ return split.reduce((memo, item) => {
18
+ if (item) {
19
+ return memo[item];
20
+ }
21
+ throw new Error('Unexpected empty segment in response data path');
22
+ }, data);
23
+ };
24
+
25
+ const withLoading = Component => {
26
+ const Subcomponent = ({
27
+ fetchFn,
28
+ resultPath,
29
+ renameData,
30
+ emptyStateTitle,
31
+ permissions,
32
+ ...rest
33
+ }) => {
34
+ const { loading, error, data } = fetchFn(rest);
35
+
36
+ if (loading) {
37
+ return <Loading />;
38
+ }
39
+
40
+ if (error) {
41
+ return (
42
+ <EmptyState
43
+ error={error}
44
+ title={errorStateTitle}
45
+ body={error.message}
46
+ />
47
+ );
48
+ }
49
+
50
+ const check = permissionCheck(data.currentUser, permissions);
51
+
52
+ if (!check.allowed) {
53
+ return (
54
+ <EmptyState
55
+ lock
56
+ title={__('Permission denied')}
57
+ body={permissionDeniedMsg(check.permissions.map(item => item.name))}
58
+ />
59
+ );
60
+ }
61
+
62
+ const result = pluckData(data, resultPath);
63
+
64
+ if ((Array.isArray(result) && result.length === 0) || !result) {
65
+ return <EmptyState title={emptyStateTitle} body={emptyStateBody} />;
66
+ }
67
+
68
+ return <Component {...rest} {...renameData(data)} />;
69
+ };
70
+
71
+ Subcomponent.propTypes = {
72
+ fetchFn: PropTypes.func.isRequired,
73
+ resultPath: PropTypes.string.isRequired,
74
+ renameData: PropTypes.func,
75
+ emptyStateTitle: PropTypes.string.isRequired,
76
+ permissions: PropTypes.array,
77
+ };
78
+
79
+ Subcomponent.defaultProps = {
80
+ renameData: data => data,
81
+ permissions: [],
82
+ };
83
+
84
+ return Subcomponent;
85
+ };
86
+
87
+ export default withLoading;
@@ -0,0 +1,5 @@
1
+ import { registerRoutes } from 'foremanReact/routes/RoutingService';
2
+
3
+ import routes from './routes/routes';
4
+
5
+ registerRoutes('foreman_openscap', routes);
@@ -0,0 +1,11 @@
1
+ fragment CurrentUserAttributes on User {
2
+ id
3
+ login
4
+ admin
5
+ permissions {
6
+ nodes {
7
+ id
8
+ name
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,23 @@
1
+ #import "./currentUserAttributes.gql"
2
+
3
+ query($search: String, $first: Int, $last: Int) {
4
+ cves(search: $search, first: $first, last: $last) {
5
+ totalCount
6
+ nodes {
7
+ id
8
+ refId
9
+ refUrl
10
+ hasErrata
11
+ definitionId
12
+ hosts {
13
+ nodes {
14
+ id
15
+ name
16
+ }
17
+ }
18
+ }
19
+ }
20
+ currentUser {
21
+ ...CurrentUserAttributes
22
+ }
23
+ }
@@ -0,0 +1,16 @@
1
+ #import "./currentUserAttributes.gql"
2
+
3
+ query($first: Int, $last: Int) {
4
+ ovalContents(first: $first, last: $last) {
5
+ totalCount
6
+ nodes {
7
+ id
8
+ name
9
+ url
10
+ originalFilename
11
+ }
12
+ }
13
+ currentUser {
14
+ ...CurrentUserAttributes
15
+ }
16
+ }
@@ -0,0 +1,17 @@
1
+ #import "./currentUserAttributes.gql"
2
+
3
+ query($first: Int, $last: Int) {
4
+ ovalPolicies(first: $first, last: $last) {
5
+ totalCount
6
+ nodes {
7
+ id
8
+ name
9
+ ovalContent {
10
+ name
11
+ }
12
+ }
13
+ }
14
+ currentUser {
15
+ ...CurrentUserAttributes
16
+ }
17
+ }
@@ -0,0 +1,26 @@
1
+ #import "./currentUserAttributes.gql"
2
+
3
+ query($id: String!) {
4
+ ovalPolicy(id: $id) {
5
+ id
6
+ name
7
+ period
8
+ cronLine
9
+ weekday
10
+ dayOfMonth
11
+ description
12
+ hostgroups {
13
+ nodes {
14
+ id
15
+ descendants {
16
+ nodes {
17
+ id
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ currentUser {
24
+ ...CurrentUserAttributes
25
+ }
26
+ }
@@ -0,0 +1 @@
1
+ export const last = array => array[array.length - 1];
@@ -0,0 +1,13 @@
1
+ import { last } from './commonHelper';
2
+
3
+ const idSeparator = '-';
4
+ const versionSeparator = ':';
5
+ const defaultVersion = '01';
6
+
7
+ export const decodeId = model => {
8
+ const split = atob(model.id).split(idSeparator);
9
+ return parseInt(last(split), 10);
10
+ };
11
+
12
+ export const encodeId = (typename, id) =>
13
+ btoa([defaultVersion, versionSeparator, typename, idSeparator, id].join(''));
@@ -0,0 +1,31 @@
1
+ import URI from 'urijs';
2
+ import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
3
+
4
+ const parsePageParams = history => URI.parseQuery(history.location.search);
5
+
6
+ export const addSearch = (basePath, params) => {
7
+ let stringyfied = '';
8
+ if (Object.keys(params).length > 0) {
9
+ stringyfied = `?${URI.buildQuery(params)}`;
10
+ }
11
+
12
+ return `${basePath}${stringyfied}`;
13
+ };
14
+
15
+ export const useCurrentPagination = history => {
16
+ const pageParams = parsePageParams(history);
17
+ const uiSettings = useForemanSettings();
18
+
19
+ return {
20
+ page: parseInt(pageParams.page, 10) || 1,
21
+ perPage: parseInt(pageParams.perPage, 10) || uiSettings.perPage,
22
+ };
23
+ };
24
+
25
+ export const pageToVars = pagination => ({
26
+ first: pagination.page * pagination.perPage,
27
+ last: pagination.perPage,
28
+ });
29
+
30
+ export const useParamsToVars = history =>
31
+ pageToVars(useCurrentPagination(history));
@@ -0,0 +1,22 @@
1
+ import { decodeId } from './globalIdHelper';
2
+
3
+ const experimental = path => `/experimental${path}`;
4
+
5
+ const showPath = path => `${path}/:id`;
6
+
7
+ export const modelPath = (basePath, model) => `${basePath}/${decodeId(model)}`;
8
+
9
+ // react-router uses path-to-regexp, should we use it as well in a future?
10
+ // https://github.com/pillarjs/path-to-regexp/tree/v1.7.0#compile-reverse-path-to-regexp
11
+ export const resolvePath = (path, params) =>
12
+ Object.entries(params).reduce(
13
+ (memo, [key, value]) => memo.replace(key, value),
14
+ path
15
+ );
16
+
17
+ export const ovalContentsPath = experimental('/compliance/oval_contents');
18
+ export const ovalPoliciesPath = experimental('/compliance/oval_policies');
19
+ export const ovalPoliciesShowPath = `${showPath(ovalPoliciesPath)}/:tab?`;
20
+ export const hostsPath = '/hosts';
21
+ export const newJobPath = '/job_invocations/new';
22
+ export const hostsShowPath = showPath(hostsPath);
@@ -0,0 +1,42 @@
1
+ import { translate as __, sprintf } from 'foremanReact/common/I18n';
2
+
3
+ export const permissionCheck = (user, permissionsRequired) => {
4
+ if (permissionsRequired.length === 0) {
5
+ return { allowed: true };
6
+ }
7
+
8
+ if (!user) {
9
+ throw new Error(
10
+ 'No user data when loading the page - cannot determine if current user is allowed to view the page.'
11
+ );
12
+ }
13
+
14
+ if (user.admin) {
15
+ return { allowed: true };
16
+ }
17
+
18
+ const permList = permissionsRequired.reduce((memo, item) => {
19
+ const found = user.permissions.nodes.find(
20
+ permission => permission.name === item
21
+ );
22
+ memo.push({ name: item, present: !!found });
23
+ return memo;
24
+ }, []);
25
+
26
+ if (permList.reduce((memo, item) => memo && item.present, true)) {
27
+ return { allowed: true, permissions: permList };
28
+ }
29
+
30
+ return { allowed: false, permissions: permList };
31
+ };
32
+
33
+ export const permissionDeniedMsg = permissions => {
34
+ let msg = __('You are not authorized to view the page. ');
35
+ if (permissions?.length > 0) {
36
+ msg += sprintf(
37
+ __('Request the following permissions from administrator: %s.'),
38
+ permissions.join(', ')
39
+ );
40
+ }
41
+ return msg;
42
+ };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { TableText } from '@patternfly/react-table';
4
+
5
+ export const linkCell = (path, text) => (
6
+ <TableText>
7
+ <Link to={path}>{text}</Link>
8
+ </TableText>
9
+ );
data/webpack/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import componentRegistry from 'foremanReact/components/componentRegistry';
2
+
3
+ import RuleSeverity from './components/RuleSeverity';
4
+
5
+ componentRegistry.register({
6
+ name: 'RuleSeverity',
7
+ type: RuleSeverity,
8
+ });
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useQuery } from '@apollo/client';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+
6
+ import IndexLayout from '../../../components/IndexLayout';
7
+ import OvalContentsTable from './OvalContentsTable';
8
+ import {
9
+ useParamsToVars,
10
+ useCurrentPagination,
11
+ } from '../../../helpers/pageParamsHelper';
12
+ import ovalContentsQuery from '../../../graphql/queries/ovalContents.gql';
13
+
14
+ const OvalContentsIndex = props => {
15
+ const useFetchFn = componentProps =>
16
+ useQuery(ovalContentsQuery, {
17
+ variables: useParamsToVars(componentProps.history),
18
+ });
19
+
20
+ const renameData = data => ({
21
+ ovalContents: data.ovalContents.nodes,
22
+ totalCount: data.ovalContents.totalCount,
23
+ });
24
+
25
+ const pagination = useCurrentPagination(props.history);
26
+
27
+ return (
28
+ <IndexLayout pageTitle={__('OVAL Contents')}>
29
+ <OvalContentsTable
30
+ {...props}
31
+ fetchFn={useFetchFn}
32
+ renameData={renameData}
33
+ resultPath="ovalContents.nodes"
34
+ pagination={pagination}
35
+ emptyStateTitle={__('No OVAL Contents found.')}
36
+ permissions={['view_oval_contents']}
37
+ />
38
+ </IndexLayout>
39
+ );
40
+ };
41
+
42
+ OvalContentsIndex.propTypes = {
43
+ history: PropTypes.object.isRequired,
44
+ };
45
+
46
+ export default OvalContentsIndex;