foreman_rh_cloud 13.0.12 → 13.1.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/lib/foreman_rh_cloud/version.rb +1 -1
- data/package.json +1 -1
- data/webpack/ForemanColumnExtensions/index.js +5 -3
- data/webpack/ForemanRhCloudFills.js +7 -0
- data/webpack/HostsIndexExtensions/VulnerabilityAnalysisActions.js +138 -0
- data/webpack/HostsIndexExtensions/__tests__/VulnerabilityAnalysisActions.test.js +567 -0
- data/webpack/HostsIndexExtensions/hostVulnerabilityStoreUtils.js +41 -0
- data/webpack/InsightsVulnerabilityActionsBar/InsightsVulnerabilityActionsBar.scss +14 -0
- data/webpack/InsightsVulnerabilityActionsBar/InsightsVulnerabilityActionsBarActions.js +169 -0
- data/webpack/InsightsVulnerabilityActionsBar/__tests__/InsightsVulnerabilityActionsBar.test.js +91 -0
- data/webpack/InsightsVulnerabilityActionsBar/__tests__/InsightsVulnerabilityActionsBarActions.test.js +299 -0
- data/webpack/InsightsVulnerabilityActionsBar/index.js +93 -0
- data/webpack/InsightsVulnerabilityHostIndexExtensions/CVECountCell.js +25 -13
- data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +156 -87
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +6 -2
- data/webpack/__mocks__/foremanReact/common/I18n.js +2 -1
- data/webpack/__mocks__/foremanReact/common/helpers.js +11 -0
- data/webpack/__mocks__/foremanReact/components/HostsIndex/index.js +8 -0
- data/webpack/__mocks__/foremanReact/redux.js +10 -0
- data/webpack/common/Hooks/ConfigHooks.js +1 -1
- data/webpack/global_index.js +7 -0
- metadata +11 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a37e0d6adc3c8b44e73f636a10ee9012c2e14ef450e1a88d65bca7bbcd7c69cc
|
|
4
|
+
data.tar.gz: f53d45a393d00773a1ac42ffc2ca08f43fc52b861fba0eab2d1d8a4e1226600e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6ceaf758e5d3068fb4540399bc45cc0387f6e32a32b7cddcf38404a86b3279a7c0728707c7363996ab73303407b8977ace52641a40ec066c00d83b02a02d29ba
|
|
7
|
+
data.tar.gz: 67b81d211aa7f0aba5ea6e81dc3349add6e003b39a27f6b097eed42b9baf5011222a48ebf1e0b9ed30999a84e8fdd4bbeb583dadd6e0043b147818fd48841efc
|
data/package.json
CHANGED
|
@@ -74,13 +74,15 @@ const hostsIndexColumnExtensions = [
|
|
|
74
74
|
columnName: 'cves_count',
|
|
75
75
|
title: __('Total CVEs'),
|
|
76
76
|
wrapper: hostDetails => <CVECountCell hostDetails={hostDetails} />,
|
|
77
|
-
weight:
|
|
77
|
+
weight: 1600,
|
|
78
78
|
tableName: 'hosts',
|
|
79
79
|
categoryName: insightsCategoryName,
|
|
80
80
|
categoryKey: 'insights',
|
|
81
81
|
isSorted: false,
|
|
82
|
-
//
|
|
83
|
-
isRelevant: contextData =>
|
|
82
|
+
// Show column unless IoP is explicitly disabled (handles undefined during loading)
|
|
83
|
+
isRelevant: contextData =>
|
|
84
|
+
// eslint-disable-next-line camelcase
|
|
85
|
+
contextData?.metadata?.foreman_rh_cloud?.iop !== false,
|
|
84
86
|
},
|
|
85
87
|
];
|
|
86
88
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
hasNoInsightsFacet,
|
|
11
11
|
} from './ForemanRhCloudHelpers';
|
|
12
12
|
import CVEsHostDetailsTabWrapper from './CVEsHostDetailsTab/CVEsHostDetailsTab';
|
|
13
|
+
import InsightsVulnerabilityActionsBar from './InsightsVulnerabilityActionsBar';
|
|
13
14
|
|
|
14
15
|
const fills = [
|
|
15
16
|
{
|
|
@@ -18,6 +19,12 @@ const fills = [
|
|
|
18
19
|
component: () => <InventoryAutoUploadSwitcher />,
|
|
19
20
|
weight: 50,
|
|
20
21
|
},
|
|
22
|
+
{
|
|
23
|
+
slot: 'hosts-index-kebab',
|
|
24
|
+
name: 'InsightsVulnerabilityActionsBar',
|
|
25
|
+
component: () => <InsightsVulnerabilityActionsBar />,
|
|
26
|
+
weight: 150,
|
|
27
|
+
},
|
|
21
28
|
{
|
|
22
29
|
slot: 'host-details-page-tabs',
|
|
23
30
|
name: 'Insights',
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
2
|
+
import { patch, get } from 'foremanReact/redux/API';
|
|
3
|
+
import { propsToCamelCase } from 'foremanReact/common/helpers';
|
|
4
|
+
import store from 'foremanReact/redux';
|
|
5
|
+
import { insightsCloudUrl } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
|
|
6
|
+
import { updateHostVulnerabilityOptOut } from './hostVulnerabilityStoreUtils';
|
|
7
|
+
|
|
8
|
+
const vulnerabilityApiPath = path =>
|
|
9
|
+
insightsCloudUrl(`api/vulnerability/v1/${path}`);
|
|
10
|
+
|
|
11
|
+
const handleToggle = (uuid, newOptOutValue, hostId) => {
|
|
12
|
+
const cacheKey = `HOST_CVE_COUNT_${uuid}`;
|
|
13
|
+
|
|
14
|
+
return patch({
|
|
15
|
+
key: cacheKey,
|
|
16
|
+
url: vulnerabilityApiPath('systems/opt_out'),
|
|
17
|
+
params: {
|
|
18
|
+
inventory_id: uuid,
|
|
19
|
+
opt_out: newOptOutValue,
|
|
20
|
+
},
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/vnd.api+json', // eslint-disable-line spellcheck/spell-checker
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Update CVE API cache data to reflect new opt_out status
|
|
26
|
+
// When disabling: optimistically update opt_out (cve_count will be null anyway)
|
|
27
|
+
// When enabling: skip optimistic update - we'll invalidate to fetch fresh data
|
|
28
|
+
updateData: newOptOutValue
|
|
29
|
+
? prevState => {
|
|
30
|
+
// Disabling - safe to optimistically update
|
|
31
|
+
if (!prevState?.data) {
|
|
32
|
+
return prevState;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
...prevState,
|
|
37
|
+
data: prevState.data.map(system => ({
|
|
38
|
+
...system,
|
|
39
|
+
attributes: {
|
|
40
|
+
...system.attributes,
|
|
41
|
+
opt_out: true,
|
|
42
|
+
},
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
: undefined, // Enabling - skip optimistic update, rely on cache invalidation below
|
|
47
|
+
|
|
48
|
+
// Show success toast
|
|
49
|
+
successToast: () =>
|
|
50
|
+
newOptOutValue
|
|
51
|
+
? __('Vulnerability analysis disabled')
|
|
52
|
+
: __('Vulnerability analysis enabled'),
|
|
53
|
+
|
|
54
|
+
// Update HOSTS Redux data to trigger table re-render
|
|
55
|
+
// This ensures kebab actions recompute with correct opt_out value
|
|
56
|
+
handleSuccess: () => {
|
|
57
|
+
updateHostVulnerabilityOptOut(hostId, newOptOutValue);
|
|
58
|
+
|
|
59
|
+
// When enabling, refetch to get actual CVE count (not null)
|
|
60
|
+
if (!newOptOutValue) {
|
|
61
|
+
store.dispatch(
|
|
62
|
+
get({
|
|
63
|
+
key: cacheKey,
|
|
64
|
+
url: vulnerabilityApiPath(`systems?uuid=${uuid}`),
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// Extract detail from JSON:API errors array if present
|
|
71
|
+
errorToast: error => {
|
|
72
|
+
if (error.response?.data?.errors?.[0]?.detail) {
|
|
73
|
+
return error.response.data.errors[0].detail;
|
|
74
|
+
}
|
|
75
|
+
return __('Failed to update vulnerability analysis status');
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getVulnerabilityAnalysisActions = hostDetails => {
|
|
81
|
+
// Check if we're in IoP mode by looking at insights attributes
|
|
82
|
+
// eslint-disable-next-line camelcase
|
|
83
|
+
const useIopMode = hostDetails?.insights_attributes?.use_iop_mode;
|
|
84
|
+
|
|
85
|
+
if (!useIopMode) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check if host has subscription UUID (is registered)
|
|
90
|
+
// eslint-disable-next-line camelcase
|
|
91
|
+
const uuid = hostDetails?.subscription_facet_attributes?.uuid;
|
|
92
|
+
|
|
93
|
+
if (!uuid) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Try to get opt_out from host object (updated by CVECountCell or previous toggle)
|
|
98
|
+
// eslint-disable-next-line camelcase
|
|
99
|
+
let optOut = hostDetails?.insights_attributes?.vulnerability_opt_out;
|
|
100
|
+
|
|
101
|
+
// Fallback: check CVE API cache if not yet set on host object
|
|
102
|
+
if (optOut === undefined) {
|
|
103
|
+
const state = store.getState();
|
|
104
|
+
const apiData = state.API?.[`HOST_CVE_COUNT_${uuid}`];
|
|
105
|
+
|
|
106
|
+
// If API returned empty data, no system record exists - don't show actions
|
|
107
|
+
if (apiData?.response?.data && apiData.response.data.length === 0) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const attributes = propsToCamelCase(
|
|
112
|
+
(apiData?.response?.data || [])[0]?.attributes || {}
|
|
113
|
+
);
|
|
114
|
+
// eslint-disable-next-line prefer-destructuring
|
|
115
|
+
optOut = attributes.optOut;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// If still undefined (data not loaded yet), don't show actions until we have data
|
|
119
|
+
// Once CVE loads, it will update host object and trigger re-render with correct action
|
|
120
|
+
if (optOut === undefined) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Show correct action based on opt_out status
|
|
125
|
+
const actionLabel = optOut
|
|
126
|
+
? __('Enable vulnerability analysis')
|
|
127
|
+
: __('Disable vulnerability analysis');
|
|
128
|
+
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
title: actionLabel,
|
|
132
|
+
onClick: () =>
|
|
133
|
+
store.dispatch(handleToggle(uuid, !optOut, hostDetails.id)),
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export default getVulnerabilityAnalysisActions;
|