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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 972f28c475749451f2833bc918cfe95601eec5db19e024aec0d550a6f8844ad8
4
- data.tar.gz: cf12bf0072e5596db8b10fd7901e8c600482bfd0799426da0d7193a7ddd8d1bb
3
+ metadata.gz: a37e0d6adc3c8b44e73f636a10ee9012c2e14ef450e1a88d65bca7bbcd7c69cc
4
+ data.tar.gz: f53d45a393d00773a1ac42ffc2ca08f43fc52b861fba0eab2d1d8a4e1226600e
5
5
  SHA512:
6
- metadata.gz: fe0c825977e36641a874663dc97ba5efcb80ba3dd130123e445739e8ae72c5aff3b2e40859f9e73f3b82ae2be863307d190adf80cc544c4eef52171959bdbd73
7
- data.tar.gz: d1f9c3d4ef5dd131b9e28a3725ebd6f6bb3bab01e5e30e1970954085264bdaa632449bc4e4ff32ccfbeb5aaa126a4f854d57d2b11fbddc272a89526185fd3811
6
+ metadata.gz: 6ceaf758e5d3068fb4540399bc45cc0387f6e32a32b7cddcf38404a86b3279a7c0728707c7363996ab73303407b8977ace52641a40ec066c00d83b02a02d29ba
7
+ data.tar.gz: 67b81d211aa7f0aba5ea6e81dc3349add6e003b39a27f6b097eed42b9baf5011222a48ebf1e0b9ed30999a84e8fdd4bbeb583dadd6e0043b147818fd48841efc
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '13.0.12'.freeze
2
+ VERSION = '13.1.0'.freeze
3
3
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "13.0.12",
3
+ "version": "13.1.0",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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: 2600,
77
+ weight: 1600,
78
78
  tableName: 'hosts',
79
79
  categoryName: insightsCategoryName,
80
80
  categoryKey: 'insights',
81
81
  isSorted: false,
82
- // eslint-disable-next-line camelcase
83
- isRelevant: contextData => contextData?.metadata?.foreman_rh_cloud?.iop,
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;