@northern.tech/store 0.3.2 → 0.3.3

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.
Files changed (197) hide show
  1. package/dist/actions.cjs +20 -17
  2. package/dist/actions.cjs.map +1 -1
  3. package/dist/actions.js +8 -8
  4. package/dist/api/general-api.js +2 -2
  5. package/dist/api/types/Tenant.ts +17 -12
  6. package/dist/api/users-api.js +2 -2
  7. package/dist/appSlice/constants.cjs +18 -10
  8. package/dist/appSlice/constants.cjs.map +1 -1
  9. package/dist/appSlice/constants.d.cts +41 -84
  10. package/dist/appSlice/constants.d.ts +41 -84
  11. package/dist/appSlice/constants.js +1 -1
  12. package/dist/appSlice/index.js +2 -2
  13. package/dist/appSlice/thunks.cjs +137 -94
  14. package/dist/appSlice/thunks.cjs.map +1 -1
  15. package/dist/appSlice/thunks.js +19 -19
  16. package/dist/auth.js +2 -2
  17. package/dist/{chunk-Q6M5TTDQ.js → chunk-2CYOM4BK.js} +1 -1
  18. package/dist/chunk-2CYOM4BK.js.map +1 -0
  19. package/dist/{chunk-74OJIKXF.js → chunk-2JHFUQ6B.js} +133 -96
  20. package/dist/chunk-2JHFUQ6B.js.map +1 -0
  21. package/dist/{chunk-YETZPQFR.js → chunk-4XJMRVFI.js} +12 -11
  22. package/dist/chunk-4XJMRVFI.js.map +1 -0
  23. package/dist/{chunk-RX55KAKX.js → chunk-7JKWI5FK.js} +2 -2
  24. package/dist/{chunk-A6CT6GTI.js → chunk-C5NEDBJI.js} +17 -11
  25. package/dist/chunk-C5NEDBJI.js.map +1 -0
  26. package/dist/{chunk-NNADGHSL.js → chunk-DAPAXWA5.js} +8 -8
  27. package/dist/{chunk-ANB5BM5J.js → chunk-DCK2DBOA.js} +27 -20
  28. package/dist/chunk-DCK2DBOA.js.map +1 -0
  29. package/dist/{chunk-E5LEU5PF.js → chunk-HPBE6KYY.js} +2 -2
  30. package/dist/{chunk-2RJIDREZ.js → chunk-LEMVXAYP.js} +25 -16
  31. package/dist/chunk-LEMVXAYP.js.map +1 -0
  32. package/dist/{chunk-NI4SZOCF.js → chunk-LGNOTPUG.js} +9 -9
  33. package/dist/{chunk-MDC7Y3EX.js → chunk-LTKOV26W.js} +22 -20
  34. package/dist/chunk-LTKOV26W.js.map +1 -0
  35. package/dist/{chunk-YTQUNAZP.js → chunk-QRGTG4YB.js} +2 -2
  36. package/dist/{chunk-XTRPX7JZ.js → chunk-TI2RL5P2.js} +2 -2
  37. package/dist/chunk-TI2RL5P2.js.map +1 -0
  38. package/dist/{chunk-YGBFDXXA.js → chunk-TUACATJA.js} +2 -2
  39. package/dist/{chunk-25AKG5HH.js → chunk-UWMYZNUB.js} +19 -11
  40. package/dist/chunk-UWMYZNUB.js.map +1 -0
  41. package/dist/{chunk-UEP36GCI.js → chunk-VMNMD6KF.js} +2 -2
  42. package/dist/{chunk-KAQJH2YL.js → chunk-WXL7PVI5.js} +12 -4
  43. package/dist/chunk-WXL7PVI5.js.map +1 -0
  44. package/dist/{chunk-VOCOFE4I.js → chunk-X7IEZBM4.js} +2 -2
  45. package/dist/{chunk-XXHONFSQ.js → chunk-YDS36ALB.js} +3 -3
  46. package/dist/{chunk-XXHONFSQ.js.map → chunk-YDS36ALB.js.map} +1 -1
  47. package/dist/commonSelectors.cjs +40 -18
  48. package/dist/commonSelectors.cjs.map +1 -1
  49. package/dist/commonSelectors.d.cts +54 -46
  50. package/dist/commonSelectors.d.ts +54 -46
  51. package/dist/commonSelectors.js +9 -9
  52. package/dist/constants.cjs +35 -19
  53. package/dist/constants.cjs.map +1 -1
  54. package/dist/constants.d.cts +3 -3
  55. package/dist/constants.d.ts +3 -3
  56. package/dist/constants.js +6 -2
  57. package/dist/deploymentdevicehook.cjs +143 -99
  58. package/dist/deploymentdevicehook.cjs.map +1 -1
  59. package/dist/deploymentdevicehook.d.cts +1 -1
  60. package/dist/deploymentdevicehook.d.ts +1 -1
  61. package/dist/deploymentdevicehook.js +24 -22
  62. package/dist/deploymentdevicehook.js.map +1 -1
  63. package/dist/deploymentsSlice/constants.cjs +8 -8
  64. package/dist/deploymentsSlice/constants.cjs.map +1 -1
  65. package/dist/deploymentsSlice/constants.js +2 -2
  66. package/dist/deploymentsSlice/index.cjs +8 -8
  67. package/dist/deploymentsSlice/index.cjs.map +1 -1
  68. package/dist/deploymentsSlice/index.js +3 -3
  69. package/dist/deploymentsSlice/selectors.cjs +8 -8
  70. package/dist/deploymentsSlice/selectors.cjs.map +1 -1
  71. package/dist/deploymentsSlice/selectors.js +3 -3
  72. package/dist/deploymentsSlice/thunks.cjs +137 -94
  73. package/dist/deploymentsSlice/thunks.cjs.map +1 -1
  74. package/dist/deploymentsSlice/thunks.js +19 -19
  75. package/dist/devicesSlice/constants.cjs +11 -8
  76. package/dist/devicesSlice/constants.cjs.map +1 -1
  77. package/dist/devicesSlice/constants.d.cts +2 -1
  78. package/dist/devicesSlice/constants.d.ts +2 -1
  79. package/dist/devicesSlice/constants.js +4 -2
  80. package/dist/devicesSlice/index.cjs +8 -8
  81. package/dist/devicesSlice/index.cjs.map +1 -1
  82. package/dist/devicesSlice/index.js +3 -3
  83. package/dist/devicesSlice/selectors.cjs +9 -9
  84. package/dist/devicesSlice/selectors.cjs.map +1 -1
  85. package/dist/devicesSlice/selectors.js +3 -3
  86. package/dist/devicesSlice/thunks.cjs +139 -94
  87. package/dist/devicesSlice/thunks.cjs.map +1 -1
  88. package/dist/devicesSlice/thunks.d.cts +12 -2
  89. package/dist/devicesSlice/thunks.d.ts +12 -2
  90. package/dist/devicesSlice/thunks.js +21 -19
  91. package/dist/flag-eu-5477R2P4.svg +130 -0
  92. package/dist/flag-us-HNQAF66I.svg +63 -0
  93. package/dist/monitorSlice/constants.cjs +8 -8
  94. package/dist/monitorSlice/constants.cjs.map +1 -1
  95. package/dist/monitorSlice/constants.js +2 -2
  96. package/dist/monitorSlice/index.cjs +8 -8
  97. package/dist/monitorSlice/index.cjs.map +1 -1
  98. package/dist/monitorSlice/index.js +3 -3
  99. package/dist/monitorSlice/thunks.cjs +59 -37
  100. package/dist/monitorSlice/thunks.cjs.map +1 -1
  101. package/dist/monitorSlice/thunks.js +17 -17
  102. package/dist/onboardingSlice/thunks.cjs +146 -100
  103. package/dist/onboardingSlice/thunks.cjs.map +1 -1
  104. package/dist/onboardingSlice/thunks.d.cts +1 -32
  105. package/dist/onboardingSlice/thunks.d.ts +1 -32
  106. package/dist/onboardingSlice/thunks.js +19 -19
  107. package/dist/organizationSlice/constants.cjs +22 -17
  108. package/dist/organizationSlice/constants.cjs.map +1 -1
  109. package/dist/organizationSlice/constants.d.cts +33 -1
  110. package/dist/organizationSlice/constants.d.ts +33 -1
  111. package/dist/organizationSlice/constants.js +4 -2
  112. package/dist/organizationSlice/index.cjs +18 -15
  113. package/dist/organizationSlice/index.cjs.map +1 -1
  114. package/dist/organizationSlice/index.d.cts +26 -1012
  115. package/dist/organizationSlice/index.d.ts +26 -1012
  116. package/dist/organizationSlice/index.js +3 -3
  117. package/dist/organizationSlice/selectors.cjs.map +1 -1
  118. package/dist/organizationSlice/selectors.d.cts +9 -1
  119. package/dist/organizationSlice/selectors.d.ts +9 -1
  120. package/dist/organizationSlice/selectors.js +3 -3
  121. package/dist/organizationSlice/thunks.cjs +1605 -1539
  122. package/dist/organizationSlice/thunks.cjs.map +1 -1
  123. package/dist/organizationSlice/thunks.d.cts +61 -36
  124. package/dist/organizationSlice/thunks.d.ts +61 -36
  125. package/dist/organizationSlice/thunks.js +19 -19
  126. package/dist/organizationSlice/types.cjs +19 -0
  127. package/dist/organizationSlice/types.cjs.map +1 -0
  128. package/dist/organizationSlice/types.d.cts +114 -0
  129. package/dist/organizationSlice/types.d.ts +114 -0
  130. package/dist/organizationSlice/types.js +1 -0
  131. package/dist/organizationSlice/types.js.map +1 -0
  132. package/dist/releasesSlice/index.js +2 -2
  133. package/dist/releasesSlice/selectors.cjs +11 -0
  134. package/dist/releasesSlice/selectors.cjs.map +1 -1
  135. package/dist/releasesSlice/selectors.js +4 -4
  136. package/dist/releasesSlice/thunks.cjs +73 -49
  137. package/dist/releasesSlice/thunks.cjs.map +1 -1
  138. package/dist/releasesSlice/thunks.d.cts +1 -4
  139. package/dist/releasesSlice/thunks.d.ts +1 -4
  140. package/dist/releasesSlice/thunks.js +17 -17
  141. package/dist/selectors.cjs +46 -18
  142. package/dist/selectors.cjs.map +1 -1
  143. package/dist/selectors.d.cts +9 -1
  144. package/dist/selectors.d.ts +9 -1
  145. package/dist/selectors.js +36 -30
  146. package/dist/store.cjs +36 -23
  147. package/dist/store.cjs.map +1 -1
  148. package/dist/store.d.cts +12 -231
  149. package/dist/store.d.ts +12 -231
  150. package/dist/store.js +13 -11
  151. package/dist/storehooks.cjs +216 -137
  152. package/dist/storehooks.cjs.map +1 -1
  153. package/dist/storehooks.js +36 -24
  154. package/dist/storehooks.js.map +1 -1
  155. package/dist/thunks.cjs +193 -122
  156. package/dist/thunks.cjs.map +1 -1
  157. package/dist/thunks.d.cts +5 -1
  158. package/dist/thunks.d.ts +5 -1
  159. package/dist/thunks.js +21 -19
  160. package/dist/usersSlice/constants.cjs +10 -10
  161. package/dist/usersSlice/constants.cjs.map +1 -1
  162. package/dist/usersSlice/constants.js +2 -2
  163. package/dist/usersSlice/index.cjs +10 -10
  164. package/dist/usersSlice/index.cjs.map +1 -1
  165. package/dist/usersSlice/index.js +3 -3
  166. package/dist/usersSlice/selectors.cjs +35 -13
  167. package/dist/usersSlice/selectors.cjs.map +1 -1
  168. package/dist/usersSlice/selectors.d.cts +44 -1
  169. package/dist/usersSlice/selectors.d.ts +44 -1
  170. package/dist/usersSlice/selectors.js +12 -6
  171. package/dist/usersSlice/thunks.cjs +135 -94
  172. package/dist/usersSlice/thunks.cjs.map +1 -1
  173. package/dist/usersSlice/thunks.d.cts +10 -9
  174. package/dist/usersSlice/thunks.d.ts +10 -9
  175. package/dist/usersSlice/thunks.js +19 -19
  176. package/dist/utils.cjs +17 -16
  177. package/dist/utils.cjs.map +1 -1
  178. package/dist/utils.js +3 -3
  179. package/package.json +7 -7
  180. package/dist/chunk-25AKG5HH.js.map +0 -1
  181. package/dist/chunk-2RJIDREZ.js.map +0 -1
  182. package/dist/chunk-74OJIKXF.js.map +0 -1
  183. package/dist/chunk-A6CT6GTI.js.map +0 -1
  184. package/dist/chunk-ANB5BM5J.js.map +0 -1
  185. package/dist/chunk-KAQJH2YL.js.map +0 -1
  186. package/dist/chunk-MDC7Y3EX.js.map +0 -1
  187. package/dist/chunk-Q6M5TTDQ.js.map +0 -1
  188. package/dist/chunk-XTRPX7JZ.js.map +0 -1
  189. package/dist/chunk-YETZPQFR.js.map +0 -1
  190. /package/dist/{chunk-RX55KAKX.js.map → chunk-7JKWI5FK.js.map} +0 -0
  191. /package/dist/{chunk-NNADGHSL.js.map → chunk-DAPAXWA5.js.map} +0 -0
  192. /package/dist/{chunk-E5LEU5PF.js.map → chunk-HPBE6KYY.js.map} +0 -0
  193. /package/dist/{chunk-NI4SZOCF.js.map → chunk-LGNOTPUG.js.map} +0 -0
  194. /package/dist/{chunk-YTQUNAZP.js.map → chunk-QRGTG4YB.js.map} +0 -0
  195. /package/dist/{chunk-YGBFDXXA.js.map → chunk-TUACATJA.js.map} +0 -0
  196. /package/dist/{chunk-UEP36GCI.js.map → chunk-VMNMD6KF.js.map} +0 -0
  197. /package/dist/{chunk-VOCOFE4I.js.map → chunk-X7IEZBM4.js.map} +0 -0
@@ -67,6 +67,14 @@ module.exports = __toCommonJS(thunks_exports);
67
67
 
68
68
  // src/appSlice/constants.ts
69
69
  var import_icons_material = require("@mui/icons-material");
70
+
71
+ // ../../assets/img/flag-eu.svg
72
+ var flag_eu_default = "../flag-eu-5477R2P4.svg";
73
+
74
+ // ../../assets/img/flag-us.svg
75
+ var flag_us_default = "../flag-us-HNQAF66I.svg";
76
+
77
+ // src/appSlice/constants.ts
70
78
  var startingDeviceCount = {
71
79
  os: "for first 50 devices",
72
80
  professional: "for first 250 devices"
@@ -89,36 +97,36 @@ var emptyChartSelection = { software: "", group: "", chartType: chartTypes.bar.k
89
97
  var defaultReportType = "distribution";
90
98
  var defaultReports = [{ ...emptyChartSelection, group: null, attribute: "artifact_name", type: defaultReportType }];
91
99
  var locations = {
92
- eu: { key: "eu", title: "EU", location: "eu.hosted.mender.io" },
93
- us: { key: "us", title: "US", location: "hosted.mender.io" }
100
+ eu: { key: "eu", title: "EU", location: "eu.hosted.mender.io", icon: flag_eu_default },
101
+ us: { key: "us", title: "US", location: "hosted.mender.io", icon: flag_us_default }
94
102
  };
95
103
  var PLANS = {
96
104
  os: {
97
105
  id: "os",
98
106
  name: "Basic",
99
107
  offer: true,
100
- price: "$32/month",
108
+ price: "$32 / month",
101
109
  deviceCount: startingDeviceCount.os,
102
- offerprice: "$23/month for first 50 devices",
110
+ offerprice: "$23 / month for first 50 devices",
103
111
  price2: "for first 6 months;\n$29/month thereafter",
104
- features: ["Basic OTA features"]
112
+ features: ["Access to core features of Mender", "Basic support"]
105
113
  },
106
114
  professional: {
107
115
  id: "professional",
108
116
  name: "Professional",
109
117
  offer: true,
110
- price: "$269/month",
118
+ price: "$269 / month",
111
119
  deviceCount: startingDeviceCount.professional,
112
- offerprice: "$200/month for first 50 devices",
120
+ offerprice: "$200 / month for first 50 devices",
113
121
  price2: "for first 6 months;\n$249/month thereafter",
114
- features: ["+ Advanced OTA features", "+ Standard support"]
122
+ features: ["Advanced OTA features", "Higher priority support"]
115
123
  },
116
124
  enterprise: {
117
125
  id: "enterprise",
118
126
  name: "Enterprise",
119
127
  price: "Custom pricing",
120
- deviceCount: "unlimited devices",
121
- features: ["+ Enterprise-grade OTA features", "+ Premium support"]
128
+ deviceCount: "Unlimited devices",
129
+ features: ["All Mender features", "Advanced security features", "SLA-backed support"]
122
130
  }
123
131
  };
124
132
  var ADDONS = {
@@ -589,6 +597,7 @@ var DEVICE_STATES = {
589
597
  rejected: "rejected"
590
598
  };
591
599
  var geoAttributes = ["geo-lat", "geo-lon"].map((attribute) => ({ attribute, scope: "inventory" }));
600
+ var REPORT_CHART_SIZE_LIMIT = 6;
592
601
 
593
602
  // src/monitorSlice/constants.ts
594
603
  var alertChannels = { email: "email" };
@@ -670,13 +679,16 @@ var SSO_TYPES = {
670
679
  configDetails: [{ key: "startURL", label: "Start Url", getValue: getOidcStartUrl }]
671
680
  }
672
681
  };
673
- var AUDIT_LOGS_TYPES = [
674
- { title: "Artifact", queryParameter: "object_type", value: "artifact" },
675
- { title: "Deployment", queryParameter: "object_deployment_name", value: "deployment" },
676
- { title: "Device", queryParameter: "object_id", value: "device" },
677
- { title: "User", queryParameter: "object_id", value: "user" }
678
- ];
679
- var SP_AUDIT_LOGS_TYPES = [AUDIT_LOGS_TYPES[3], { title: "Tenant", queryParameter: "object_id", value: "tenant" }];
682
+ var auditlogTypes = {
683
+ artifact: { title: "Artifact", queryParameter: "object_type", value: "artifact" },
684
+ deployment: { title: "Deployment", queryParameter: "object_deployment_name", value: "deployment" },
685
+ device: { title: "Device", queryParameter: "object_id", value: "device" },
686
+ user_access_token: { title: "Personal Access Token", queryParameter: "user_access_token", value: "user_access_token" },
687
+ user: { title: "User", queryParameter: "object_id", value: "user" },
688
+ tenant: { title: "Tenant", queryParameter: "object_id", value: "tenant" }
689
+ };
690
+ var AUDIT_LOGS_TYPES = [auditlogTypes.artifact, auditlogTypes.deployment, auditlogTypes.device, auditlogTypes.user_access_token, auditlogTypes.user];
691
+ var SP_AUDIT_LOGS_TYPES = [auditlogTypes.user, auditlogTypes.tenant];
680
692
  var emptyWebhook = {
681
693
  description: "",
682
694
  enabled: true,
@@ -809,7 +821,7 @@ var uiPermissionsByArea = {
809
821
  explanation: "Granting access to the audit log will allow tracing changes to devices, releases and user accounts, as well as providing information about deployments.",
810
822
  key: "auditlog",
811
823
  uiPermissions: [uiPermissionsById.read],
812
- title: "System audit log"
824
+ title: "System Audit Log"
813
825
  },
814
826
  deployments: {
815
827
  endpoints: [
@@ -960,7 +972,7 @@ var serviceProviderRolesById = {
960
972
  },
961
973
  readOnly: {
962
974
  name: "Read access",
963
- value: staticRolesByName.admin,
975
+ value: staticRolesByName.readOnly,
964
976
  description: "This role can see all linked organizations but cannot make any changes",
965
977
  permissions: [],
966
978
  uiPermissions: {
@@ -2037,6 +2049,9 @@ var Api = {
2037
2049
  };
2038
2050
  var general_api_default = Api;
2039
2051
 
2052
+ // src/devicesSlice/thunks.tsx
2053
+ var import_react_router_dom = require("react-router-dom");
2054
+
2040
2055
  // src/appSlice/selectors.ts
2041
2056
  var import_helpers2 = require("@northern.tech/utils/helpers");
2042
2057
  var import_toolkit9 = require("@reduxjs/toolkit");
@@ -2165,7 +2180,7 @@ var getGroups = (0, import_toolkit11.createSelector)([getGroupsById], (groupsByI
2165
2180
  (accu, [groupname, group]) => {
2166
2181
  const name = groupname === UNGROUPED_GROUP.id ? UNGROUPED_GROUP.name : groupname;
2167
2182
  const groupItem = { ...group, groupId: name, name: groupname };
2168
- if (group.filters.length > 0) {
2183
+ if (group.filters?.length > 0) {
2169
2184
  if (groupname !== UNGROUPED_GROUP.id) {
2170
2185
  accu.dynamic.push(groupItem);
2171
2186
  } else {
@@ -2240,14 +2255,15 @@ var getAuditLogEntry = (0, import_toolkit12.createSelector)([getAuditLog, getAud
2240
2255
  // src/utils.ts
2241
2256
  var import_helpers4 = require("@northern.tech/utils/helpers");
2242
2257
  var filterProcessors = {
2243
- $gt: (val) => Number(val) || val,
2244
- $gte: (val) => Number(val) || val,
2245
- $lt: (val) => Number(val) || val,
2246
- $lte: (val) => Number(val) || val,
2247
- $in: (val) => ("" + val).split(",").map((i) => i.trim()),
2248
- $nin: (val) => ("" + val).split(",").map((i) => i.trim()),
2249
- $exists: import_helpers4.yes,
2250
- $nexists: () => false
2258
+ [DEVICE_FILTERING_OPTIONS.$gt.key]: (val) => Number(val) || val,
2259
+ [DEVICE_FILTERING_OPTIONS.$gte.key]: (val) => Number(val) || val,
2260
+ [DEVICE_FILTERING_OPTIONS.$lt.key]: (val) => Number(val) || val,
2261
+ [DEVICE_FILTERING_OPTIONS.$lte.key]: (val) => Number(val) || val,
2262
+ [DEVICE_FILTERING_OPTIONS.$ltne.key]: (val) => Number(val) || val,
2263
+ [DEVICE_FILTERING_OPTIONS.$in.key]: (val) => ("" + val).split(",").map((i) => i.trim()),
2264
+ [DEVICE_FILTERING_OPTIONS.$nin.key]: (val) => ("" + val).split(",").map((i) => i.trim()),
2265
+ [DEVICE_FILTERING_OPTIONS.$exists.key]: import_helpers4.yes,
2266
+ [DEVICE_FILTERING_OPTIONS.$nexists.key]: () => false
2251
2267
  };
2252
2268
  var filterAliases = {
2253
2269
  $nexists: { alias: DEVICE_FILTERING_OPTIONS.$exists.key, value: false }
@@ -2371,8 +2387,13 @@ var getTooltipsById = (state) => state.users.tooltips.byId;
2371
2387
  var getGlobalSettings = (state) => state.users.globalSettings;
2372
2388
  var getCurrentUserId = (state) => state.users.currentUser;
2373
2389
  var getUsersById = (state) => state.users.byId;
2390
+ var getUsersList = (0, import_toolkit14.createSelector)([getUsersById], (usersById) => Object.values(usersById));
2374
2391
  var getCurrentUser = (0, import_toolkit14.createSelector)([getUsersById, getCurrentUserId], (usersById, userId) => usersById[userId] ?? {});
2375
2392
  var getUserSettings = (state) => state.users.userSettings;
2393
+ var getSelectedDeviceAttribute = (0, import_toolkit14.createSelector)(
2394
+ [getUserSettings],
2395
+ ({ columnSelection }) => columnSelection.map((attribute) => ({ attribute: attribute.key, scope: attribute.scope }))
2396
+ );
2376
2397
  var getIsDarkMode = (0, import_toolkit14.createSelector)([getUserSettings], ({ mode }) => isDarkMode(mode));
2377
2398
  var getShowHelptips = (0, import_toolkit14.createSelector)(
2378
2399
  [getTooltipsById],
@@ -2397,7 +2418,7 @@ var getOfflineThresholdSettings = (0, import_toolkit14.createSelector)([getGloba
2397
2418
  interval: offlineThreshold?.interval || DEVICE_ONLINE_CUTOFF.interval,
2398
2419
  intervalUnit: offlineThreshold?.intervalUnit || DEVICE_ONLINE_CUTOFF.intervalName
2399
2420
  }));
2400
- var getRolesList = (0, import_toolkit14.createSelector)([getRolesById], (rolesById2) => Object.entries(rolesById2).map(([id, role]) => ({ id, ...role })));
2421
+ var getRolesList = (0, import_toolkit14.createSelector)([getRolesById], (rolesById2) => Object.entries(rolesById2).map(([value, role]) => ({ value, ...role })));
2401
2422
  var getCurrentSession = (state) => state.users.currentSession;
2402
2423
 
2403
2424
  // src/commonSelectors.ts
@@ -2459,12 +2480,18 @@ var getUserCapabilities = (0, import_toolkit15.createSelector)([getUserRoles, ge
2459
2480
  });
2460
2481
  var getTenantCapabilities = (0, import_toolkit15.createSelector)(
2461
2482
  [getFeatures, getOrganization, getIsEnterprise],
2462
- ({ hasAuditlogs: isAuditlogEnabled, hasDeviceConfig: isDeviceConfigEnabled, hasDeviceConnect: isDeviceConnectEnabled, hasMonitor: isMonitorEnabled }, { addons = [], plan = PLANS.os.id }, isEnterprise) => {
2483
+ ({
2484
+ hasAuditlogs: isAuditlogEnabled,
2485
+ hasDeviceConfig: isDeviceConfigEnabled,
2486
+ hasDeviceConnect: isDeviceConnectEnabled,
2487
+ hasMonitor: isMonitorEnabled,
2488
+ isHosted
2489
+ }, { addons = [], plan = PLANS.os.id }, isEnterprise) => {
2463
2490
  const canDelta = isEnterprise || plan === PLANS.professional.id;
2464
2491
  const hasAuditlogs = isAuditlogEnabled && isEnterprise;
2465
- const hasDeviceConfig = isDeviceConfigEnabled && addons.some((addon) => addon.name === "configure" && Boolean(addon.enabled));
2466
- const hasDeviceConnect = isDeviceConnectEnabled && (!isEnterprise || addons.some((addon) => addon.name === "troubleshoot" && Boolean(addon.enabled)));
2467
- const hasMonitor = isMonitorEnabled && addons.some((addon) => addon.name === "monitor" && Boolean(addon.enabled));
2492
+ const hasDeviceConfig = addons.some((addon) => addon.name === ADDONS.configure.id && addon.enabled) || isDeviceConfigEnabled && !isHosted;
2493
+ const hasDeviceConnect = addons.some((addon) => addon.name === ADDONS.troubleshoot.id && addon.enabled) || isDeviceConnectEnabled && !isHosted;
2494
+ const hasMonitor = isMonitorEnabled && addons.some((addon) => addon.name === ADDONS.monitor.id && addon.enabled);
2468
2495
  return {
2469
2496
  canDelta,
2470
2497
  canRetry: canDelta,
@@ -2594,7 +2621,7 @@ var getAuditlogDevice = (0, import_toolkit15.createSelector)([getAuditLogEntry,
2594
2621
  var getRelevantRoles = (0, import_toolkit15.createSelector)([getOrganization, getRolesList], ({ service_provider }, roles) => {
2595
2622
  if (service_provider) {
2596
2623
  return roles.reduce((accu, role) => {
2597
- if (rolesById[role.id]) {
2624
+ if (rolesById[role.value]) {
2598
2625
  return accu;
2599
2626
  }
2600
2627
  accu.push(role);
@@ -2602,20 +2629,19 @@ var getRelevantRoles = (0, import_toolkit15.createSelector)([getOrganization, ge
2602
2629
  }, Object.values(serviceProviderRolesById));
2603
2630
  }
2604
2631
  return Object.keys(rolesById).reverse().reduce((accu, key) => {
2605
- const index = accu.findIndex(({ id }) => id === key);
2632
+ const index = accu.findIndex(({ value }) => value === key);
2606
2633
  accu = [accu[index], ...accu.filter((item, itemIndex) => index !== itemIndex)];
2607
2634
  return accu;
2608
2635
  }, roles);
2609
2636
  });
2610
2637
 
2611
2638
  // src/store.ts
2639
+ var import_react_redux = require("react-redux");
2612
2640
  var import_helpers6 = require("@northern.tech/utils/helpers");
2613
2641
  var import_toolkit16 = require("@reduxjs/toolkit");
2614
2642
  var { setSnackbar, uploadProgress } = actions_default;
2615
2643
  var keys = ["sessionDeploymentChecker", settingsKeys.initialized];
2616
- var resetEnvironment = () => {
2617
- keys.map((key) => window.sessionStorage.removeItem(key));
2618
- };
2644
+ var resetEnvironment = () => keys.forEach((key) => window.sessionStorage.removeItem(key));
2619
2645
  resetEnvironment();
2620
2646
  var commonErrorFallback = "Please check your connection.";
2621
2647
  var commonErrorHandler = (err, errorContext, dispatch, fallback, mightBeAuthRelated = false) => {
@@ -2641,6 +2667,14 @@ var sessionReducer = (state, action) => {
2641
2667
  }
2642
2668
  return rootReducer(state, action);
2643
2669
  };
2670
+ var rejectionLoggerMiddleware = () => (next) => (action) => {
2671
+ if (action.type.endsWith("/rejected")) {
2672
+ const { error } = action;
2673
+ console.error("Rejection in action:", action);
2674
+ console.error(error.stack);
2675
+ }
2676
+ return next(action);
2677
+ };
2644
2678
  var getConfiguredStore = (options = {}) => {
2645
2679
  const { preloadedState = {}, ...config } = options;
2646
2680
  return (0, import_toolkit16.configureStore)({
@@ -2656,7 +2690,7 @@ var getConfiguredStore = (options = {}) => {
2656
2690
  ignoredActionPaths: ["uploads", "snackbar", /payload\..*$/],
2657
2691
  ignoredPaths: ["app.uploadsById", "app.snackbar", "organization.externalDeviceIntegrations"]
2658
2692
  }
2659
- })
2693
+ }).concat(rejectionLoggerMiddleware)
2660
2694
  });
2661
2695
  };
2662
2696
  var store = getConfiguredStore({
@@ -2773,6 +2807,7 @@ var setSearchState = (0, import_toolkit17.createAsyncThunk)(`${sliceName}/setSea
2773
2807
 
2774
2808
  // src/deploymentsSlice/thunks.ts
2775
2809
  var import_helpers8 = require("@northern.tech/utils/helpers");
2810
+ var import_tracking = __toESM(require("@northern.tech/utils/tracking"), 1);
2776
2811
  var import_toolkit18 = require("@reduxjs/toolkit");
2777
2812
  var import_validator = require("validator");
2778
2813
  var { receivedDevice, setSnackbar: setSnackbar2 } = actions_default;
@@ -2829,6 +2864,26 @@ var getDeploymentsByStatus2 = (0, import_toolkit18.createAsyncThunk)(`${sliceNam
2829
2864
  return Promise.all(tasks);
2830
2865
  });
2831
2866
  });
2867
+ var isWithinFirstMonth = (expirationDate) => {
2868
+ if (!expirationDate) {
2869
+ return false;
2870
+ }
2871
+ const endOfFirstMonth = new Date(expirationDate);
2872
+ endOfFirstMonth.setMonth(endOfFirstMonth.getMonth() - 11);
2873
+ return endOfFirstMonth > /* @__PURE__ */ new Date();
2874
+ };
2875
+ var trackDeploymentCreation = (totalDeploymentCount, hasDeployments, trial_expiration) => {
2876
+ import_tracking.default.event({ category: "deployments", action: "create" });
2877
+ if (!totalDeploymentCount) {
2878
+ if (!hasDeployments) {
2879
+ import_tracking.default.event({ category: "deployments", action: "create_initial_deployment" });
2880
+ if (isWithinFirstMonth(trial_expiration)) {
2881
+ import_tracking.default.event({ category: "deployments", action: "create_initial_deployment_first_month" });
2882
+ }
2883
+ }
2884
+ import_tracking.default.event({ category: "deployments", action: "create_initial_deployment_user" });
2885
+ }
2886
+ };
2832
2887
  var MAX_PREVIOUS_PHASES_COUNT = 5;
2833
2888
  var createDeployment = (0, import_toolkit18.createAsyncThunk)(`${sliceName2}/createDeployment`, ({ newDeployment, hasNewRetryDefault = false }, { dispatch, getState }) => {
2834
2889
  let request;
@@ -2839,6 +2894,9 @@ var createDeployment = (0, import_toolkit18.createAsyncThunk)(`${sliceName2}/cre
2839
2894
  } else {
2840
2895
  request = general_api_default.post(`${deploymentsApiUrl}/deployments`, newDeployment);
2841
2896
  }
2897
+ const totalDeploymentCount = Object.values(getDeploymentsByStatus(getState())).reduce((accu, item) => accu + item.total, 0);
2898
+ const { hasDeployments } = getGlobalSettings(getState());
2899
+ const { trial_expiration } = getOrganization(getState());
2842
2900
  return request.catch((err) => commonErrorHandler(err, "Error creating deployment.", dispatch)).then((data) => {
2843
2901
  const lastslashindex = data.headers.location.lastIndexOf("/");
2844
2902
  const deploymentId = data.headers.location.substring(lastslashindex + 1);
@@ -2853,6 +2911,7 @@ var createDeployment = (0, import_toolkit18.createAsyncThunk)(`${sliceName2}/cre
2853
2911
  dispatch(getSingleDeployment(deploymentId)),
2854
2912
  dispatch(setSnackbar2("Deployment created successfully", TIMEOUTS.fiveSeconds))
2855
2913
  ];
2914
+ trackDeploymentCreation(totalDeploymentCount, hasDeployments, trial_expiration);
2856
2915
  const { canManageUsers } = getUserCapabilities(getState());
2857
2916
  if (canManageUsers) {
2858
2917
  const { phases, retries } = newDeployment;
@@ -3090,1610 +3149,1604 @@ var saveDeltaDeploymentsConfig = (0, import_toolkit18.createAsyncThunk)(`${slice
3090
3149
  });
3091
3150
  });
3092
3151
 
3093
- // src/devicesSlice/thunks.tsx
3094
- var import_react_router_dom = require("react-router-dom");
3095
- var import_helpers9 = require("@northern.tech/utils/helpers");
3152
+ // src/monitorSlice/thunks.ts
3096
3153
  var import_toolkit19 = require("@reduxjs/toolkit");
3097
- var import_axios2 = require("axios");
3098
- var import_pluralize = __toESM(require("pluralize"), 1);
3099
- var import_uuid = require("uuid");
3100
- var import_jsx_runtime2 = require("react/jsx-runtime");
3101
- var { cleanUpUpload, initUpload, setSnackbar: setSnackbar3, uploadProgress: uploadProgress2 } = actions_default;
3102
3154
  var { page: defaultPage2, perPage: defaultPerPage2 } = DEVICE_LIST_DEFAULTS;
3103
- var defaultAttributes = [
3104
- { scope: "identity", attribute: "status" },
3105
- { scope: "inventory", attribute: "artifact_name" },
3106
- { scope: "inventory", attribute: "device_type" },
3107
- { scope: "inventory", attribute: "mender_is_gateway" },
3108
- { scope: "inventory", attribute: "mender_gateway_system_id" },
3109
- { scope: "inventory", attribute: rootfsImageVersion },
3110
- { scope: "monitor", attribute: "alerts" },
3111
- { scope: "system", attribute: "created_ts" },
3112
- { scope: "system", attribute: "updated_ts" },
3113
- { scope: "system", attribute: "check_in_time" },
3114
- { scope: "system", attribute: "group" },
3115
- { scope: "tags", attribute: "name" }
3116
- ];
3117
- var getGroups2 = (0, import_toolkit19.createAsyncThunk)(
3118
- `${sliceName3}/getGroups`,
3119
- (_, { dispatch, getState }) => general_api_default.get(`${inventoryApiUrl}/groups`).then((res) => {
3120
- const state = getGroupsById(getState());
3121
- const dynamicGroups = Object.entries(state).reduce((accu, [id, group]) => {
3122
- if (group.id || group.filters?.length && id !== UNGROUPED_GROUP.id) {
3123
- accu[id] = group;
3124
- }
3125
- return accu;
3126
- }, {});
3127
- const groups = res.data.reduce((accu, group) => {
3128
- accu[group] = { deviceIds: [], filters: [], total: 0, ...state[group] };
3129
- return accu;
3130
- }, dynamicGroups);
3131
- const filters = [{ key: "group", value: res.data, operator: DEVICE_FILTERING_OPTIONS.$nin.key, scope: "system" }];
3132
- return Promise.all([
3133
- dispatch(actions3.receivedGroups(groups)),
3134
- dispatch(getDevicesByStatus2({ filterSelection: filters, group: 0, page: 1, perPage: 1, status: void 0 }))
3135
- ]).then((promises) => {
3136
- const devicesRetrieval = promises[promises.length - 1] || [];
3137
- const { payload } = devicesRetrieval || {};
3138
- const result = payload[payload.length - 1] || {};
3139
- if (!result.total) {
3140
- return Promise.resolve();
3141
- }
3142
- return Promise.resolve(
3143
- dispatch(
3144
- actions3.addGroup({
3145
- groupName: UNGROUPED_GROUP.id,
3146
- group: { filters: [{ key: "group", value: res.data, operator: DEVICE_FILTERING_OPTIONS.$nin.key, scope: "system" }] }
3147
- })
3148
- )
3149
- );
3150
- });
3151
- })
3152
- );
3153
- var addDevicesToGroup = (0, import_toolkit19.createAsyncThunk)(
3154
- `${sliceName3}/addDevicesToGroup`,
3155
- ({ group, deviceIds, isCreation }, { dispatch }) => general_api_default.patch(`${inventoryApiUrl}/groups/${group}/devices`, deviceIds).then(() => dispatch(actions3.addToGroup({ group, deviceIds }))).finally(() => isCreation ? Promise.resolve(dispatch(getGroups2())) : {})
3156
- );
3157
- var removeDevicesFromGroup = (0, import_toolkit19.createAsyncThunk)(
3158
- `${sliceName3}/removeDevicesFromGroup`,
3159
- ({ group, deviceIds }, { dispatch }) => general_api_default.delete(`${inventoryApiUrl}/groups/${group}/devices`, deviceIds).then(
3160
- () => Promise.all([
3161
- dispatch(actions3.removeFromGroup({ group, deviceIds })),
3162
- dispatch(setSnackbar3(`The ${(0, import_pluralize.default)("devices", deviceIds.length)} ${(0, import_pluralize.default)("were", deviceIds.length)} removed from the group`, TIMEOUTS.fiveSeconds))
3155
+ var cutoffLength = 75;
3156
+ var ellipsis = "...";
3157
+ var longTextTrimmer = (text) => text.length >= cutoffLength + ellipsis.length ? `${text.substring(0, cutoffLength + ellipsis.length)}${ellipsis}` : text;
3158
+ var sanitizeDeviceAlerts = (alerts) => alerts.map((alert) => ({ ...alert, fullName: alert.name, name: longTextTrimmer(alert.name) }));
3159
+ var getDeviceAlerts = (0, import_toolkit19.createAsyncThunk)(`${sliceName4}/getDeviceAlerts`, ({ id, config = {} }, { dispatch }) => {
3160
+ const { page = defaultPage2, perPage = defaultPerPage2, issuedBefore, issuedAfter, sortAscending = false } = config;
3161
+ const issued_after = issuedAfter ? `&issued_after=${issuedAfter}` : "";
3162
+ const issued_before = issuedBefore ? `&issued_before=${issuedBefore}` : "";
3163
+ return general_api_default.get(`${monitorApiUrlv1}/devices/${id}/alerts?page=${page}&per_page=${perPage}${issued_after}${issued_before}&sort_ascending=${sortAscending}`).catch((err) => commonErrorHandler(err, `Retrieving device alerts for device ${id} failed:`, dispatch)).then(
3164
+ (res) => Promise.all([
3165
+ dispatch(actions4.receiveDeviceAlerts({ deviceId: id, alerts: sanitizeDeviceAlerts(res.data) })),
3166
+ dispatch(actions4.setAlertListState({ total: Number(res.headers[headerNames.total]) }))
3163
3167
  ])
3164
- )
3168
+ );
3169
+ });
3170
+ var getLatestDeviceAlerts = (0, import_toolkit19.createAsyncThunk)(`${sliceName4}/getLatestDeviceAlerts`, ({ id, config = {} }, { dispatch }) => {
3171
+ const { page = defaultPage2, perPage = 10 } = config;
3172
+ return general_api_default.get(`${monitorApiUrlv1}/devices/${id}/alerts/latest?page=${page}&per_page=${perPage}`).catch((err) => commonErrorHandler(err, `Retrieving device alerts for device ${id} failed:`, dispatch)).then((res) => Promise.resolve(dispatch(actions4.receiveLatestDeviceAlerts({ deviceId: id, alerts: sanitizeDeviceAlerts(res.data) }))));
3173
+ });
3174
+ var getIssueCountsByType2 = (0, import_toolkit19.createAsyncThunk)(`${sliceName4}/getIssueCountsByType`, ({ type, options = {} }, { dispatch, getState }) => {
3175
+ const state = getState();
3176
+ const { filters = getDeviceFilters(state), group, status, ...remainder } = options;
3177
+ const { applicableFilters: nonMonitorFilters, filterTerms } = convertDeviceListStateToFilters({
3178
+ ...remainder,
3179
+ filters,
3180
+ group,
3181
+ offlineThreshold: state.app.offlineThreshold,
3182
+ selectedIssues: [type],
3183
+ status
3184
+ });
3185
+ return general_api_default.post(getSearchEndpoint(getState()), {
3186
+ page: 1,
3187
+ per_page: 1,
3188
+ filters: filterTerms,
3189
+ attributes: [{ scope: "identity", attribute: "status" }]
3190
+ }).catch((err) => commonErrorHandler(err, `Retrieving issue counts failed:`, dispatch, commonErrorFallback)).then((res) => {
3191
+ const total = nonMonitorFilters.length ? state.monitor.issueCounts.byType[type].total : Number(res.headers[headerNames.total]);
3192
+ const filtered = nonMonitorFilters.length ? Number(res.headers[headerNames.total]) : total;
3193
+ if (total === state.monitor.issueCounts.byType[type].total && filtered === state.monitor.issueCounts.byType[type].filtered) {
3194
+ return Promise.resolve();
3195
+ }
3196
+ return Promise.resolve(dispatch(actions4.receiveDeviceIssueCounts({ counts: { filtered, total }, issueType: type })));
3197
+ });
3198
+ });
3199
+ var getDeviceMonitorConfig = (0, import_toolkit19.createAsyncThunk)(
3200
+ `${sliceName4}/getDeviceMonitorConfig`,
3201
+ (id, { dispatch }) => general_api_default.get(`${monitorApiUrlv1}/devices/${id}/config`).catch((err) => commonErrorHandler(err, `Retrieving device monitor config for device ${id} failed:`, dispatch)).then(({ data }) => Promise.all([dispatch(actions_default.receivedDevice({ id, monitors: data }), Promise.resolve(data))]))
3165
3202
  );
3166
- var getGroupNotification = (newGroup, selectedGroup) => {
3167
- const successMessage = "The group was updated successfully";
3168
- if (newGroup === selectedGroup) {
3169
- return [successMessage, TIMEOUTS.fiveSeconds];
3203
+ var changeNotificationSetting = (0, import_toolkit19.createAsyncThunk)(
3204
+ `${sliceName4}/changeNotificationSetting`,
3205
+ ({ enabled, channel = alertChannels.email }, { dispatch }) => {
3206
+ return general_api_default.put(`${monitorApiUrlv1}/settings/global/channel/alerts/${channel}/status`, { enabled }).catch((err) => commonErrorHandler(err, `${enabled ? "En" : "Dis"}abling ${channel} alerts failed:`, dispatch)).then(
3207
+ () => Promise.all([
3208
+ dispatch(actions4.changeAlertChannel({ channel, enabled })),
3209
+ dispatch(actions_default.setSnackbar(`Successfully ${enabled ? "en" : "dis"}abled ${channel} alerts`, TIMEOUTS.fiveSeconds))
3210
+ ])
3211
+ );
3170
3212
  }
3171
- return [
3172
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
3173
- successMessage,
3174
- " - ",
3175
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom.Link, { to: `/devices?inventory=group:eq:${newGroup}`, children: "click here" }),
3176
- " to see it."
3177
- ] }),
3178
- 5e3,
3179
- void 0,
3180
- void 0,
3181
- () => {
3213
+ );
3214
+
3215
+ // src/usersSlice/thunks.ts
3216
+ var import_helptips = require("@northern.tech/common-ui/helptips");
3217
+
3218
+ // src/api/users-api.ts
3219
+ var import_axios2 = __toESM(require("axios"), 1);
3220
+ var Api2 = {
3221
+ postLogin: (url, { email: username, password, ...body }) => import_axios2.default.post(url, body, { ...commonRequestConfig, auth: { username, password } }).then((res) => ({ text: res.data, code: res.status, contentType: res.headers?.["content-type"] })),
3222
+ putVerifyTFA: (url, userData) => {
3223
+ let body = {};
3224
+ if (userData.hasOwnProperty("token2fa")) {
3225
+ body = { token2fa: userData.token2fa };
3182
3226
  }
3183
- ];
3227
+ return import_axios2.default.put(url, body, { ...commonRequestConfig, headers: { ...commonRequestConfig.headers, Authorization: `Bearer ${getToken()}` } });
3228
+ }
3184
3229
  };
3185
- var addStaticGroup = (0, import_toolkit19.createAsyncThunk)(
3186
- `${sliceName3}/addStaticGroup`,
3187
- ({ group, devices }, { dispatch, getState }) => Promise.resolve(dispatch(addDevicesToGroup({ group, deviceIds: devices.map(({ id }) => id), isCreation: true }))).then(
3188
- () => Promise.resolve(
3189
- dispatch(
3190
- actions3.addGroup({
3191
- group: { deviceIds: [], total: 0, filters: [], ...getState().devices.groups.byId[group] },
3192
- groupName: group
3193
- })
3194
- )
3195
- ).then(
3196
- () => Promise.all([
3197
- dispatch(setDeviceListState({ setOnly: true })),
3198
- dispatch(getGroups2()),
3199
- dispatch(setSnackbar3(...getGroupNotification(group, getState().devices.groups.selectedGroup)))
3200
- ])
3201
- )
3202
- ).catch((err) => commonErrorHandler(err, `Group could not be updated:`, dispatch))
3230
+ var users_api_default = Api2;
3231
+
3232
+ // src/usersSlice/thunks.ts
3233
+ var import_helpers9 = require("@northern.tech/utils/helpers");
3234
+ var import_retrytimer = require("@northern.tech/utils/retrytimer");
3235
+ var import_toolkit20 = require("@reduxjs/toolkit");
3236
+ var import_md5 = __toESM(require("md5"), 1);
3237
+ var import_universal_cookie3 = __toESM(require("universal-cookie"), 1);
3238
+ var cookies3 = new import_universal_cookie3.default();
3239
+ var { setAnnouncement, setSnackbar: setSnackbar3 } = actions_default;
3240
+ var handleLoginError = (err, { token2fa: has2FA, password }, rejectWithValue) => (dispatch) => {
3241
+ const errorText = (0, import_helpers9.extractErrorMessage)(err);
3242
+ const is2FABackend = errorText.includes("2fa");
3243
+ if (is2FABackend && !has2FA) {
3244
+ return rejectWithValue({ error: "2fa code missing" });
3245
+ }
3246
+ if (password === void 0) {
3247
+ return Promise.reject();
3248
+ }
3249
+ const twoFAError = is2FABackend ? " and verification code" : "";
3250
+ const errorMessage = `There was a problem logging in. Please check your email${twoFAError ? "," : " and"} password${twoFAError}. If you still have problems, contact an administrator.`;
3251
+ return Promise.reject(dispatch(setSnackbar3({ message: (0, import_helpers9.preformatWithRequestID)(err.response, errorMessage), action: "Copy to clipboard" })));
3252
+ };
3253
+ var loginUser = (0, import_toolkit20.createAsyncThunk)(
3254
+ `${sliceName8}/loginUser`,
3255
+ ({ stayLoggedIn, ...userData }, { dispatch, rejectWithValue }) => users_api_default.postLogin(`${useradmApiUrlv1}/auth/login`, { ...userData, no_expiry: stayLoggedIn }).catch((err) => {
3256
+ cleanUp();
3257
+ return Promise.reject(dispatch(handleLoginError(err, userData, rejectWithValue)));
3258
+ }).then(({ text: response, contentType }) => {
3259
+ if (contentType.includes(APPLICATION_JSON_CONTENT_TYPE)) {
3260
+ const { id, kind } = response;
3261
+ const type = kind.split("/")[1];
3262
+ const ssoLoginUrl = SSO_TYPES[type].getStartUrl(id);
3263
+ window.location.replace(ssoLoginUrl);
3264
+ return;
3265
+ }
3266
+ const token = response;
3267
+ if (contentType !== APPLICATION_JWT_CONTENT_TYPE || !token) {
3268
+ return;
3269
+ }
3270
+ let now = /* @__PURE__ */ new Date();
3271
+ now.setSeconds(now.getSeconds() + maxSessionAge);
3272
+ const expiresAt = stayLoggedIn ? void 0 : now.toISOString();
3273
+ setSessionInfo({ token, expiresAt });
3274
+ cookies3.remove("JWT", { path: "/" });
3275
+ return dispatch(getUser(OWN_USER_ID)).unwrap().catch((e) => {
3276
+ cleanUp();
3277
+ return Promise.reject(dispatch(setSnackbar3((0, import_helpers9.extractErrorMessage)(e))));
3278
+ }).then(() => {
3279
+ window.sessionStorage.removeItem("pendings-redirect");
3280
+ if (window.location.pathname !== "/ui/") {
3281
+ window.location.replace("/ui/");
3282
+ }
3283
+ return Promise.resolve(dispatch(actions8.successfullyLoggedIn({ expiresAt, token })));
3284
+ });
3285
+ })
3203
3286
  );
3204
- var removeStaticGroup = (0, import_toolkit19.createAsyncThunk)(
3205
- `${sliceName3}/removeStaticGroup`,
3206
- (groupName, { dispatch }) => general_api_default.delete(`${inventoryApiUrl}/groups/${groupName}`).then(
3207
- () => Promise.all([
3208
- dispatch(actions3.removeGroup(groupName)),
3209
- dispatch(getGroups2()),
3210
- dispatch(setSnackbar3("Group was removed successfully", TIMEOUTS.fiveSeconds))
3211
- ])
3287
+ var logoutUser = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/logoutUser`, (_, { dispatch, getState }) => {
3288
+ if (Object.keys(getState().app.uploadsById).length) {
3289
+ return Promise.reject();
3290
+ }
3291
+ return general_api_default.post(`${useradmApiUrlv1}/auth/logout`).finally(() => {
3292
+ cleanUp();
3293
+ (0, import_retrytimer.clearAllRetryTimers)(setSnackbar3);
3294
+ return Promise.resolve(dispatch({ type: USER_LOGOUT }));
3295
+ });
3296
+ });
3297
+ var switchUserOrganization = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/switchUserOrganization`, (tenantId, { getState }) => {
3298
+ if (Object.keys(getState().app.uploadsById).length) {
3299
+ return Promise.reject();
3300
+ }
3301
+ return general_api_default.get(`${useradmApiUrlv1}/users/tenants/${tenantId}/token`).then(({ data: token }) => {
3302
+ window.sessionStorage.setItem("tenantChanged", "true");
3303
+ setSessionInfo({ ...getSessionInfo(), token });
3304
+ window.location.reload();
3305
+ });
3306
+ });
3307
+ var passwordResetStart = (0, import_toolkit20.createAsyncThunk)(
3308
+ `${sliceName8}/passwordResetStart`,
3309
+ (email, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/auth/password-reset/start`, { email }).catch(
3310
+ (err) => commonErrorHandler(err, `The password reset request cannot be processed:`, dispatch, void 0, true)
3212
3311
  )
3213
3312
  );
3214
- var getDynamicGroups = (0, import_toolkit19.createAsyncThunk)(
3215
- `${sliceName3}/getDynamicGroups`,
3216
- (_, { dispatch, getState }) => general_api_default.get(`${inventoryApiUrlV2}/filters?per_page=${MAX_PAGE_SIZE}`).then(({ data: filters }) => {
3217
- const state = getGroupsById(getState());
3218
- const staticGroups = Object.entries(state).reduce((accu, [id, group]) => {
3219
- if (!(group.id || group.filters?.length)) {
3220
- accu[id] = group;
3221
- }
3222
- return accu;
3223
- }, {});
3224
- const groups = (filters || []).reduce((accu, filter) => {
3225
- accu[filter.name] = {
3226
- deviceIds: [],
3227
- total: 0,
3228
- ...state[filter.name],
3229
- id: filter.id,
3230
- filters: mapTermsToFilters(filter.terms)
3231
- };
3232
- return accu;
3233
- }, staticGroups);
3234
- return Promise.resolve(dispatch(actions3.receivedGroups(groups)));
3235
- }).catch(() => console.log("Dynamic group retrieval failed - likely accessing a non-enterprise backend"))
3313
+ var passwordResetComplete = (0, import_toolkit20.createAsyncThunk)(
3314
+ `${sliceName8}/passwordResetComplete`,
3315
+ ({ secretHash, newPassword }, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/auth/password-reset/complete`, { secret_hash: secretHash, password: newPassword }).catch((err = {}) => {
3316
+ const { error, response = {} } = err;
3317
+ let errorMsg = "";
3318
+ if (response.status == 400) {
3319
+ errorMsg = "the link you are using expired or the request is not valid, please try again.";
3320
+ } else {
3321
+ errorMsg = error;
3322
+ }
3323
+ dispatch(setSnackbar3("The password reset request cannot be processed: " + errorMsg));
3324
+ return Promise.reject(err);
3325
+ })
3236
3326
  );
3237
- var addDynamicGroup = (0, import_toolkit19.createAsyncThunk)(
3238
- `${sliceName3}/addDynamicGroup`,
3239
- ({ groupName, filterPredicates }, { dispatch, getState }) => general_api_default.post(`${inventoryApiUrlV2}/filters`, { name: groupName, terms: mapFiltersToTerms(filterPredicates) }).then(
3240
- (res) => Promise.resolve(
3241
- dispatch(
3242
- actions3.addGroup({
3243
- groupName,
3244
- group: {
3245
- id: res.headers[headerNames.location].substring(res.headers[headerNames.location].lastIndexOf("/") + 1),
3246
- filters: filterPredicates
3247
- }
3248
- })
3249
- )
3250
- ).then(() => {
3251
- const { cleanedFilters } = getGroupFilters(groupName, getState().devices.groups);
3252
- return Promise.all([
3253
- dispatch(actions3.setDeviceFilters(cleanedFilters)),
3254
- dispatch(setSnackbar3(...getGroupNotification(groupName, getState().devices.groups.selectedGroup))),
3255
- dispatch(getDynamicGroups())
3256
- ]);
3257
- })
3258
- ).catch((err) => commonErrorHandler(err, `Group could not be updated:`, dispatch))
3327
+ var verifyEmailStart = (0, import_toolkit20.createAsyncThunk)(
3328
+ `${sliceName8}/verifyEmailStart`,
3329
+ (_, { dispatch, getState }) => general_api_default.post(`${useradmApiUrlv1}/auth/verify-email/start`, { email: getCurrentUser(getState()).email }).catch((err) => commonErrorHandler(err, "An error occured starting the email verification process:", dispatch)).finally(() => Promise.resolve(dispatch(getUser(OWN_USER_ID))))
3259
3330
  );
3260
- var updateDynamicGroup = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/updateDynamicGroup`, ({ groupName, filterPredicates }, { dispatch, getState }) => {
3261
- const filterId = getState().devices.groups.byId[groupName].id;
3262
- return general_api_default.delete(`${inventoryApiUrlV2}/filters/${filterId}`).then(() => Promise.resolve(dispatch(addDynamicGroup({ groupName, filterPredicates }))));
3263
- });
3264
- var removeDynamicGroup = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/removeDynamicGroup`, (groupName, { dispatch, getState }) => {
3265
- const filterId = getState().devices.groups.byId[groupName].id;
3266
- return general_api_default.delete(`${inventoryApiUrlV2}/filters/${filterId}`).then(
3267
- () => Promise.all([dispatch(actions3.removeGroup(groupName)), dispatch(setSnackbar3("Group was removed successfully", TIMEOUTS.fiveSeconds))])
3268
- );
3269
- });
3270
- var getGroupFilters = (group, groupsState, filters = []) => {
3271
- const groupName = group === UNGROUPED_GROUP.id || group === UNGROUPED_GROUP.name ? UNGROUPED_GROUP.id : group;
3272
- const selectedGroup = groupsState.byId[groupName];
3273
- const groupFilterLength = selectedGroup?.filters?.length || 0;
3274
- const cleanedFilters = groupFilterLength ? [...filters, ...selectedGroup.filters].filter(filtersFilter) : filters;
3275
- return { cleanedFilters, groupName, selectedGroup, groupFilterLength };
3276
- };
3277
- var selectGroup = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/selectGroup`, ({ group, filters = [] }, { dispatch, getState }) => {
3278
- const { cleanedFilters, groupName, selectedGroup, groupFilterLength } = getGroupFilters(group, getState().devices.groups, filters);
3279
- if (getSelectedGroup(getState()) === groupName && (filters.length === 0 && !groupFilterLength || filters.length === cleanedFilters.length)) {
3280
- return Promise.resolve();
3281
- }
3282
- let tasks = [];
3283
- if (groupFilterLength) {
3284
- tasks.push(dispatch(actions3.setDeviceFilters(cleanedFilters)));
3331
+ var verifyEmailComplete = (0, import_toolkit20.createAsyncThunk)(
3332
+ `${sliceName8}/verifyEmailComplete`,
3333
+ (secret_hash, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/auth/verify-email/complete`, { secret_hash }).catch((err) => commonErrorHandler(err, "An error occured completing the email verification process:", dispatch)).finally(() => Promise.resolve(dispatch(getUser(OWN_USER_ID))))
3334
+ );
3335
+ var verify2FA = (0, import_toolkit20.createAsyncThunk)(
3336
+ `${sliceName8}/verify2FA`,
3337
+ (tfaData, { dispatch }) => users_api_default.putVerifyTFA(`${useradmApiUrlv1}/2faverify`, tfaData).then(() => Promise.resolve(dispatch(getUser(OWN_USER_ID)))).catch(
3338
+ (err) => commonErrorHandler(err, "An error occured validating the verification code: failed to verify token, please try again.", dispatch, void 0, true)
3339
+ )
3340
+ );
3341
+ var getUserList = (0, import_toolkit20.createAsyncThunk)(
3342
+ `${sliceName8}/getUserList`,
3343
+ (_, { dispatch, getState }) => general_api_default.get(`${useradmApiUrlv1}/users`).then((res) => {
3344
+ const currentUsersById = getUsersById(getState());
3345
+ const users = res.data.reduce(
3346
+ (accu, item) => {
3347
+ accu[item.id] = {
3348
+ ...accu[item.id],
3349
+ ...item
3350
+ };
3351
+ return accu;
3352
+ },
3353
+ { ...currentUsersById }
3354
+ );
3355
+ return dispatch(actions8.receivedUserList(users));
3356
+ }).catch((err) => commonErrorHandler(err, `Users couldn't be loaded.`, dispatch, commonErrorFallback))
3357
+ );
3358
+ var getUser = (0, import_toolkit20.createAsyncThunk)(
3359
+ `${sliceName8}/getUser`,
3360
+ (id, { dispatch, rejectWithValue }) => general_api_default.get(`${useradmApiUrlv1}/users/${id}`).then(
3361
+ ({ data: user }) => Promise.all([
3362
+ dispatch(actions8.receivedUser(user)),
3363
+ dispatch(setHideAnnouncement({ shouldHide: false, userId: user.id })),
3364
+ dispatch(updateUserColumnSettings({ currentUserId: user.id })),
3365
+ user
3366
+ ])
3367
+ ).catch((e) => rejectWithValue(e))
3368
+ );
3369
+ var initializeSelf = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/initializeSelf`, (_, { dispatch }) => dispatch(getUser(OWN_USER_ID)));
3370
+ var updateUserColumnSettings = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/updateUserColumnSettings`, ({ columns, currentUserId }, { dispatch, getState }) => {
3371
+ const userId = currentUserId ?? getCurrentUser(getState()).id;
3372
+ const storageKey = `${userId}-column-widths`;
3373
+ let customColumns = [];
3374
+ if (!columns) {
3375
+ try {
3376
+ customColumns = JSON.parse(window.localStorage.getItem(storageKey)) || customColumns;
3377
+ } catch {
3378
+ }
3285
3379
  } else {
3286
- tasks.push(dispatch(actions3.setDeviceFilters(filters)));
3287
- tasks.push(dispatch(getGroupDevices({ group: groupName, perPage: 1, shouldIncludeAllStates: true })));
3380
+ customColumns = columns;
3288
3381
  }
3289
- const selectedGroupName = selectedGroup || !Object.keys(getGroupsById(getState())).length ? groupName : void 0;
3290
- tasks.push(dispatch(actions3.selectGroup(selectedGroupName)));
3291
- return Promise.all(tasks);
3382
+ window.localStorage.setItem(storageKey, JSON.stringify(customColumns));
3383
+ return Promise.resolve(dispatch(actions8.setCustomColumns(customColumns)));
3292
3384
  });
3293
- var getEarliestTs = (dateA = "", dateB = "") => !dateA || !dateB ? dateA || dateB : dateA < dateB ? dateA : dateB;
3294
- var reduceReceivedDevices = (devices, ids, state, status) => devices.reduce(
3295
- (accu, device) => {
3296
- const stateDevice = getDeviceById(state, device.id);
3297
- const {
3298
- attributes: storedAttributes = {},
3299
- identity_data: storedIdentity = {},
3300
- monitor: storedMonitor = {},
3301
- tags: storedTags = {},
3302
- group: storedGroup
3303
- } = stateDevice;
3304
- const { identity, inventory, monitor, system = {}, tags } = mapDeviceAttributes(device.attributes);
3305
- device.tags = { ...storedTags, ...tags };
3306
- device.group = system.group ?? storedGroup;
3307
- device.monitor = { ...storedMonitor, ...monitor };
3308
- device.identity_data = { ...storedIdentity, ...identity, ...device.identity_data ? device.identity_data : {} };
3309
- device.status = status ? status : device.status || identity.status;
3310
- device.check_in_time_rounded = system.check_in_time ?? stateDevice.check_in_time_rounded;
3311
- device.check_in_time_exact = device.check_in_time ?? stateDevice.check_in_time_exact;
3312
- device.created_ts = getEarliestTs(getEarliestTs(system.created_ts, device.created_ts), stateDevice.created_ts);
3313
- device.updated_ts = device.attributes ? device.updated_ts : stateDevice.updated_ts;
3314
- device.isNew = new Date(device.created_ts) > new Date(state.app.newThreshold);
3315
- device.isOffline = new Date(device.check_in_time_rounded) < new Date(state.app.offlineThreshold) || device.check_in_time_rounded === void 0;
3316
- device.attributes = device.attributes ? { ...storedAttributes, ...inventory } : storedAttributes;
3317
- accu.devicesById[device.id] = { ...stateDevice, ...device };
3318
- accu.ids.push(device.id);
3319
- return accu;
3385
+ var userActions = {
3386
+ add: {
3387
+ successMessage: "The user was added successfully.",
3388
+ errorMessage: "adding"
3320
3389
  },
3321
- { ids, devicesById: {} }
3322
- );
3323
- var getGroupDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getGroupDevices`, (options, { dispatch, getState }) => {
3324
- const { group, shouldIncludeAllStates, ...remainder } = options;
3325
- const { cleanedFilters: filterSelection } = getGroupFilters(group, getState().devices.groups);
3326
- return Promise.resolve(
3327
- dispatch(getDevicesByStatus2({ ...remainder, filterSelection, group, status: shouldIncludeAllStates ? void 0 : DEVICE_STATES.accepted }))
3328
- ).unwrap().then((results) => {
3329
- if (!group) {
3330
- return Promise.resolve();
3331
- }
3332
- const { deviceAccu, total } = results[results.length - 1];
3333
- const stateGroup = getState().devices.groups.byId[group];
3334
- if (!stateGroup && !total && !deviceAccu.ids.length) {
3335
- return Promise.resolve();
3336
- }
3337
- return Promise.resolve(
3338
- dispatch(
3339
- actions3.addGroup({
3340
- group: {
3341
- deviceIds: deviceAccu.ids.length === total || deviceAccu.ids.length > stateGroup?.deviceIds ? deviceAccu.ids : stateGroup.deviceIds,
3342
- total
3343
- },
3344
- groupName: group
3345
- })
3346
- )
3347
- );
3348
- });
3349
- });
3350
- var getAllGroupDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getAllGroupDevices`, (group, { dispatch, getState }) => {
3351
- if (!group || !!group && (!getGroupsById(getState())[group] || getGroupsById(getState())[group].filters.length)) {
3352
- return Promise.resolve();
3390
+ create: {
3391
+ successMessage: "The user was created successfully.",
3392
+ errorMessage: "creating"
3393
+ },
3394
+ edit: {
3395
+ successMessage: "The user has been updated.",
3396
+ errorMessage: "editing"
3397
+ },
3398
+ remove: {
3399
+ successMessage: "The user was removed from the system.",
3400
+ errorMessage: "removing"
3353
3401
  }
3354
- const { attributes, filterTerms } = prepareSearchArguments({
3355
- filters: [],
3356
- group,
3357
- state: getState(),
3358
- status: DEVICE_STATES.accepted
3359
- });
3360
- const getAllDevices = (perPage = MAX_PAGE_SIZE, page = defaultPage2, devices = []) => general_api_default.post(getSearchEndpoint(getState()), {
3361
- page,
3362
- per_page: perPage,
3363
- filters: filterTerms,
3364
- attributes
3365
- }).then((res) => {
3366
- const state = getState();
3367
- const deviceAccu = reduceReceivedDevices(res.data, devices, state);
3368
- dispatch(actions3.receivedDevices(deviceAccu.devicesById));
3369
- const total = Number(res.headers[headerNames.total]);
3370
- if (total > perPage * page) {
3371
- return getAllDevices(perPage, page + 1, deviceAccu.ids);
3372
- }
3373
- return Promise.resolve(dispatch(actions3.addGroup({ group: { deviceIds: deviceAccu.ids, total: deviceAccu.ids.length }, groupName: group })));
3374
- });
3375
- return getAllDevices();
3402
+ };
3403
+ var userActionErrorHandler = (err, type, dispatch) => commonErrorHandler(err, `There was an error ${userActions[type].errorMessage} the user.`, dispatch);
3404
+ var createUser = (0, import_toolkit20.createAsyncThunk)(
3405
+ `${sliceName8}/createUser`,
3406
+ ({ shouldResetPassword, ...userData }, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/users`, { ...userData, send_reset_password: shouldResetPassword }).then(() => Promise.all([dispatch(actions8.createdUser(userData)), dispatch(getUserList()), dispatch(setSnackbar3(userActions.create.successMessage))])).catch((err) => userActionErrorHandler(err, "create", dispatch))
3407
+ );
3408
+ var removeUser = (0, import_toolkit20.createAsyncThunk)(
3409
+ `${sliceName8}/removeUser`,
3410
+ (userId, { dispatch }) => general_api_default.delete(`${useradmApiUrlv1}/users/${userId}`).then(() => Promise.all([dispatch(actions8.removedUser(userId)), dispatch(getUserList()), dispatch(setSnackbar3(userActions.remove.successMessage))])).catch((err) => userActionErrorHandler(err, "remove", dispatch))
3411
+ );
3412
+ var editUser = (0, import_toolkit20.createAsyncThunk)(
3413
+ `${sliceName8}/editUser`,
3414
+ ({ id, ...userData }, { dispatch, getState }) => general_api_default.put(`${useradmApiUrlv1}/users/${id}`, userData).then(
3415
+ () => Promise.all([
3416
+ dispatch(actions8.updatedUser({ ...userData, id: id === OWN_USER_ID ? getCurrentUser(getState()).id : id })),
3417
+ dispatch(setSnackbar3(userActions.edit.successMessage))
3418
+ ])
3419
+ )
3420
+ );
3421
+ var addUserToCurrentTenant = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/addUserToTenant`, (userId, { dispatch, getState }) => {
3422
+ const { id } = getOrganization(getState());
3423
+ return general_api_default.post(`${useradmApiUrlv1}/users/${userId}/assign`, { tenant_ids: [id] }).catch((err) => commonErrorHandler(err, `There was an error adding the user to your organization:`, dispatch)).then(() => Promise.all([dispatch(setSnackbar3(userActions.add.successMessage)), dispatch(getUserList())]));
3376
3424
  });
3377
- var getAllDynamicGroupDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getAllDynamicGroupDevices`, (group, { dispatch, getState }) => {
3378
- if (!!group && (!getGroupsById(getState())[group] || !getGroupsById(getState())[group].filters.length)) {
3379
- return Promise.resolve();
3380
- }
3381
- const { attributes, filterTerms: filters } = prepareSearchArguments({
3382
- filters: getState().devices.groups.byId[group].filters,
3383
- state: getState(),
3384
- status: DEVICE_STATES.accepted
3385
- });
3386
- const getAllDevices = (perPage = MAX_PAGE_SIZE, page = defaultPage2, devices = []) => general_api_default.post(getSearchEndpoint(getState()), { page, per_page: perPage, filters, attributes }).then((res) => {
3387
- const state = getState();
3388
- const deviceAccu = reduceReceivedDevices(res.data, devices, state);
3389
- dispatch(actions3.receivedDevices(deviceAccu.devicesById));
3390
- const total = Number(res.headers[headerNames.total]);
3391
- if (total > deviceAccu.ids.length) {
3392
- return getAllDevices(perPage, page + 1, deviceAccu.ids);
3425
+ var enableUser2fa = (0, import_toolkit20.createAsyncThunk)(
3426
+ `${sliceName8}/enableUser2fa`,
3427
+ (userId = OWN_USER_ID, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/users/${userId}/2fa/enable`).catch((err) => commonErrorHandler(err, `There was an error enabling Two Factor authentication for the user.`, dispatch)).then(() => Promise.resolve(dispatch(getUser(userId))))
3428
+ );
3429
+ var disableUser2fa = (0, import_toolkit20.createAsyncThunk)(
3430
+ `${sliceName8}/disableUser2fa`,
3431
+ (userId = OWN_USER_ID, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/users/${userId}/2fa/disable`).catch((err) => commonErrorHandler(err, `There was an error disabling Two Factor authentication for the user.`, dispatch)).then(() => Promise.all([dispatch(getUser(userId)), dispatch(actions8.receivedQrCode(null))]))
3432
+ );
3433
+ var mapHttpPermission = (permission) => Object.entries(uiPermissionsByArea).reduce(
3434
+ (accu, [area, definition]) => {
3435
+ const endpointMatches = definition.endpoints.filter(
3436
+ (endpoint) => endpoint.path.test(permission.value) && (endpoint.types.includes(permission.type) || permission.type === PermissionTypes.Any)
3437
+ );
3438
+ if (permission.value === PermissionTypes.Any || permission.value.includes(apiRoot) && endpointMatches.length) {
3439
+ const endpointUiPermission = endpointMatches.reduce((endpointAccu, endpoint) => [...endpointAccu, ...endpoint.uiPermissions], []);
3440
+ const collector = (endpointUiPermission || definition.uiPermissions).reduce((permissionsAccu, uiPermission) => {
3441
+ if (permission.type === PermissionTypes.Any || !endpointMatches.length && uiPermission.verbs.some((verb) => verb === permission.type)) {
3442
+ permissionsAccu.push(uiPermission.value);
3443
+ }
3444
+ return permissionsAccu;
3445
+ }, []).filter(import_helpers9.duplicateFilter);
3446
+ if (Array.isArray(accu[area])) {
3447
+ accu[area] = [...accu[area], ...collector].filter(import_helpers9.duplicateFilter);
3448
+ } else {
3449
+ accu[area] = mergePermissions(accu[area], { [scopedPermissionAreas[area].excessiveAccessSelector]: collector });
3450
+ }
3393
3451
  }
3394
- return Promise.resolve(dispatch(actions3.addGroup({ group: { deviceIds: deviceAccu.ids, total }, groupName: group })));
3395
- });
3396
- return getAllDevices();
3397
- });
3398
- var getDeviceById2 = (0, import_toolkit19.createAsyncThunk)(
3399
- `${sliceName3}/getDeviceById`,
3400
- (id, { dispatch, getState }) => general_api_default.get(`${inventoryApiUrl}/devices/${id}`).then((res) => {
3401
- const device = reduceReceivedDevices([res.data], [], getState()).devicesById[id];
3402
- device.etag = res.headers.etag;
3403
- dispatch(actions3.receivedDevice(device));
3404
- return Promise.resolve(device);
3405
- }).catch((err) => {
3406
- const errMsg = (0, import_helpers9.extractErrorMessage)(err);
3407
- if (errMsg.includes("Not Found")) {
3408
- console.log(`${id} does not have any inventory information`);
3409
- const device = reduceReceivedDevices(
3410
- [
3411
- {
3412
- id,
3413
- attributes: [
3414
- { name: "status", value: "decomissioned", scope: "identity" },
3415
- { name: "decomissioned", value: "true", scope: "inventory" }
3416
- ]
3417
- }
3418
- ],
3419
- [],
3420
- getState()
3421
- ).devicesById[id];
3422
- dispatch(actions3.receivedDevice(device));
3423
- }
3424
- })
3452
+ return accu;
3453
+ },
3454
+ { ...emptyUiPermissions }
3425
3455
  );
3426
- var getDeviceInfo = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getDeviceInfo`, (deviceId, { dispatch, getState }) => {
3427
- const device = getDeviceById(getState(), deviceId);
3428
- const { hasDeviceConfig, hasDeviceConnect, hasMonitor } = getTenantCapabilities(getState());
3429
- const { canConfigure } = getUserCapabilities(getState());
3430
- const integrations = getDeviceTwinIntegrations(getState());
3431
- let tasks = [dispatch(getDeviceAuth(deviceId)), ...integrations.map((integration) => dispatch(getDeviceTwin({ deviceId, integration })))];
3432
- if (hasDeviceConfig && canConfigure && [DEVICE_STATES.accepted, DEVICE_STATES.preauth].includes(device.status)) {
3433
- tasks.push(dispatch(getDeviceConfig(deviceId)));
3434
- }
3435
- if (device.status === DEVICE_STATES.accepted) {
3436
- tasks.push(dispatch(getDeviceById2(deviceId)));
3437
- if (hasDeviceConnect) {
3438
- tasks.push(dispatch(getDeviceConnect(deviceId)));
3439
- }
3440
- if (hasMonitor) {
3441
- tasks.push(dispatch(getLatestDeviceAlerts({ id: deviceId })));
3442
- tasks.push(dispatch(getDeviceMonitorConfig(deviceId)));
3443
- }
3456
+ var permissionActionTypes = {
3457
+ any: mapHttpPermission,
3458
+ CREATE_DEPLOYMENT: (permission) => permission.type === PermissionTypes.DeviceGroup ? {
3459
+ deployments: [uiPermissionsById.deploy.value],
3460
+ groups: { [permission.value]: [uiPermissionsById.deploy.value] }
3461
+ } : {},
3462
+ http: mapHttpPermission,
3463
+ REMOTE_TERMINAL: (permission) => permission.type === PermissionTypes.DeviceGroup ? {
3464
+ groups: { [permission.value]: [uiPermissionsById.connect.value] }
3465
+ } : {},
3466
+ VIEW_DEVICE: (permission) => permission.type === PermissionTypes.DeviceGroup ? {
3467
+ groups: { [permission.value]: [uiPermissionsById.read.value] }
3468
+ } : {}
3469
+ };
3470
+ var combinePermissions = (existingPermissions, additionalPermissions = {}) => Object.entries(additionalPermissions).reduce((accu, [name, permissions]) => {
3471
+ let maybeExistingPermissions = accu[name] || [];
3472
+ accu[name] = [...permissions, ...maybeExistingPermissions].filter(import_helpers9.duplicateFilter);
3473
+ return accu;
3474
+ }, existingPermissions);
3475
+ var tryParseCustomPermission = (permission) => {
3476
+ const uiPermissions = permissionActionTypes[permission.action](permission.object);
3477
+ const result = mergePermissions({ ...emptyUiPermissions }, uiPermissions);
3478
+ return { isCustom: true, permission, result };
3479
+ };
3480
+ var customPermissionHandler = (accu, permission) => {
3481
+ let processor = tryParseCustomPermission(permission);
3482
+ return {
3483
+ ...accu,
3484
+ isCustom: accu.isCustom || processor.isCustom,
3485
+ uiPermissions: mergePermissions(accu.uiPermissions, processor.result)
3486
+ };
3487
+ };
3488
+ var mapPermissionSet = (permissionSetName, names, scope, existingGroupsPermissions = {}) => {
3489
+ const permission = Object.values(uiPermissionsById).find((permission2) => permission2.permissionSets[scope] === permissionSetName).value;
3490
+ const scopedPermissions = names.reduce((accu, name) => combinePermissions(accu, { [name]: [permission] }), existingGroupsPermissions);
3491
+ return Object.entries(scopedPermissions).reduce((accu, [key, permissions]) => ({ ...accu, [key]: deriveImpliedAreaPermissions(scope, permissions) }), {});
3492
+ };
3493
+ var isEmptyPermissionSet = (permissionSet) => !Object.values(permissionSet).reduce((accu, permissions) => {
3494
+ if (Array.isArray(permissions)) {
3495
+ return accu || !!permissions.length;
3444
3496
  }
3445
- return Promise.all(tasks);
3446
- });
3447
- var deriveInactiveDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/deriveInactiveDevices`, (deviceIds, { dispatch, getState }) => {
3448
- const yesterday = /* @__PURE__ */ new Date();
3449
- yesterday.setDate(yesterday.getDate() - 1);
3450
- const yesterdaysIsoString = yesterday.toISOString();
3451
- const devices = deviceIds.reduce(
3452
- (accu, id) => {
3453
- const device = getDeviceById(getState(), id);
3454
- if (device && device.updated_ts > yesterdaysIsoString) {
3455
- accu.active.push(id);
3456
- } else {
3457
- accu.inactive.push(id);
3497
+ return accu || !(0, import_helpers9.isEmpty)(permissions);
3498
+ }, false);
3499
+ var parseRolePermissions = ({ permission_sets_with_scope = [], permissions = [] }, permissionSets) => {
3500
+ const preliminaryResult = permission_sets_with_scope.reduce(
3501
+ (accu, permissionSet) => {
3502
+ let processor = permissionSets[permissionSet.name];
3503
+ if (!processor) {
3504
+ return accu;
3458
3505
  }
3459
- return accu;
3506
+ const scope = Object.keys(scopedPermissionAreas).find((scope2) => uiPermissionsByArea[scope2].scope === permissionSet.scope?.type);
3507
+ if (scope) {
3508
+ const result = mapPermissionSet(permissionSet.name, permissionSet.scope.value, scope, accu.uiPermissions[scope]);
3509
+ return { ...accu, uiPermissions: { ...accu.uiPermissions, [scope]: result } };
3510
+ } else if (isEmptyPermissionSet(processor.result)) {
3511
+ return processor.permissions.reduce(customPermissionHandler, accu);
3512
+ }
3513
+ return {
3514
+ ...accu,
3515
+ isCustom: accu.isCustom || processor.isCustom,
3516
+ uiPermissions: mergePermissions(accu.uiPermissions, processor.result)
3517
+ };
3460
3518
  },
3461
- { active: [], inactive: [] }
3519
+ { isCustom: false, uiPermissions: { ...emptyUiPermissions, groups: {}, releases: {} } }
3462
3520
  );
3463
- return dispatch(actions3.setInactiveDevices({ activeDeviceTotal: devices.active.length, inactiveDeviceTotal: devices.inactive.length }));
3464
- });
3465
- var getDeviceCount = (0, import_toolkit19.createAsyncThunk)(
3466
- `${sliceName3}/getDeviceCount`,
3467
- (status, { dispatch, getState }) => general_api_default.post(getSearchEndpoint(getState()), {
3468
- page: 1,
3469
- per_page: 1,
3470
- filters: mapFiltersToTerms([{ key: "status", value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: "identity" }]),
3471
- attributes: defaultAttributes
3472
- }).then((response) => {
3473
- const count = Number(response.headers[headerNames.total]);
3474
- if (status) {
3475
- return dispatch(actions3.setDevicesCountByStatus({ count, status }));
3521
+ return permissions.reduce(customPermissionHandler, preliminaryResult);
3522
+ };
3523
+ var normalizeRbacRoles = (roles, rolesById2, permissionSets) => roles.reduce(
3524
+ (accu, role) => {
3525
+ let normalizedPermissions;
3526
+ let isCustom = false;
3527
+ if (rolesById2[role.name]) {
3528
+ normalizedPermissions = {
3529
+ ...rolesById2[role.name].uiPermissions,
3530
+ groups: { ...rolesById2[role.name].uiPermissions.groups },
3531
+ releases: { ...rolesById2[role.name].uiPermissions.releases }
3532
+ };
3533
+ } else {
3534
+ const result = parseRolePermissions(role, permissionSets);
3535
+ normalizedPermissions = result.uiPermissions;
3536
+ isCustom = result.isCustom;
3476
3537
  }
3477
- return dispatch(actions3.setTotalDevices(count));
3478
- })
3479
- );
3480
- var getAllDeviceCounts = (0, import_toolkit19.createAsyncThunk)(
3481
- `${sliceName3}/getAllDeviceCounts`,
3482
- (_, { dispatch }) => Promise.all([DEVICE_STATES.accepted, DEVICE_STATES.pending].map((status) => dispatch(getDeviceCount(status))))
3538
+ const roleState = accu[role.name] ?? { ...emptyRole };
3539
+ accu[role.name] = {
3540
+ ...roleState,
3541
+ ...role,
3542
+ description: roleState.description ? roleState.description : role.description,
3543
+ editable: !rolesById[role.name] && !isCustom && (typeof roleState.editable !== "undefined" ? roleState.editable : true),
3544
+ isCustom,
3545
+ name: roleState.name ? roleState.name : role.name,
3546
+ uiPermissions: normalizedPermissions
3547
+ };
3548
+ return accu;
3549
+ },
3550
+ { ...rolesById2 }
3483
3551
  );
3484
- var getDeviceLimit2 = (0, import_toolkit19.createAsyncThunk)(
3485
- `${sliceName3}/getDeviceLimit`,
3486
- (_, { dispatch }) => general_api_default.get(`${deviceAuthV2}/limits/max_devices`).then((res) => dispatch(actions3.setDeviceLimit(res.data.limit)))
3552
+ var getPermissionSets = (0, import_toolkit20.createAsyncThunk)(
3553
+ `${sliceName8}/getPermissionSets`,
3554
+ (_, { dispatch, getState }) => general_api_default.get(`${useradmApiUrlv2}/permission_sets?per_page=500`).then(({ data }) => {
3555
+ const permissionSets = data.reduce(
3556
+ (accu, permissionSet) => {
3557
+ const permissionSetState = accu[permissionSet.name] ?? {};
3558
+ let permissionSetObject = { ...permissionSetState, ...permissionSet };
3559
+ permissionSetObject.result = Object.values(uiPermissionsById).reduce(
3560
+ (accu2, item) => Object.entries(item.permissionSets).reduce((collector, [area, permissionSet2]) => {
3561
+ if (scopedPermissionAreas[area]) {
3562
+ return collector;
3563
+ }
3564
+ if (permissionSet2 === permissionSetObject.name) {
3565
+ collector[area] = [...collector[area], item.value].filter(import_helpers9.duplicateFilter);
3566
+ }
3567
+ return collector;
3568
+ }, accu2),
3569
+ { ...emptyUiPermissions, ...permissionSetObject.result ?? {} }
3570
+ );
3571
+ const scopes = Object.values(scopedPermissionAreas).reduce((accu2, { key, scopeType }) => {
3572
+ if (permissionSetObject.supported_scope_types?.includes(key) || permissionSetObject.supported_scope_types?.includes(scopeType)) {
3573
+ accu2.push(key);
3574
+ }
3575
+ return accu2;
3576
+ }, []);
3577
+ permissionSetObject = scopes.reduce((accu2, scope) => {
3578
+ accu2.result[scope] = mapPermissionSet(permissionSetObject.name, [scopedPermissionAreas[scope].excessiveAccessSelector], scope);
3579
+ return accu2;
3580
+ }, permissionSetObject);
3581
+ accu[permissionSet.name] = permissionSetObject;
3582
+ return accu;
3583
+ },
3584
+ { ...getState().users.permissionSetsById }
3585
+ );
3586
+ return Promise.all([dispatch(actions8.receivedPermissionSets(permissionSets)), permissionSets]);
3587
+ }).catch(() => console.log("Permission set retrieval failed - likely accessing a non-RBAC backend"))
3487
3588
  );
3488
- var setDeviceListState = (0, import_toolkit19.createAsyncThunk)(
3489
- `${sliceName3}/setDeviceListState`,
3490
- ({ shouldSelectDevices = true, forceRefresh, fetchAuth = true, ...selectionState }, { dispatch, getState }) => {
3491
- const currentState = getDeviceListState(getState());
3492
- const refreshTrigger = forceRefresh ? !currentState.refreshTrigger : selectionState.refreshTrigger;
3493
- let nextState = {
3494
- ...currentState,
3495
- setOnly: false,
3496
- refreshTrigger,
3497
- ...selectionState,
3498
- sort: { ...currentState.sort, ...selectionState.sort }
3499
- };
3500
- let tasks = [];
3501
- const { isLoading: currentLoading, deviceIds: currentDevices, selection: currentSelection, ...currentRequestState } = currentState;
3502
- const { isLoading: nextLoading, deviceIds: nextDevices, selection: nextSelection, ...nextRequestState } = nextState;
3503
- if (!nextState.setOnly && !(0, import_helpers9.deepCompare)(currentRequestState, nextRequestState)) {
3504
- const { direction: sortDown = SORTING_OPTIONS.desc, key: sortCol, scope: sortScope } = nextState.sort ?? {};
3505
- const sortBy = sortCol ? [{ attribute: sortCol, order: sortDown, scope: sortScope }] : void 0;
3506
- const applicableSelectedState = nextState.state === ALL_DEVICE_STATES ? void 0 : nextState.state;
3507
- nextState.isLoading = true;
3508
- tasks.push(
3509
- dispatch(getDevicesByStatus2({ ...nextState, status: applicableSelectedState, sortOptions: sortBy, fetchAuth })).unwrap().then((results) => {
3510
- const { deviceAccu, total } = results[results.length - 1];
3511
- const devicesState = shouldSelectDevices ? { deviceIds: deviceAccu.ids, total, isLoading: false } : { isLoading: false };
3512
- return Promise.resolve(dispatch(actions3.setDeviceListState(devicesState)));
3513
- }).catch(() => Promise.resolve({ isLoading: false }))
3514
- );
3589
+ var getRoles = (0, import_toolkit20.createAsyncThunk)(
3590
+ `${sliceName8}/getRoles`,
3591
+ (_, { dispatch, getState }) => Promise.all([general_api_default.get(`${useradmApiUrlv2}/roles?per_page=500`), dispatch(getPermissionSets())]).then((results) => {
3592
+ if (!results) {
3593
+ return Promise.resolve();
3515
3594
  }
3516
- tasks.push(dispatch(actions3.setDeviceListState(nextState)));
3517
- return Promise.all(tasks);
3518
- }
3595
+ const [{ data: roles }, { payload: permissionSetTasks }] = results;
3596
+ const rolesById2 = normalizeRbacRoles(roles, getRolesById(getState()), permissionSetTasks[permissionSetTasks.length - 1]);
3597
+ return Promise.resolve(dispatch(actions8.receivedRoles(rolesById2)));
3598
+ }).catch(() => console.log("Role retrieval failed - likely accessing a non-RBAC backend"))
3519
3599
  );
3520
- var getDevicesByStatus2 = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getDevicesByStatus`, (options, { dispatch, getState }) => {
3521
- const {
3522
- status,
3523
- fetchAuth = true,
3524
- filterSelection,
3525
- group,
3526
- selectedIssues = [],
3527
- page = defaultPage2,
3528
- perPage = defaultPerPage2,
3529
- sortOptions = [],
3530
- selectedAttributes = []
3531
- } = options;
3532
- const state = getState();
3533
- const { applicableFilters, filterTerms } = convertDeviceListStateToFilters({
3534
- filters: filterSelection ?? getDeviceFilters(state),
3535
- group: group ?? getSelectedGroup(state),
3536
- groups: state.devices.groups,
3537
- offlineThreshold: state.app.offlineThreshold,
3538
- selectedIssues,
3539
- status
3540
- });
3541
- const attributes = [...defaultAttributes, getIdAttribute(getState()), ...selectedAttributes];
3542
- return general_api_default.post(getSearchEndpoint(getState()), {
3543
- page,
3544
- per_page: perPage,
3545
- filters: filterTerms,
3546
- sort: sortOptions,
3547
- attributes
3548
- }).then((response) => {
3549
- const state2 = getState();
3550
- const deviceAccu = reduceReceivedDevices(response.data, [], state2, status);
3551
- let total = !applicableFilters.length ? Number(response.headers[headerNames.total]) : null;
3552
- if (status && state2.devices.byStatus[status].total === deviceAccu.ids.length) {
3553
- total = deviceAccu.ids.length;
3554
- }
3555
- let tasks = [dispatch(actions3.receivedDevices(deviceAccu.devicesById))];
3556
- if (status) {
3557
- tasks.push(dispatch(actions3.setDevicesByStatus({ deviceIds: deviceAccu.ids, status, total })));
3558
- }
3559
- const receivedDevices = Object.values(deviceAccu.devicesById);
3560
- if (receivedDevices.length && fetchAuth) {
3561
- tasks.push(dispatch(getDevicesWithAuth(receivedDevices)));
3562
- }
3563
- tasks.push(Promise.resolve({ deviceAccu, total: Number(response.headers[headerNames.total]) }));
3564
- return Promise.all(tasks);
3565
- }).catch((err) => commonErrorHandler(err, `${status} devices couldn't be loaded.`, dispatch, commonErrorFallback));
3566
- });
3567
- var getAllDevicesByStatus = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getAllDevicesByStatus`, (status, { dispatch, getState }) => {
3568
- const attributes = [...defaultAttributes, getIdAttribute(getState())];
3569
- const getAllDevices = (perPage = MAX_PAGE_SIZE, page = 1, devices = []) => general_api_default.post(getSearchEndpoint(getState()), {
3570
- page,
3571
- per_page: perPage,
3572
- filters: mapFiltersToTerms([{ key: "status", value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: "identity" }]),
3573
- attributes
3574
- }).then((res) => {
3575
- const state = getState();
3576
- const deviceAccu = reduceReceivedDevices(res.data, devices, state, status);
3577
- dispatch(actions3.receivedDevices(deviceAccu.devicesById));
3578
- const total = Number(res.headers[headerNames.total]);
3579
- if (total > state.deployments.deploymentDeviceLimit) {
3580
- return Promise.resolve();
3581
- }
3582
- if (total > perPage * page) {
3583
- return getAllDevices(perPage, page + 1, deviceAccu.ids);
3600
+ var deriveImpliedAreaPermissions = (area, areaPermissions, skipPermissions = []) => {
3601
+ const highestAreaPermissionLevelSelected = areaPermissions.reduce(
3602
+ (highest, current) => uiPermissionsById[current].permissionLevel > highest ? uiPermissionsById[current].permissionLevel : highest,
3603
+ 1
3604
+ );
3605
+ return uiPermissionsByArea[area].uiPermissions.reduce((permissions, current) => {
3606
+ if ((current.permissionLevel < highestAreaPermissionLevelSelected || areaPermissions.includes(current.value)) && !skipPermissions.includes(current.value)) {
3607
+ permissions.push(current.value);
3584
3608
  }
3585
- let tasks = [dispatch(actions3.setDevicesByStatus({ deviceIds: deviceAccu.ids, forceUpdate: true, status, total: deviceAccu.ids.length }))];
3586
- if (status === DEVICE_STATES.accepted && deviceAccu.ids.length === total) {
3587
- tasks.push(dispatch(deriveInactiveDevices(deviceAccu.ids)));
3588
- tasks.push(dispatch(deriveReportsData()));
3609
+ return permissions;
3610
+ }, []);
3611
+ };
3612
+ var transformAreaRoleDataToScopedPermissionsSets = (area, areaPermissions, excessiveAccessSelector) => {
3613
+ const permissionSetObject = areaPermissions.reduce((accu, { item, uiPermissions }) => {
3614
+ const skipPermissions = scopedPermissionAreas.releases.key === area && item !== ALL_RELEASES ? [uiPermissionsById.upload.value] : [];
3615
+ const impliedPermissions = deriveImpliedAreaPermissions(area, uiPermissions, skipPermissions);
3616
+ accu = impliedPermissions.reduce((itemPermissionAccu, impliedPermission) => {
3617
+ const permissionSetState = itemPermissionAccu[uiPermissionsById[impliedPermission].permissionSets[area]] ?? {
3618
+ type: uiPermissionsByArea[area].scope,
3619
+ value: []
3620
+ };
3621
+ itemPermissionAccu[uiPermissionsById[impliedPermission].permissionSets[area]] = {
3622
+ ...permissionSetState,
3623
+ value: [...permissionSetState.value, item]
3624
+ };
3625
+ return itemPermissionAccu;
3626
+ }, accu);
3627
+ return accu;
3628
+ }, {});
3629
+ return Object.entries(permissionSetObject).map(([name, { value, ...scope }]) => {
3630
+ if (value.includes(excessiveAccessSelector)) {
3631
+ return { name };
3589
3632
  }
3590
- return Promise.all(tasks);
3633
+ return { name, scope: { ...scope, value: value.filter(import_helpers9.duplicateFilter) } };
3591
3634
  });
3592
- return getAllDevices();
3593
- });
3594
- var searchDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/searchDevices`, (passedOptions = {}, { dispatch, getState }) => {
3595
- const state = getState();
3596
- let options = { ...state.app.searchState, ...passedOptions };
3597
- const { page = defaultPage2, searchTerm, sortOptions = [] } = options;
3598
- const { columnSelection = [] } = getUserSettings(state);
3599
- const selectedAttributes = columnSelection.map((column) => ({ attribute: column.key, scope: column.scope }));
3600
- const attributes = (0, import_helpers9.attributeDuplicateFilter)([...defaultAttributes, getIdAttribute(state), ...selectedAttributes], "attribute");
3601
- return general_api_default.post(getSearchEndpoint(getState()), {
3602
- page,
3603
- per_page: 10,
3604
- filters: [],
3605
- sort: sortOptions,
3606
- text: searchTerm,
3607
- attributes
3608
- }).then((response) => {
3609
- const deviceAccu = reduceReceivedDevices(response.data, [], getState());
3610
- return Promise.all([
3611
- dispatch(actions3.receivedDevices(deviceAccu.devicesById)),
3612
- Promise.resolve({ deviceIds: deviceAccu.ids, searchTotal: Number(response.headers[headerNames.total]) })
3613
- ]);
3614
- }).catch((err) => commonErrorHandler(err, `devices couldn't be searched.`, dispatch, commonErrorFallback));
3615
- });
3616
- var ATTRIBUTE_LIST_CUTOFF = 100;
3617
- var attributeReducer = (attributes = []) => attributes.slice(0, ATTRIBUTE_LIST_CUTOFF).reduce(
3618
- (accu, { name, scope }) => {
3619
- if (!accu[scope]) {
3620
- accu[scope] = [];
3635
+ };
3636
+ var transformRoleDataToRole = (roleData, roleState = {}) => {
3637
+ const role = { ...roleState, ...roleData };
3638
+ const { description = "", name, uiPermissions = emptyUiPermissions } = role;
3639
+ const { maybeUiPermissions, remainderKeys } = Object.entries(emptyUiPermissions).reduce(
3640
+ (accu, [key, emptyPermissions]) => {
3641
+ if (!scopedPermissionAreas[key]) {
3642
+ accu.remainderKeys.push(key);
3643
+ } else if (uiPermissions[key]) {
3644
+ accu.maybeUiPermissions[key] = uiPermissions[key].reduce(itemUiPermissionsReducer, emptyPermissions);
3645
+ }
3646
+ return accu;
3647
+ },
3648
+ { maybeUiPermissions: {}, remainderKeys: [] }
3649
+ );
3650
+ const { permissionSetsWithScope, roleUiPermissions } = remainderKeys.reduce(
3651
+ (accu, area) => {
3652
+ const areaPermissions = role.uiPermissions[area];
3653
+ if (!Array.isArray(areaPermissions)) {
3654
+ return accu;
3655
+ }
3656
+ const impliedPermissions = deriveImpliedAreaPermissions(area, areaPermissions);
3657
+ accu.roleUiPermissions[area] = impliedPermissions;
3658
+ const mappedPermissions = impliedPermissions.map((uiPermission) => ({ name: uiPermissionsById[uiPermission].permissionSets[area] }));
3659
+ accu.permissionSetsWithScope.push(...mappedPermissions);
3660
+ return accu;
3661
+ },
3662
+ { permissionSetsWithScope: [{ name: defaultPermissionSets.Basic.name }], roleUiPermissions: {} }
3663
+ );
3664
+ const scopedPermissionSets = Object.values(scopedPermissionAreas).reduce((accu, { key, excessiveAccessSelector }) => {
3665
+ if (!uiPermissions[key]) {
3666
+ return accu;
3621
3667
  }
3622
- accu[scope].push(name);
3668
+ accu.push(...transformAreaRoleDataToScopedPermissionsSets(key, uiPermissions[key], excessiveAccessSelector));
3623
3669
  return accu;
3670
+ }, []);
3671
+ return {
3672
+ permissionSetsWithScope: [...permissionSetsWithScope, ...scopedPermissionSets],
3673
+ role: {
3674
+ ...emptyRole,
3675
+ name,
3676
+ description: description ? description : roleState.description,
3677
+ uiPermissions: {
3678
+ ...emptyUiPermissions,
3679
+ ...roleUiPermissions,
3680
+ ...maybeUiPermissions
3681
+ }
3682
+ }
3683
+ };
3684
+ };
3685
+ var roleActions = {
3686
+ create: {
3687
+ successMessage: "The role was created successfully.",
3688
+ errorMessage: "creating"
3624
3689
  },
3625
- { identity: [], inventory: [], system: [], tags: [] }
3690
+ edit: {
3691
+ successMessage: "The role has been updated.",
3692
+ errorMessage: "editing"
3693
+ },
3694
+ remove: {
3695
+ successMessage: "The role was deleted successfully.",
3696
+ errorMessage: "removing"
3697
+ }
3698
+ };
3699
+ var roleActionErrorHandler = (err, type, dispatch) => commonErrorHandler(err, `There was an error ${roleActions[type].errorMessage} the role.`, dispatch);
3700
+ var createRole = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/createRole`, (roleData, { dispatch }) => {
3701
+ const { permissionSetsWithScope, role } = transformRoleDataToRole(roleData);
3702
+ return general_api_default.post(`${useradmApiUrlv2}/roles`, {
3703
+ name: role.name,
3704
+ description: role.description,
3705
+ permission_sets_with_scope: permissionSetsWithScope
3706
+ }).then(() => Promise.all([dispatch(actions8.createdRole(role)), dispatch(getRoles()), dispatch(setSnackbar3(roleActions.create.successMessage))])).catch((err) => roleActionErrorHandler(err, "create", dispatch));
3707
+ });
3708
+ var editRole = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/editRole`, (roleData, { dispatch, getState }) => {
3709
+ const { permissionSetsWithScope, role } = transformRoleDataToRole(roleData, getRolesById(getState())[roleData.name]);
3710
+ return general_api_default.put(`${useradmApiUrlv2}/roles/${role.name}`, {
3711
+ description: role.description,
3712
+ name: role.name,
3713
+ permission_sets_with_scope: permissionSetsWithScope
3714
+ }).then(() => Promise.all([dispatch(actions8.createdRole(role)), dispatch(getRoles()), dispatch(setSnackbar3(roleActions.edit.successMessage))])).catch((err) => roleActionErrorHandler(err, "edit", dispatch));
3715
+ });
3716
+ var removeRole = (0, import_toolkit20.createAsyncThunk)(
3717
+ `${sliceName8}/removeRole`,
3718
+ (roleId, { dispatch }) => general_api_default.delete(`${useradmApiUrlv2}/roles/${roleId}`).then(() => Promise.all([dispatch(actions8.removedRole(roleId)), dispatch(getRoles()), dispatch(setSnackbar3(roleActions.remove.successMessage))])).catch((err) => roleActionErrorHandler(err, "remove", dispatch))
3626
3719
  );
3627
- var getDeviceAttributes = (0, import_toolkit19.createAsyncThunk)(
3628
- `${sliceName3}/getDeviceAttributes`,
3629
- (_, { dispatch, getState }) => general_api_default.get(getAttrsEndpoint(getState())).then(({ data }) => {
3630
- const { identity: identityAttributes, inventory: inventoryAttributes, system: systemAttributes, tags: tagAttributes } = attributeReducer(data || []);
3631
- return dispatch(actions3.setFilterAttributes({ identityAttributes, inventoryAttributes, systemAttributes, tagAttributes }));
3720
+ var getGlobalSettings2 = (0, import_toolkit20.createAsyncThunk)(
3721
+ `${sliceName8}/getGlobalSettings`,
3722
+ (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/settings`).then(({ data: settings, headers: { etag } }) => {
3723
+ window.sessionStorage.setItem(settingsKeys.initialized, true);
3724
+ return Promise.all([dispatch(actions8.setGlobalSettings(settings)), dispatch(setOfflineThreshold()), etag]);
3632
3725
  })
3633
3726
  );
3634
- var getReportingLimits = (0, import_toolkit19.createAsyncThunk)(
3635
- `${sliceName3}/getReportingLimits`,
3636
- (_, { dispatch }) => general_api_default.get(`${reportingApiUrl}/devices/attributes`).catch((err) => commonErrorHandler(err, `filterable attributes limit & usage could not be retrieved.`, dispatch, commonErrorFallback)).then(({ data }) => {
3637
- const { attributes, count, limit } = data;
3638
- const groupedAttributes = attributeReducer(attributes);
3639
- return Promise.resolve(dispatch(actions3.setFilterablesConfig({ count, limit, attributes: groupedAttributes })));
3727
+ var saveGlobalSettings = (0, import_toolkit20.createAsyncThunk)(
3728
+ `${sliceName8}/saveGlobalSettings`,
3729
+ ({ beOptimistic = false, notify = false, ...settings }, { dispatch, getState }) => {
3730
+ if (!window.sessionStorage.getItem(settingsKeys.initialized) && !beOptimistic) {
3731
+ return;
3732
+ }
3733
+ return dispatch(getGlobalSettings2()).unwrap().then((result) => {
3734
+ let updatedSettings = { ...getState().users.globalSettings, ...settings };
3735
+ if (getCurrentUser(getState()).verified) {
3736
+ updatedSettings["2fa"] = twoFAStates.enabled;
3737
+ } else {
3738
+ delete updatedSettings["2fa"];
3739
+ }
3740
+ let tasks = [dispatch(actions8.setGlobalSettings(updatedSettings))];
3741
+ const headers = result[result.length - 1] ? { "If-Match": result[result.length - 1] } : {};
3742
+ return general_api_default.post(`${useradmApiUrlv1}/settings`, updatedSettings, { headers }).then(() => {
3743
+ if (notify) {
3744
+ tasks.push(dispatch(setSnackbar3("Settings saved successfully")));
3745
+ }
3746
+ return Promise.all(tasks);
3747
+ }).catch((err) => {
3748
+ if (beOptimistic) {
3749
+ return Promise.all([tasks]);
3750
+ }
3751
+ console.log(err);
3752
+ return commonErrorHandler(err, `The settings couldn't be saved.`, dispatch);
3753
+ });
3754
+ });
3755
+ }
3756
+ );
3757
+ var getUserSettings2 = (0, import_toolkit20.createAsyncThunk)(
3758
+ `${sliceName8}/getUserSettings`,
3759
+ (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/settings/me`).then(({ data: settings, headers: { etag } }) => {
3760
+ window.sessionStorage.setItem(settingsKeys.initialized, true);
3761
+ return Promise.all([dispatch(actions8.setUserSettings(settings)), etag]);
3640
3762
  })
3641
3763
  );
3642
- var ensureVersionString = (software, fallback) => software.length && software !== "artifact_name" ? software.endsWith(".version") ? software : `${software}.version` : fallback;
3643
- var REPORT_CHART_SIZE_LIMIT = 6;
3644
- var getSingleReportData = (reportConfig, groups) => {
3645
- const { attribute, group, software = "" } = reportConfig;
3646
- const filters = [{ key: "status", scope: "identity", operator: DEVICE_FILTERING_OPTIONS.$eq.key, value: "accepted" }];
3647
- if (group) {
3648
- const staticGroupFilter = { key: "group", scope: "system", operator: DEVICE_FILTERING_OPTIONS.$eq.key, value: group };
3649
- const { cleanedFilters: groupFilters } = getGroupFilters(group, groups);
3650
- filters.push(...groupFilters.length ? groupFilters : [staticGroupFilter]);
3764
+ var saveUserSettings = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/saveUserSettings`, (settings = { onboarding: {} }, { dispatch, getState }) => {
3765
+ if (!getCurrentUser(getState()).id) {
3766
+ return Promise.resolve();
3651
3767
  }
3652
- const aggregationAttribute = ensureVersionString(software, attribute);
3653
- return general_api_default.post(`${reportingApiUrl}/devices/aggregate`, {
3654
- aggregations: [{ attribute: aggregationAttribute, name: "*", scope: "inventory", size: REPORT_CHART_SIZE_LIMIT }],
3655
- filters: mapFiltersToTerms(filters)
3656
- }).then(({ data }) => ({ data, reportConfig }));
3657
- };
3658
- var getReportsData = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getReportsData`, (_, { dispatch, getState }) => {
3659
- const state = getState();
3660
- const currentUserId = getCurrentUser(state).id;
3661
- const reports = getUserSettings(state).reports || getGlobalSettings(state)[`${currentUserId}-reports`] || (Object.keys(getDevicesById(state)).length ? defaultReports : []);
3662
- return Promise.all(reports.map((report) => getSingleReportData(report, getState().devices.groups))).then((results) => {
3663
- const devicesState = getState().devices;
3664
- const totalDeviceCount = devicesState.byStatus.accepted.total;
3665
- const newReports = results.map(({ data, reportConfig }) => {
3666
- let { items, other_count } = data[0];
3667
- const { attribute, group, software = "" } = reportConfig;
3668
- const dataCount = items.reduce((accu, item) => accu + item.count, 0);
3669
- const otherCount = !group && (software === rootfsImageVersion || attribute === "artifact_name") ? totalDeviceCount - dataCount : other_count;
3670
- return { items, otherCount, total: otherCount + dataCount };
3671
- });
3672
- return Promise.resolve(dispatch(actions3.setDeviceReports(newReports)));
3673
- });
3674
- });
3675
- var initializeDistributionData = (report, groups, devices, totalDeviceCount) => {
3676
- const { attribute, group = "", software = "" } = report;
3677
- const effectiveAttribute = software ? software : attribute;
3678
- const { deviceIds, total = 0 } = groups[group] || {};
3679
- const relevantDevices = groups[group] ? deviceIds.map((id) => devices[id]) : Object.values(devices);
3680
- const distributionByAttribute = relevantDevices.reduce((accu, item) => {
3681
- if (!item.attributes || item.status !== DEVICE_STATES.accepted) return accu;
3682
- if (!accu[item.attributes[effectiveAttribute]]) {
3683
- accu[item.attributes[effectiveAttribute]] = 0;
3684
- }
3685
- accu[item.attributes[effectiveAttribute]] = accu[item.attributes[effectiveAttribute]] + 1;
3686
- return accu;
3687
- }, {});
3688
- const distributionByAttributeSorted = Object.entries(distributionByAttribute).sort((pairA, pairB) => pairB[1] - pairA[1]);
3689
- const items = distributionByAttributeSorted.map(([key, count]) => ({ key, count }));
3690
- const dataCount = items.reduce((accu, item) => accu + item.count, 0);
3691
- const otherCount = (groups[group] ? total : totalDeviceCount) - dataCount;
3692
- return { items, otherCount, total: otherCount + dataCount };
3693
- };
3694
- var deriveReportsData = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/deriveReportsData`, (_, { dispatch, getState }) => {
3695
- const state = getState();
3696
- const {
3697
- groups: { byId: groupsById },
3698
- byId,
3699
- byStatus: {
3700
- accepted: { total }
3701
- }
3702
- } = state.devices;
3703
- const reports = getUserSettings(state).reports || state.users.globalSettings[`${state.users.currentUser}-reports`] || (Object.keys(byId).length ? defaultReports : []);
3704
- const newReports = reports.map((report) => initializeDistributionData(report, groupsById, byId, total));
3705
- return Promise.resolve(dispatch(actions3.setDeviceReports(newReports)));
3706
- });
3707
- var getReportsDataWithoutBackendSupport = (0, import_toolkit19.createAsyncThunk)(
3708
- `${sliceName3}/getReportsDataWithoutBackendSupport`,
3709
- (_, { dispatch, getState }) => Promise.all([dispatch(getAllDevicesByStatus(DEVICE_STATES.accepted)), dispatch(getGroups2()), dispatch(getDynamicGroups())]).then(() => {
3710
- const { dynamic: dynamicGroups, static: staticGroups } = getGroups(getState());
3768
+ return dispatch(getUserSettings2()).unwrap().then((result) => {
3769
+ const userSettings = getUserSettings(getState());
3770
+ const onboardingState = getOnboardingState(getState());
3771
+ const tooltipState = getTooltipsState(getState());
3772
+ const updatedSettings = {
3773
+ ...userSettings,
3774
+ ...settings,
3775
+ onboarding: {
3776
+ ...onboardingState,
3777
+ ...settings.onboarding
3778
+ },
3779
+ tooltips: tooltipState
3780
+ };
3781
+ const headers = result[result.length - 1] ? { "If-Match": result[result.length - 1] } : {};
3711
3782
  return Promise.all([
3712
- ...staticGroups.map(({ groupId }) => dispatch(getAllGroupDevices(groupId))),
3713
- ...dynamicGroups.map(({ groupId }) => dispatch(getAllDynamicGroupDevices(groupId)))
3714
- ]).then(() => dispatch(deriveReportsData()));
3715
- })
3716
- );
3717
- var getDeviceConnect = (0, import_toolkit19.createAsyncThunk)(
3718
- `${sliceName3}/getDeviceConnect`,
3719
- (id, { dispatch }) => general_api_default.get(`${deviceConnect}/devices/${id}`).then(
3720
- ({ data }) => Promise.all([dispatch(actions3.receivedDevice({ connect_status: data.status, connect_updated_ts: data.updated_ts, id })), Promise.resolve(data)])
3721
- )
3722
- );
3723
- var getSessionDetails = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getSessionDetails`, ({ sessionId, deviceId, userId, startDate, endDate }) => {
3724
- const { start: startUnix, end: endUnix } = (0, import_helpers9.dateRangeToUnix)(startDate, endDate);
3725
- const createdAfter = startDate ? `&created_after=${startUnix}` : "";
3726
- const createdBefore = endDate ? `&created_before=${endUnix}` : "";
3727
- const objectSearch = `&object_id=${deviceId}`;
3728
- return general_api_default.get(`${auditLogsApiUrl}/logs?per_page=500${createdAfter}${createdBefore}&actor_id=${userId}${objectSearch}`).then(
3729
- ({ data: auditLogEntries }) => {
3730
- const { start, end } = auditLogEntries.reduce(
3731
- (accu, item) => {
3732
- if (item.meta?.session_id?.includes(sessionId)) {
3733
- accu.start = new Date(item.action.startsWith("open") ? item.time : accu.start);
3734
- accu.end = new Date(item.action.startsWith("close") ? item.time : accu.end);
3735
- }
3736
- return accu;
3737
- },
3738
- { start: startDate || endDate, end: endDate || startDate }
3739
- );
3740
- return Promise.resolve({ start, end });
3741
- }
3742
- );
3783
+ Promise.resolve(dispatch(actions8.setUserSettings(updatedSettings))),
3784
+ general_api_default.post(`${useradmApiUrlv1}/settings/me`, updatedSettings, { headers })
3785
+ ]).catch(() => dispatch(actions8.setUserSettings(userSettings)));
3786
+ });
3743
3787
  });
3744
- var getDeviceFileDownloadLink = (0, import_toolkit19.createAsyncThunk)(
3745
- `${sliceName3}/getDeviceFileDownloadLink`,
3746
- ({ deviceId, path }) => Promise.resolve(`${window.location.origin}${deviceConnect}/devices/${deviceId}/download?path=${encodeURIComponent(path)}`)
3788
+ var get2FAQRCode = (0, import_toolkit20.createAsyncThunk)(
3789
+ `${sliceName8}/get2FAQRCode`,
3790
+ (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/2faqr`).then((res) => dispatch(actions8.receivedQrCode(res.data.qr)))
3747
3791
  );
3748
- var deviceFileUpload = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/deviceFileUpload`, ({ deviceId, path, file }, { dispatch }) => {
3749
- let formData = new FormData();
3750
- formData.append("path", path);
3751
- formData.append("file", file);
3752
- const uploadId = (0, import_uuid.v4)();
3753
- const cancelSource = new AbortController();
3754
- return Promise.all([
3755
- dispatch(setSnackbar3("Uploading file")),
3756
- dispatch(initUpload({ id: uploadId, upload: { inprogress: true, uploadProgress: 0, cancelSource } })),
3757
- general_api_default.uploadPut(
3758
- `${deviceConnect}/devices/${deviceId}/upload`,
3759
- formData,
3760
- (e) => dispatch(uploadProgress2({ id: uploadId, progress: progress(e) })),
3761
- cancelSource.signal
3762
- )
3763
- ]).then(() => Promise.resolve(dispatch(setSnackbar3("Upload successful", TIMEOUTS.fiveSeconds)))).catch((err) => {
3764
- if ((0, import_axios2.isCancel)(err)) {
3765
- return dispatch(setSnackbar3("The upload has been cancelled", TIMEOUTS.fiveSeconds));
3766
- }
3767
- return commonErrorHandler(err, `Error uploading file to device.`, dispatch);
3768
- }).finally(() => dispatch(cleanUpUpload(uploadId)));
3792
+ var setHideAnnouncement = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/setHideAnnouncement`, ({ shouldHide, userId }, { dispatch, getState }) => {
3793
+ const currentUserId = userId || getCurrentUser(getState()).id;
3794
+ const hash = getState().app.hostedAnnouncement ? (0, import_md5.default)(getState().app.hostedAnnouncement) : "";
3795
+ const announceCookie = cookies3.get(`${currentUserId}${hash}`);
3796
+ if (shouldHide || hash.length && typeof announceCookie !== "undefined") {
3797
+ cookies3.set(`${currentUserId}${hash}`, true, { maxAge: 604800 });
3798
+ return Promise.resolve(dispatch(setAnnouncement()));
3799
+ }
3800
+ return Promise.resolve();
3769
3801
  });
3770
- var getDeviceAuth = (0, import_toolkit19.createAsyncThunk)(
3771
- `${sliceName3}/getDeviceAuth`,
3772
- (id, { dispatch }) => dispatch(getDevicesWithAuth([{ id }])).unwrap().then((results) => {
3773
- if (results[results.length - 1]) {
3774
- return Promise.resolve(results[results.length - 1][0]);
3775
- }
3776
- return Promise.resolve();
3802
+ var getTokens = (0, import_toolkit20.createAsyncThunk)(
3803
+ `${sliceName8}/getTokens`,
3804
+ (_, { dispatch, getState }) => general_api_default.get(`${useradmApiUrlv1}/settings/tokens`).then(({ data: tokens }) => {
3805
+ const user = getCurrentUser(getState());
3806
+ const updatedUser = {
3807
+ ...user,
3808
+ tokens
3809
+ };
3810
+ return Promise.resolve(dispatch(actions8.updatedUser(updatedUser)));
3777
3811
  })
3778
3812
  );
3779
- var getDevicesWithAuth = (0, import_toolkit19.createAsyncThunk)(
3780
- `${sliceName3}/getDevicesWithAuth`,
3781
- (devices, { dispatch, getState }) => devices.length ? general_api_default.get(`${deviceAuthV2}/devices?id=${devices.map((device) => device.id).join("&id=")}`).then(({ data: receivedDevices }) => {
3782
- const { devicesById } = reduceReceivedDevices(receivedDevices, [], getState());
3783
- return Promise.all([dispatch(actions3.receivedDevices(devicesById)), Promise.resolve(receivedDevices)]);
3784
- }).catch((err) => commonErrorHandler(err, `Error: ${err}`, dispatch)) : Promise.resolve([[], []])
3813
+ var ONE_YEAR = 31536e3;
3814
+ var generateToken = (0, import_toolkit20.createAsyncThunk)(
3815
+ `${sliceName8}/generateToken`,
3816
+ ({ expiresIn = ONE_YEAR, name }, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/settings/tokens`, { name, expires_in: expiresIn }).then(({ data: token }) => Promise.all([dispatch(getTokens()), token])).catch((err) => commonErrorHandler(err, "There was an error creating the token:", dispatch))
3785
3817
  );
3786
- var updateDeviceAuth = (0, import_toolkit19.createAsyncThunk)(
3787
- `${sliceName3}/updateDeviceAuth`,
3788
- ({ deviceId, authId, status }, { dispatch, getState }) => general_api_default.put(`${deviceAuthV2}/devices/${deviceId}/auth/${authId}/status`, { status }).then(() => Promise.all([dispatch(getDeviceAuth(deviceId)), dispatch(setSnackbar3("Device authorization status was updated successfully"))])).catch((err) => commonErrorHandler(err, "There was a problem updating the device authorization status:", dispatch)).then(() => Promise.resolve(dispatch(actions3.maybeUpdateDevicesByStatus({ deviceId, authId })))).finally(() => dispatch(setDeviceListState({ refreshTrigger: !getDeviceListState(getState()).refreshTrigger })))
3818
+ var revokeToken = (0, import_toolkit20.createAsyncThunk)(
3819
+ `${sliceName8}/revokeToken`,
3820
+ (token, { dispatch }) => general_api_default.delete(`${useradmApiUrlv1}/settings/tokens/${token.id}`).then(() => Promise.resolve(dispatch(getTokens())))
3789
3821
  );
3790
- var updateDevicesAuth = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/updateDevicesAuth`, ({ deviceIds, status }, { dispatch, getState }) => {
3791
- let devices = getDevicesById(getState());
3792
- const deviceIdsWithoutAuth = deviceIds.reduce((accu, id) => devices[id].auth_sets ? accu : [...accu, { id }], []);
3793
- return dispatch(getDevicesWithAuth(deviceIdsWithoutAuth)).then(() => {
3794
- devices = getDevicesById(getState());
3795
- const deviceAuthUpdates = deviceIds.map((id) => {
3796
- const device = devices[id];
3797
- if (device.auth_sets.length !== 1) {
3798
- return Promise.reject();
3822
+ var setTooltipReadState = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/setTooltipReadState`, ({ persist, ...remainder }, { dispatch }) => {
3823
+ let tasks = [dispatch(actions8.setTooltipState(remainder))];
3824
+ if (persist) {
3825
+ tasks.push(dispatch(saveUserSettings()));
3826
+ }
3827
+ return Promise.all(tasks);
3828
+ });
3829
+ var setAllTooltipsReadState = (0, import_toolkit20.createAsyncThunk)(`${sliceName8}/toggleHelptips`, (readState = READ_STATES.read, { dispatch }) => {
3830
+ const updatedTips = Object.keys(import_helptips.HELPTOOLTIPS).reduce((accu, id) => ({ ...accu, [id]: { readState } }), {});
3831
+ return Promise.resolve(dispatch(actions8.setTooltipsState(updatedTips))).then(() => dispatch(saveUserSettings()));
3832
+ });
3833
+ var submitFeedback = (0, import_toolkit20.createAsyncThunk)(
3834
+ `${sliceName8}/submitFeedback`,
3835
+ ({ satisfaction, feedback, ...meta }, { dispatch }) => general_api_default.post(`${tenantadmApiUrlv2}/contact/support`, {
3836
+ subject: "feedback submission",
3837
+ body: JSON.stringify({ feedback, satisfaction, meta })
3838
+ }).then(() => {
3839
+ const today = /* @__PURE__ */ new Date();
3840
+ dispatch(saveUserSettings({ feedbackCollectedAt: today.toISOString().split("T")[0] }));
3841
+ setTimeout(() => dispatch(actions8.setShowFeedbackDialog(false)), TIMEOUTS.threeSeconds);
3842
+ })
3843
+ );
3844
+
3845
+ // src/devicesSlice/thunks.tsx
3846
+ var import_helpers10 = require("@northern.tech/utils/helpers");
3847
+ var import_toolkit21 = require("@reduxjs/toolkit");
3848
+ var import_axios3 = require("axios");
3849
+ var import_pluralize = __toESM(require("pluralize"), 1);
3850
+ var import_uuid = require("uuid");
3851
+ var import_jsx_runtime2 = require("react/jsx-runtime");
3852
+ var { cleanUpUpload, initUpload, setSnackbar: setSnackbar4, uploadProgress: uploadProgress2 } = actions_default;
3853
+ var { page: defaultPage3, perPage: defaultPerPage3 } = DEVICE_LIST_DEFAULTS;
3854
+ var defaultAttributes = [
3855
+ { scope: "identity", attribute: "status" },
3856
+ { scope: "inventory", attribute: "artifact_name" },
3857
+ { scope: "inventory", attribute: "device_type" },
3858
+ { scope: "inventory", attribute: "mender_is_gateway" },
3859
+ { scope: "inventory", attribute: "mender_gateway_system_id" },
3860
+ { scope: "inventory", attribute: rootfsImageVersion },
3861
+ { scope: "monitor", attribute: "alerts" },
3862
+ { scope: "system", attribute: "created_ts" },
3863
+ { scope: "system", attribute: "updated_ts" },
3864
+ { scope: "system", attribute: "check_in_time" },
3865
+ { scope: "system", attribute: "group" },
3866
+ { scope: "tags", attribute: "name" }
3867
+ ];
3868
+ var getGroups2 = (0, import_toolkit21.createAsyncThunk)(
3869
+ `${sliceName3}/getGroups`,
3870
+ (_, { dispatch, getState }) => general_api_default.get(`${inventoryApiUrl}/groups`).then((res) => {
3871
+ const state = getGroupsById(getState());
3872
+ const dynamicGroups = Object.entries(state).reduce((accu, [id, group]) => {
3873
+ if (group.id || group.filters?.length && id !== UNGROUPED_GROUP.id) {
3874
+ accu[id] = group;
3799
3875
  }
3800
- return dispatch(updateDeviceAuth({ authId: device.auth_sets[0].id, deviceId: device.id, status })).unwrap().catch((err) => commonErrorHandler(err, "The action was stopped as there was a problem updating a device authorization status: ", dispatch, "", false));
3801
- });
3802
- return Promise.allSettled(deviceAuthUpdates).then((results) => {
3803
- const { skipped, count } = results.reduce(
3804
- (accu, item) => {
3805
- if (item.status === "rejected") {
3806
- accu.skipped = accu.skipped + 1;
3807
- } else {
3808
- accu.count = accu.count + 1;
3809
- }
3810
- return accu;
3811
- },
3812
- { skipped: 0, count: 0 }
3876
+ return accu;
3877
+ }, {});
3878
+ const groups = res.data.reduce((accu, group) => {
3879
+ accu[group] = { deviceIds: [], filters: [], total: 0, ...state[group] };
3880
+ return accu;
3881
+ }, dynamicGroups);
3882
+ const filters = [{ key: "group", value: res.data, operator: DEVICE_FILTERING_OPTIONS.$nin.key, scope: "system" }];
3883
+ return Promise.all([
3884
+ dispatch(actions3.receivedGroups(groups)),
3885
+ dispatch(getDevicesByStatus2({ filterSelection: filters, group: 0, page: 1, perPage: 1, status: void 0 }))
3886
+ ]).then((promises) => {
3887
+ const devicesRetrieval = promises[promises.length - 1] || [];
3888
+ const { payload } = devicesRetrieval || {};
3889
+ const result = payload[payload.length - 1] || {};
3890
+ if (!result.total) {
3891
+ return Promise.resolve();
3892
+ }
3893
+ return Promise.resolve(
3894
+ dispatch(
3895
+ actions3.addGroup({
3896
+ groupName: UNGROUPED_GROUP.id,
3897
+ group: { filters: [{ key: "group", value: res.data, operator: DEVICE_FILTERING_OPTIONS.$nin.key, scope: "system" }] }
3898
+ })
3899
+ )
3813
3900
  );
3814
- const message = (0, import_helpers9.getSnackbarMessage)(skipped, count);
3815
- return dispatch(setSnackbar3(message));
3816
3901
  });
3817
- });
3818
- });
3819
- var deleteAuthset = (0, import_toolkit19.createAsyncThunk)(
3820
- `${sliceName3}/deleteAuthset`,
3821
- ({ deviceId, authId }, { dispatch, getState }) => general_api_default.delete(`${deviceAuthV2}/devices/${deviceId}/auth/${authId}`).then(() => Promise.all([dispatch(setSnackbar3("Device authorization status was updated successfully"))])).catch((err) => commonErrorHandler(err, "There was a problem updating the device authorization status:", dispatch)).then(() => Promise.resolve(dispatch(actions3.maybeUpdateDevicesByStatus({ deviceId, authId })))).finally(() => dispatch(setDeviceListState({ refreshTrigger: !getState().devices.deviceList.refreshTrigger })))
3822
- );
3823
- var preauthDevice = (0, import_toolkit19.createAsyncThunk)(
3824
- `${sliceName3}/preauthDevice`,
3825
- (authset, { dispatch }) => general_api_default.post(`${deviceAuthV2}/devices`, authset).catch((err) => {
3826
- if (err.response.status === 409) {
3827
- return Promise.reject("A device with a matching identity data set already exists");
3828
- }
3829
- return commonErrorHandler(err, "The device could not be added:", dispatch);
3830
- }).then(() => Promise.resolve(dispatch(setSnackbar3("Device was successfully added to the preauthorization list", TIMEOUTS.fiveSeconds))))
3831
- );
3832
- var decommissionDevice = (0, import_toolkit19.createAsyncThunk)(
3833
- `${sliceName3}/decommissionDevice`,
3834
- ({ deviceId, authId }, { dispatch, getState }) => general_api_default.delete(`${deviceAuthV2}/devices/${deviceId}`).then(() => Promise.resolve(dispatch(setSnackbar3("Device was decommissioned successfully")))).catch((err) => commonErrorHandler(err, "There was a problem decommissioning the device:", dispatch)).then(() => Promise.resolve(dispatch(actions3.maybeUpdateDevicesByStatus({ deviceId, authId })))).finally(() => dispatch(setDeviceListState({ refreshTrigger: !getState().devices.deviceList.refreshTrigger })))
3835
- );
3836
- var getDeviceConfig = (0, import_toolkit19.createAsyncThunk)(
3837
- `${sliceName3}/getDeviceConfig`,
3838
- (deviceId, { dispatch }) => general_api_default.get(`${deviceConfig}/${deviceId}`).then(({ data }) => Promise.all([dispatch(actions3.receivedDevice({ id: deviceId, config: data })), Promise.resolve(data)])).catch((err) => {
3839
- if (err.response?.data?.error.status_code !== 404) {
3840
- return commonErrorHandler(err, `There was an error retrieving the configuration for device ${deviceId}.`, dispatch, commonErrorFallback);
3841
- }
3842
3902
  })
3843
3903
  );
3844
- var setDeviceConfig = (0, import_toolkit19.createAsyncThunk)(
3845
- `${sliceName3}/setDeviceConfig`,
3846
- ({ deviceId, config }, { dispatch }) => general_api_default.put(`${deviceConfig}/${deviceId}`, config).catch((err) => commonErrorHandler(err, `There was an error setting the configuration for device ${deviceId}.`, dispatch, commonErrorFallback)).then(() => Promise.resolve(dispatch(getDeviceConfig(deviceId))))
3904
+ var addDevicesToGroup = (0, import_toolkit21.createAsyncThunk)(
3905
+ `${sliceName3}/addDevicesToGroup`,
3906
+ ({ group, deviceIds, isCreation }, { dispatch }) => general_api_default.patch(`${inventoryApiUrl}/groups/${group}/devices`, deviceIds).then(() => dispatch(actions3.addToGroup({ group, deviceIds }))).finally(() => isCreation ? Promise.resolve(dispatch(getGroups2())) : {})
3847
3907
  );
3848
- var applyDeviceConfig = (0, import_toolkit19.createAsyncThunk)(
3849
- `${sliceName3}/applyDeviceConfig`,
3850
- ({ deviceId, configDeploymentConfiguration, isDefault, config }, { dispatch, getState }) => general_api_default.post(`${deviceConfig}/${deviceId}/deploy`, configDeploymentConfiguration).catch((err) => commonErrorHandler(err, `There was an error deploying the configuration to device ${deviceId}.`, dispatch, commonErrorFallback)).then(({ data }) => {
3851
- const device = getDeviceById(getState(), deviceId);
3852
- const { canManageUsers } = getUserCapabilities(getState());
3853
- let tasks = [
3854
- dispatch(actions3.receivedDevice({ ...device, config: { ...device.config, deployment_id: data.deployment_id } })),
3855
- new Promise((resolve) => setTimeout(() => resolve(dispatch(getSingleDeployment(data.deployment_id))), TIMEOUTS.oneSecond))
3856
- ];
3857
- if (isDefault && canManageUsers) {
3858
- const { previous } = getGlobalSettings(getState()).defaultDeviceConfig ?? {};
3859
- tasks.push(dispatch(saveGlobalSettings({ defaultDeviceConfig: { current: config, previous } })));
3860
- }
3861
- return Promise.all(tasks);
3862
- })
3908
+ var removeDevicesFromGroup = (0, import_toolkit21.createAsyncThunk)(
3909
+ `${sliceName3}/removeDevicesFromGroup`,
3910
+ ({ group, deviceIds }, { dispatch }) => general_api_default.delete(`${inventoryApiUrl}/groups/${group}/devices`, deviceIds).then(
3911
+ () => Promise.all([
3912
+ dispatch(actions3.removeFromGroup({ group, deviceIds })),
3913
+ dispatch(setSnackbar4(`The ${(0, import_pluralize.default)("devices", deviceIds.length)} ${(0, import_pluralize.default)("were", deviceIds.length)} removed from the group`, TIMEOUTS.fiveSeconds))
3914
+ ])
3915
+ )
3863
3916
  );
3864
- var setDeviceTags = (0, import_toolkit19.createAsyncThunk)(
3865
- `${sliceName3}/setDeviceTags`,
3866
- ({ deviceId, tags }, { dispatch }) => (
3867
- // to prevent tag set failures, retrieve the device & use the freshest etag we can get
3868
- Promise.resolve(dispatch(getDeviceById2(deviceId))).then((device) => {
3869
- const headers = device.etag ? { "If-Match": device.etag } : {};
3870
- return general_api_default.put(
3871
- `${inventoryApiUrl}/devices/${deviceId}/tags`,
3872
- Object.entries(tags).map(([name, value]) => ({ name, value })),
3873
- { headers }
3874
- ).catch((err) => commonErrorHandler(err, `There was an error setting tags for device ${deviceId}.`, dispatch, "Please check your connection.")).then(() => Promise.all([dispatch(actions3.receivedDevice({ ...device, id: deviceId, tags })), dispatch(setSnackbar3("Device name changed"))]));
3875
- })
3876
- )
3877
- );
3878
- var getDeviceTwin = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getDeviceTwin`, ({ deviceId, integration }, { dispatch, getState }) => {
3879
- let providerResult = {};
3880
- return general_api_default.get(`${iotManagerBaseURL}/devices/${deviceId}/state`).then(({ data }) => {
3881
- providerResult = { ...data, twinError: "" };
3882
- }).catch((err) => {
3883
- providerResult = {
3884
- twinError: `There was an error getting the ${EXTERNAL_PROVIDER[integration.provider].twinTitle.toLowerCase()} for device ${deviceId}. ${err}`
3885
- };
3886
- }).finally(() => {
3887
- const device = getDeviceById(getState(), deviceId);
3888
- Promise.resolve(dispatch(actions3.receivedDevice({ ...device, twinsByIntegration: { ...device.twinsByIntegration, ...providerResult } })));
3889
- });
3890
- });
3891
- var setDeviceTwin = (0, import_toolkit19.createAsyncThunk)(
3892
- `${sliceName3}/setDeviceTwin`,
3893
- ({ deviceId, integration, settings }, { dispatch, getState }) => general_api_default.put(`${iotManagerBaseURL}/devices/${deviceId}/state/${integration.id}`, { desired: settings }).catch(
3894
- (err) => commonErrorHandler(
3895
- err,
3896
- `There was an error updating the ${EXTERNAL_PROVIDER[integration.provider].twinTitle.toLowerCase()} for device ${deviceId}.`,
3897
- dispatch
3898
- )
3899
- ).then(() => {
3900
- const device = getDeviceById(getState(), deviceId);
3901
- const { twinsByIntegration = {} } = device;
3902
- const { [integration.id]: currentState = {} } = twinsByIntegration;
3903
- return Promise.resolve(
3904
- dispatch(actions3.receivedDevice({ ...device, twinsByIntegration: { ...twinsByIntegration, [integration.id]: { ...currentState, desired: settings } } }))
3905
- );
3906
- })
3907
- );
3908
- var prepareSearchArguments = ({ filters, group, state, status }) => {
3909
- const { filterTerms } = convertDeviceListStateToFilters({ filters, group, offlineThreshold: state.app.offlineThreshold, selectedIssues: [], status });
3910
- const { columnSelection = [] } = getUserSettings(state);
3911
- const selectedAttributes = columnSelection.map((column) => ({ attribute: column.key, scope: column.scope }));
3912
- const attributes = [...defaultAttributes, getIdAttribute(state), ...selectedAttributes];
3913
- return { attributes, filterTerms };
3914
- };
3915
- var getSystemDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getSystemDevices`, (options, { dispatch, getState }) => {
3916
- const { id, page = defaultPage2, perPage = defaultPerPage2, sortOptions = [] } = options;
3917
- const state = getState();
3918
- const { hasFullFiltering } = getTenantCapabilities(state);
3919
- if (!hasFullFiltering) {
3920
- return Promise.resolve();
3917
+ var getGroupNotification = (newGroup, selectedGroup) => {
3918
+ const successMessage = "The group was updated successfully";
3919
+ if (newGroup === selectedGroup) {
3920
+ return [successMessage, TIMEOUTS.fiveSeconds];
3921
3921
  }
3922
- const { attributes: deviceAttributes = {} } = getDeviceById(state, id);
3923
- const { mender_gateway_system_id = "" } = deviceAttributes;
3924
- const filters = [
3925
- { ...emptyFilter, key: "mender_is_gateway", operator: DEVICE_FILTERING_OPTIONS.$ne.key, value: "true", scope: "inventory" },
3926
- { ...emptyFilter, key: "mender_gateway_system_id", value: mender_gateway_system_id, scope: "inventory" }
3927
- ];
3928
- const { attributes, filterTerms } = prepareSearchArguments({ filters, state });
3929
- return general_api_default.post(getSearchEndpoint(getState()), {
3930
- page,
3931
- per_page: perPage,
3932
- filters: filterTerms,
3933
- sort: sortOptions,
3934
- attributes
3935
- }).catch((err) => commonErrorHandler(err, `There was an error getting system devices device ${id}.`, dispatch, "Please check your connection.")).then(({ data, headers }) => {
3936
- const state2 = getState();
3937
- const { devicesById, ids } = reduceReceivedDevices(data, [], state2);
3938
- const device = {
3939
- ...getDeviceById(state2, id),
3940
- systemDeviceIds: ids,
3941
- systemDeviceTotal: Number(headers[headerNames.total])
3942
- };
3943
- return Promise.resolve(dispatch(actions3.receivedDevices({ ...devicesById, [id]: device })));
3944
- });
3945
- });
3946
- var getGatewayDevices = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getGatewayDevices`, (deviceId, { dispatch, getState }) => {
3947
- const state = getState();
3948
- const { attributes = {} } = getDeviceById(state, deviceId);
3949
- const { mender_gateway_system_id = "" } = attributes;
3950
- const filters = [
3951
- { ...emptyFilter, key: "id", operator: DEVICE_FILTERING_OPTIONS.$ne.key, value: deviceId, scope: "identity" },
3952
- { ...emptyFilter, key: "mender_is_gateway", value: "true", scope: "inventory" },
3953
- { ...emptyFilter, key: "mender_gateway_system_id", value: mender_gateway_system_id, scope: "inventory" }
3922
+ return [
3923
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
3924
+ successMessage,
3925
+ " - ",
3926
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom.Link, { to: `/devices?inventory=group:eq:${newGroup}`, children: "click here" }),
3927
+ " to see it."
3928
+ ] }),
3929
+ 5e3,
3930
+ void 0,
3931
+ void 0,
3932
+ () => {
3933
+ }
3954
3934
  ];
3955
- const { attributes: attributeSelection, filterTerms } = prepareSearchArguments({ filters, state });
3956
- return general_api_default.post(getSearchEndpoint(getState()), {
3957
- page: 1,
3958
- per_page: MAX_PAGE_SIZE,
3959
- filters: filterTerms,
3960
- attributes: attributeSelection
3961
- }).then(({ data }) => {
3962
- const { ids } = reduceReceivedDevices(data, [], getState());
3963
- let tasks = ids.map((deviceId2) => dispatch(getDeviceInfo(deviceId2)));
3964
- tasks.push(dispatch(actions3.receivedDevice({ id: deviceId, gatewayIds: ids })));
3965
- return Promise.all(tasks);
3966
- });
3967
- });
3968
- var getDevicesInBounds = (0, import_toolkit19.createAsyncThunk)(`${sliceName3}/getDevicesInBounds`, ({ bounds, group }, { dispatch, getState }) => {
3969
- const state = getState();
3970
- const { filterTerms } = convertDeviceListStateToFilters({
3971
- group: group === ALL_DEVICES ? void 0 : group,
3972
- groups: state.devices.groups,
3973
- status: DEVICE_STATES.accepted
3974
- });
3975
- return general_api_default.post(getSearchEndpoint(getState()), {
3976
- page: 1,
3977
- per_page: MAX_PAGE_SIZE,
3978
- filters: filterTerms,
3979
- attributes: geoAttributes,
3980
- geo_bounding_box_filter: {
3981
- geo_bounding_box: {
3982
- location: {
3983
- top_left: { lat: bounds._northEast.lat, lon: bounds._southWest.lng },
3984
- bottom_right: { lat: bounds._southWest.lat, lon: bounds._northEast.lng }
3985
- }
3935
+ };
3936
+ var addStaticGroup = (0, import_toolkit21.createAsyncThunk)(
3937
+ `${sliceName3}/addStaticGroup`,
3938
+ ({ group, devices }, { dispatch, getState }) => Promise.resolve(dispatch(addDevicesToGroup({ group, deviceIds: devices.map(({ id }) => id), isCreation: true }))).then(
3939
+ () => Promise.resolve(
3940
+ dispatch(
3941
+ actions3.addGroup({
3942
+ group: { deviceIds: [], total: 0, filters: [], ...getState().devices.groups.byId[group] },
3943
+ groupName: group
3944
+ })
3945
+ )
3946
+ ).then(
3947
+ () => Promise.all([
3948
+ dispatch(setDeviceListState({ setOnly: true })),
3949
+ dispatch(getGroups2()),
3950
+ dispatch(setSnackbar4(...getGroupNotification(group, getState().devices.groups.selectedGroup)))
3951
+ ])
3952
+ )
3953
+ ).catch((err) => commonErrorHandler(err, `Group could not be updated:`, dispatch))
3954
+ );
3955
+ var removeStaticGroup = (0, import_toolkit21.createAsyncThunk)(
3956
+ `${sliceName3}/removeStaticGroup`,
3957
+ (groupName, { dispatch }) => general_api_default.delete(`${inventoryApiUrl}/groups/${groupName}`).then(
3958
+ () => Promise.all([
3959
+ dispatch(actions3.removeGroup(groupName)),
3960
+ dispatch(getGroups2()),
3961
+ dispatch(setSnackbar4("Group was removed successfully", TIMEOUTS.fiveSeconds))
3962
+ ])
3963
+ )
3964
+ );
3965
+ var getDynamicGroups = (0, import_toolkit21.createAsyncThunk)(
3966
+ `${sliceName3}/getDynamicGroups`,
3967
+ (_, { dispatch, getState }) => general_api_default.get(`${inventoryApiUrlV2}/filters?per_page=${MAX_PAGE_SIZE}`).then(({ data: filters }) => {
3968
+ const state = getGroupsById(getState());
3969
+ const staticGroups = Object.entries(state).reduce((accu, [id, group]) => {
3970
+ if (!(group.id || group.filters?.length)) {
3971
+ accu[id] = group;
3986
3972
  }
3987
- }
3988
- }).then(({ data }) => {
3989
- const { devicesById } = reduceReceivedDevices(data, [], getState());
3990
- return Promise.resolve(dispatch(actions3.receivedDevices(devicesById)));
3991
- });
3973
+ return accu;
3974
+ }, {});
3975
+ const groups = (filters || []).reduce((accu, filter) => {
3976
+ accu[filter.name] = {
3977
+ deviceIds: [],
3978
+ total: 0,
3979
+ ...state[filter.name],
3980
+ id: filter.id,
3981
+ filters: mapTermsToFilters(filter.terms)
3982
+ };
3983
+ return accu;
3984
+ }, staticGroups);
3985
+ return Promise.resolve(dispatch(actions3.receivedGroups(groups)));
3986
+ }).catch(() => console.log("Dynamic group retrieval failed - likely accessing a non-enterprise backend"))
3987
+ );
3988
+ var addDynamicGroup = (0, import_toolkit21.createAsyncThunk)(
3989
+ `${sliceName3}/addDynamicGroup`,
3990
+ ({ groupName, filterPredicates }, { dispatch, getState }) => general_api_default.post(`${inventoryApiUrlV2}/filters`, { name: groupName, terms: mapFiltersToTerms(filterPredicates) }).then(
3991
+ (res) => Promise.resolve(
3992
+ dispatch(
3993
+ actions3.addGroup({
3994
+ groupName,
3995
+ group: {
3996
+ id: res.headers[headerNames.location].substring(res.headers[headerNames.location].lastIndexOf("/") + 1),
3997
+ filters: filterPredicates
3998
+ }
3999
+ })
4000
+ )
4001
+ ).then(() => {
4002
+ const { cleanedFilters } = getGroupFilters(groupName, getState().devices.groups);
4003
+ return Promise.all([
4004
+ dispatch(actions3.setDeviceFilters(cleanedFilters)),
4005
+ dispatch(setSnackbar4(...getGroupNotification(groupName, getState().devices.groups.selectedGroup))),
4006
+ dispatch(getDynamicGroups())
4007
+ ]);
4008
+ })
4009
+ ).catch((err) => commonErrorHandler(err, `Group could not be updated:`, dispatch))
4010
+ );
4011
+ var updateDynamicGroup = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/updateDynamicGroup`, ({ groupName, filterPredicates }, { dispatch, getState }) => {
4012
+ const filterId = getState().devices.groups.byId[groupName].id;
4013
+ return general_api_default.delete(`${inventoryApiUrlV2}/filters/${filterId}`).then(() => Promise.resolve(dispatch(addDynamicGroup({ groupName, filterPredicates }))));
3992
4014
  });
3993
-
3994
- // src/monitorSlice/thunks.ts
3995
- var import_toolkit20 = require("@reduxjs/toolkit");
3996
- var { page: defaultPage3, perPage: defaultPerPage3 } = DEVICE_LIST_DEFAULTS;
3997
- var cutoffLength = 75;
3998
- var ellipsis = "...";
3999
- var longTextTrimmer = (text) => text.length >= cutoffLength + ellipsis.length ? `${text.substring(0, cutoffLength + ellipsis.length)}${ellipsis}` : text;
4000
- var sanitizeDeviceAlerts = (alerts) => alerts.map((alert) => ({ ...alert, fullName: alert.name, name: longTextTrimmer(alert.name) }));
4001
- var getDeviceAlerts = (0, import_toolkit20.createAsyncThunk)(`${sliceName4}/getDeviceAlerts`, ({ id, config = {} }, { dispatch }) => {
4002
- const { page = defaultPage3, perPage = defaultPerPage3, issuedBefore, issuedAfter, sortAscending = false } = config;
4003
- const issued_after = issuedAfter ? `&issued_after=${issuedAfter}` : "";
4004
- const issued_before = issuedBefore ? `&issued_before=${issuedBefore}` : "";
4005
- return general_api_default.get(`${monitorApiUrlv1}/devices/${id}/alerts?page=${page}&per_page=${perPage}${issued_after}${issued_before}&sort_ascending=${sortAscending}`).catch((err) => commonErrorHandler(err, `Retrieving device alerts for device ${id} failed:`, dispatch)).then(
4006
- (res) => Promise.all([
4007
- dispatch(actions4.receiveDeviceAlerts({ deviceId: id, alerts: sanitizeDeviceAlerts(res.data) })),
4008
- dispatch(actions4.setAlertListState({ total: Number(res.headers[headerNames.total]) }))
4009
- ])
4015
+ var removeDynamicGroup = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/removeDynamicGroup`, (groupName, { dispatch, getState }) => {
4016
+ const filterId = getState().devices.groups.byId[groupName].id;
4017
+ return general_api_default.delete(`${inventoryApiUrlV2}/filters/${filterId}`).then(
4018
+ () => Promise.all([dispatch(actions3.removeGroup(groupName)), dispatch(setSnackbar4("Group was removed successfully", TIMEOUTS.fiveSeconds))])
4010
4019
  );
4011
4020
  });
4012
- var getLatestDeviceAlerts = (0, import_toolkit20.createAsyncThunk)(`${sliceName4}/getLatestDeviceAlerts`, ({ id, config = {} }, { dispatch }) => {
4013
- const { page = defaultPage3, perPage = 10 } = config;
4014
- return general_api_default.get(`${monitorApiUrlv1}/devices/${id}/alerts/latest?page=${page}&per_page=${perPage}`).catch((err) => commonErrorHandler(err, `Retrieving device alerts for device ${id} failed:`, dispatch)).then((res) => Promise.resolve(dispatch(actions4.receiveLatestDeviceAlerts({ deviceId: id, alerts: sanitizeDeviceAlerts(res.data) }))));
4015
- });
4016
- var getIssueCountsByType2 = (0, import_toolkit20.createAsyncThunk)(`${sliceName4}/getIssueCountsByType`, ({ type, options = {} }, { dispatch, getState }) => {
4017
- const state = getState();
4018
- const { filters = getDeviceFilters(state), group, status, ...remainder } = options;
4019
- const { applicableFilters: nonMonitorFilters, filterTerms } = convertDeviceListStateToFilters({
4020
- ...remainder,
4021
- filters,
4022
- group,
4023
- offlineThreshold: state.app.offlineThreshold,
4024
- selectedIssues: [type],
4025
- status
4026
- });
4027
- return general_api_default.post(getSearchEndpoint(getState()), {
4028
- page: 1,
4029
- per_page: 1,
4030
- filters: filterTerms,
4031
- attributes: [{ scope: "identity", attribute: "status" }]
4032
- }).catch((err) => commonErrorHandler(err, `Retrieving issue counts failed:`, dispatch, commonErrorFallback)).then((res) => {
4033
- const total = nonMonitorFilters.length ? state.monitor.issueCounts.byType[type].total : Number(res.headers[headerNames.total]);
4034
- const filtered = nonMonitorFilters.length ? Number(res.headers[headerNames.total]) : total;
4035
- if (total === state.monitor.issueCounts.byType[type].total && filtered === state.monitor.issueCounts.byType[type].filtered) {
4036
- return Promise.resolve();
4037
- }
4038
- return Promise.resolve(dispatch(actions4.receiveDeviceIssueCounts({ counts: { filtered, total }, issueType: type })));
4039
- });
4040
- });
4041
- var getDeviceMonitorConfig = (0, import_toolkit20.createAsyncThunk)(
4042
- `${sliceName4}/getDeviceMonitorConfig`,
4043
- (id, { dispatch }) => general_api_default.get(`${monitorApiUrlv1}/devices/${id}/config`).catch((err) => commonErrorHandler(err, `Retrieving device monitor config for device ${id} failed:`, dispatch)).then(({ data }) => Promise.all([dispatch(actions_default.receivedDevice({ id, monitors: data }), Promise.resolve(data))]))
4044
- );
4045
- var changeNotificationSetting = (0, import_toolkit20.createAsyncThunk)(
4046
- `${sliceName4}/changeNotificationSetting`,
4047
- ({ enabled, channel = alertChannels.email }, { dispatch }) => {
4048
- return general_api_default.put(`${monitorApiUrlv1}/settings/global/channel/alerts/${channel}/status`, { enabled }).catch((err) => commonErrorHandler(err, `${enabled ? "En" : "Dis"}abling ${channel} alerts failed:`, dispatch)).then(
4049
- () => Promise.all([
4050
- dispatch(actions4.changeAlertChannel({ channel, enabled })),
4051
- dispatch(actions_default.setSnackbar(`Successfully ${enabled ? "en" : "dis"}abled ${channel} alerts`, TIMEOUTS.fiveSeconds))
4052
- ])
4053
- );
4054
- }
4055
- );
4056
-
4057
- // src/api/users-api.ts
4058
- var import_axios3 = __toESM(require("axios"), 1);
4059
- var Api2 = {
4060
- postLogin: (url, { email: username, password, ...body }) => import_axios3.default.post(url, body, { ...commonRequestConfig, auth: { username, password } }).then((res) => ({ text: res.data, code: res.status, contentType: res.headers?.["content-type"] })),
4061
- putVerifyTFA: (url, userData) => {
4062
- let body = {};
4063
- if (userData.hasOwnProperty("token2fa")) {
4064
- body = { token2fa: userData.token2fa };
4065
- }
4066
- return import_axios3.default.put(url, body, { ...commonRequestConfig, headers: { ...commonRequestConfig.headers, Authorization: `Bearer ${getToken()}` } });
4067
- }
4021
+ var getGroupFilters = (group, groupsState, filters = []) => {
4022
+ const groupName = group === UNGROUPED_GROUP.id || group === UNGROUPED_GROUP.name ? UNGROUPED_GROUP.id : group;
4023
+ const selectedGroup = groupsState.byId[groupName];
4024
+ const groupFilterLength = selectedGroup?.filters?.length || 0;
4025
+ const cleanedFilters = groupFilterLength ? [...filters, ...selectedGroup.filters].filter(filtersFilter) : filters;
4026
+ return { cleanedFilters, groupName, selectedGroup, groupFilterLength };
4068
4027
  };
4069
- var users_api_default = Api2;
4070
-
4071
- // src/usersSlice/thunks.ts
4072
- var import_helpers10 = require("@northern.tech/utils/helpers");
4073
- var import_retrytimer = require("@northern.tech/utils/retrytimer");
4074
- var import_toolkit21 = require("@reduxjs/toolkit");
4075
- var import_md5 = __toESM(require("md5"), 1);
4076
- var import_universal_cookie3 = __toESM(require("universal-cookie"), 1);
4077
- var cookies3 = new import_universal_cookie3.default();
4078
- var { setAnnouncement, setSnackbar: setSnackbar4 } = actions_default;
4079
- var handleLoginError = (err, { token2fa: has2FA, password }, rejectWithValue) => (dispatch) => {
4080
- const errorText = (0, import_helpers10.extractErrorMessage)(err);
4081
- const is2FABackend = errorText.includes("2fa");
4082
- if (is2FABackend && !has2FA) {
4083
- return rejectWithValue({ error: "2fa code missing" });
4028
+ var selectGroup = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/selectGroup`, ({ group, filters = [] }, { dispatch, getState }) => {
4029
+ const { cleanedFilters, groupName, selectedGroup, groupFilterLength } = getGroupFilters(group, getState().devices.groups, filters);
4030
+ if (getSelectedGroup(getState()) === groupName && (filters.length === 0 && !groupFilterLength || filters.length === cleanedFilters.length)) {
4031
+ return Promise.resolve();
4084
4032
  }
4085
- if (password === void 0) {
4086
- return Promise.reject();
4033
+ let tasks = [];
4034
+ if (groupFilterLength) {
4035
+ tasks.push(dispatch(actions3.setDeviceFilters(cleanedFilters)));
4036
+ } else {
4037
+ tasks.push(dispatch(actions3.setDeviceFilters(filters)));
4038
+ tasks.push(dispatch(getGroupDevices({ group: groupName, perPage: 1, shouldIncludeAllStates: true })));
4087
4039
  }
4088
- const twoFAError = is2FABackend ? " and verification code" : "";
4089
- const errorMessage = `There was a problem logging in. Please check your email${twoFAError ? "," : " and"} password${twoFAError}. If you still have problems, contact an administrator.`;
4090
- return Promise.reject(dispatch(setSnackbar4((0, import_helpers10.preformatWithRequestID)(err.response, errorMessage), null, "Copy to clipboard")));
4091
- };
4092
- var loginUser = (0, import_toolkit21.createAsyncThunk)(
4093
- `${sliceName8}/loginUser`,
4094
- ({ stayLoggedIn, ...userData }, { dispatch, rejectWithValue }) => users_api_default.postLogin(`${useradmApiUrlv1}/auth/login`, { ...userData, no_expiry: stayLoggedIn }).catch((err) => {
4095
- cleanUp();
4096
- return Promise.reject(dispatch(handleLoginError(err, userData, rejectWithValue)));
4097
- }).then(({ text: response, contentType }) => {
4098
- if (contentType.includes(APPLICATION_JSON_CONTENT_TYPE)) {
4099
- const { id, kind } = response;
4100
- const type = kind.split("/")[1];
4101
- const ssoLoginUrl = SSO_TYPES[type].getStartUrl(id);
4102
- window.location.replace(ssoLoginUrl);
4103
- return;
4040
+ const selectedGroupName = selectedGroup || !Object.keys(getGroupsById(getState())).length ? groupName : void 0;
4041
+ tasks.push(dispatch(actions3.selectGroup(selectedGroupName)));
4042
+ return Promise.all(tasks);
4043
+ });
4044
+ var getEarliestTs = (dateA = "", dateB = "") => !dateA || !dateB ? dateA || dateB : dateA < dateB ? dateA : dateB;
4045
+ var reduceReceivedDevices = (devices, ids, state, status) => devices.reduce(
4046
+ (accu, device) => {
4047
+ const stateDevice = getDeviceById(state, device.id);
4048
+ const {
4049
+ attributes: storedAttributes = {},
4050
+ identity_data: storedIdentity = {},
4051
+ monitor: storedMonitor = {},
4052
+ tags: storedTags = {},
4053
+ group: storedGroup
4054
+ } = stateDevice;
4055
+ const { identity, inventory, monitor, system = {}, tags } = mapDeviceAttributes(device.attributes);
4056
+ device.tags = { ...storedTags, ...tags };
4057
+ device.group = system.group ?? storedGroup;
4058
+ device.monitor = { ...storedMonitor, ...monitor };
4059
+ device.identity_data = { ...storedIdentity, ...identity, ...device.identity_data ? device.identity_data : {} };
4060
+ device.status = status ? status : device.status || identity.status;
4061
+ device.check_in_time_rounded = system.check_in_time ?? stateDevice.check_in_time_rounded;
4062
+ device.check_in_time_exact = device.check_in_time ?? stateDevice.check_in_time_exact;
4063
+ device.created_ts = getEarliestTs(getEarliestTs(system.created_ts, device.created_ts), stateDevice.created_ts);
4064
+ device.updated_ts = device.attributes ? device.updated_ts : stateDevice.updated_ts;
4065
+ device.isNew = new Date(device.created_ts) > new Date(state.app.newThreshold);
4066
+ device.isOffline = new Date(device.check_in_time_rounded) < new Date(state.app.offlineThreshold) || device.check_in_time_rounded === void 0;
4067
+ device.attributes = device.attributes ? { ...storedAttributes, ...inventory } : storedAttributes;
4068
+ accu.devicesById[device.id] = { ...stateDevice, ...device };
4069
+ accu.ids.push(device.id);
4070
+ return accu;
4071
+ },
4072
+ { ids, devicesById: {} }
4073
+ );
4074
+ var getGroupDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getGroupDevices`, (options, { dispatch, getState }) => {
4075
+ const { group, shouldIncludeAllStates, ...remainder } = options;
4076
+ const { cleanedFilters: filterSelection } = getGroupFilters(group, getState().devices.groups);
4077
+ return Promise.resolve(
4078
+ dispatch(getDevicesByStatus2({ ...remainder, filterSelection, group, status: shouldIncludeAllStates ? void 0 : DEVICE_STATES.accepted }))
4079
+ ).unwrap().then((results) => {
4080
+ if (!group) {
4081
+ return Promise.resolve();
4104
4082
  }
4105
- const token = response;
4106
- if (contentType !== APPLICATION_JWT_CONTENT_TYPE || !token) {
4107
- return;
4083
+ const { deviceAccu, total } = results[results.length - 1];
4084
+ const stateGroup = getState().devices.groups.byId[group];
4085
+ if (!stateGroup && !total && !deviceAccu.ids.length) {
4086
+ return Promise.resolve();
4108
4087
  }
4109
- let now = /* @__PURE__ */ new Date();
4110
- now.setSeconds(now.getSeconds() + maxSessionAge);
4111
- const expiresAt = stayLoggedIn ? void 0 : now.toISOString();
4112
- setSessionInfo({ token, expiresAt });
4113
- cookies3.remove("JWT", { path: "/" });
4114
- return (
4115
- // @ts-ignore
4116
- Promise.resolve(dispatch(getUser(OWN_USER_ID))).unwrap().catch((e) => {
4117
- cleanUp();
4118
- return Promise.reject(dispatch(setSnackbar4((0, import_helpers10.extractErrorMessage)(e))));
4119
- }).then(() => {
4120
- window.sessionStorage.removeItem("pendings-redirect");
4121
- if (window.location.pathname !== "/ui/") {
4122
- window.location.replace("/ui/");
4123
- }
4124
- return Promise.resolve(dispatch(actions8.successfullyLoggedIn({ expiresAt, token })));
4125
- })
4088
+ return Promise.resolve(
4089
+ dispatch(
4090
+ actions3.addGroup({
4091
+ group: {
4092
+ deviceIds: deviceAccu.ids.length === total || deviceAccu.ids.length > stateGroup?.deviceIds ? deviceAccu.ids : stateGroup.deviceIds,
4093
+ total
4094
+ },
4095
+ groupName: group
4096
+ })
4097
+ )
4126
4098
  );
4127
- })
4128
- );
4129
- var logoutUser = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/logoutUser`, (_, { dispatch, getState }) => {
4130
- if (Object.keys(getState().app.uploadsById).length) {
4131
- return Promise.reject();
4132
- }
4133
- return general_api_default.post(`${useradmApiUrlv1}/auth/logout`).finally(() => {
4134
- cleanUp();
4135
- (0, import_retrytimer.clearAllRetryTimers)(setSnackbar4);
4136
- return Promise.resolve(dispatch({ type: USER_LOGOUT }));
4137
4099
  });
4138
4100
  });
4139
- var switchUserOrganization = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/switchUserOrganization`, (tenantId, { getState }) => {
4140
- if (Object.keys(getState().app.uploadsById).length) {
4141
- return Promise.reject();
4101
+ var getAllGroupDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getAllGroupDevices`, (group, { dispatch, getState }) => {
4102
+ if (!group || !!group && (!getGroupsById(getState())[group] || getGroupsById(getState())[group].filters.length)) {
4103
+ return Promise.resolve();
4142
4104
  }
4143
- return general_api_default.get(`${useradmApiUrlv1}/users/tenants/${tenantId}/token`).then(({ data: token }) => {
4144
- setSessionInfo({ ...getSessionInfo(), token });
4145
- window.location.reload();
4105
+ const { attributes, filterTerms } = prepareSearchArguments({
4106
+ filters: [],
4107
+ group,
4108
+ state: getState(),
4109
+ status: DEVICE_STATES.accepted
4146
4110
  });
4147
- });
4148
- var passwordResetStart = (0, import_toolkit21.createAsyncThunk)(
4149
- `${sliceName8}/passwordResetStart`,
4150
- (email, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/auth/password-reset/start`, { email }).catch(
4151
- (err) => commonErrorHandler(err, `The password reset request cannot be processed:`, dispatch, void 0, true)
4152
- )
4153
- );
4154
- var passwordResetComplete = (0, import_toolkit21.createAsyncThunk)(
4155
- `${sliceName8}/passwordResetComplete`,
4156
- ({ secretHash, newPassword }, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/auth/password-reset/complete`, { secret_hash: secretHash, password: newPassword }).catch((err = {}) => {
4157
- const { error, response = {} } = err;
4158
- let errorMsg = "";
4159
- if (response.status == 400) {
4160
- errorMsg = "the link you are using expired or the request is not valid, please try again.";
4161
- } else {
4162
- errorMsg = error;
4163
- }
4164
- dispatch(setSnackbar4("The password reset request cannot be processed: " + errorMsg));
4165
- return Promise.reject(err);
4166
- })
4167
- );
4168
- var verifyEmailStart = (0, import_toolkit21.createAsyncThunk)(
4169
- `${sliceName8}/verifyEmailStart`,
4170
- (_, { dispatch, getState }) => general_api_default.post(`${useradmApiUrlv1}/auth/verify-email/start`, { email: getCurrentUser(getState()).email }).catch((err) => commonErrorHandler(err, "An error occured starting the email verification process:", dispatch)).finally(() => Promise.resolve(dispatch(getUser(OWN_USER_ID))))
4171
- );
4172
- var verifyEmailComplete = (0, import_toolkit21.createAsyncThunk)(
4173
- `${sliceName8}/verifyEmailComplete`,
4174
- (secret_hash, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/auth/verify-email/complete`, { secret_hash }).catch((err) => commonErrorHandler(err, "An error occured completing the email verification process:", dispatch)).finally(() => Promise.resolve(dispatch(getUser(OWN_USER_ID))))
4175
- );
4176
- var verify2FA = (0, import_toolkit21.createAsyncThunk)(
4177
- `${sliceName8}/verify2FA`,
4178
- (tfaData, { dispatch }) => users_api_default.putVerifyTFA(`${useradmApiUrlv1}/2faverify`, tfaData).then(() => Promise.resolve(dispatch(getUser(OWN_USER_ID)))).catch(
4179
- (err) => commonErrorHandler(err, "An error occured validating the verification code: failed to verify token, please try again.", dispatch, void 0, true)
4180
- )
4181
- );
4182
- var getUserList = (0, import_toolkit21.createAsyncThunk)(
4183
- `${sliceName8}/getUserList`,
4184
- (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/users`).then((res) => {
4185
- const users = res.data.reduce((accu, item) => {
4186
- accu[item.id] = item;
4187
- return accu;
4188
- }, {});
4189
- return dispatch(actions8.receivedUserList(users));
4190
- }).catch((err) => commonErrorHandler(err, `Users couldn't be loaded.`, dispatch, commonErrorFallback))
4191
- );
4192
- var getUser = (0, import_toolkit21.createAsyncThunk)(
4193
- `${sliceName8}/getUser`,
4194
- (id, { dispatch, rejectWithValue }) => general_api_default.get(`${useradmApiUrlv1}/users/${id}`).then(
4195
- ({ data: user }) => Promise.all([
4196
- dispatch(actions8.receivedUser(user)),
4197
- // @ts-ignore
4198
- dispatch(setHideAnnouncement({ shouldHide: false, userId: user.id })),
4199
- // @ts-ignore
4200
- dispatch(updateUserColumnSettings({ currentUserId: user.id })),
4201
- user
4202
- ])
4203
- ).catch((e) => rejectWithValue(e))
4204
- );
4205
- var initializeSelf = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/initializeSelf`, (_, { dispatch }) => dispatch(getUser(OWN_USER_ID)));
4206
- var updateUserColumnSettings = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/updateUserColumnSettings`, ({ columns, currentUserId }, { dispatch, getState }) => {
4207
- const userId = currentUserId ?? getCurrentUser(getState()).id;
4208
- const storageKey = `${userId}-column-widths`;
4209
- let customColumns = [];
4210
- if (!columns) {
4211
- try {
4212
- customColumns = JSON.parse(window.localStorage.getItem(storageKey)) || customColumns;
4213
- } catch {
4111
+ const getAllDevices = (perPage = MAX_PAGE_SIZE, page = defaultPage3, devices = []) => general_api_default.post(getSearchEndpoint(getState()), {
4112
+ page,
4113
+ per_page: perPage,
4114
+ filters: filterTerms,
4115
+ attributes
4116
+ }).then((res) => {
4117
+ const state = getState();
4118
+ const deviceAccu = reduceReceivedDevices(res.data, devices, state);
4119
+ dispatch(actions3.receivedDevices(deviceAccu.devicesById));
4120
+ const total = Number(res.headers[headerNames.total]);
4121
+ if (total > perPage * page) {
4122
+ return getAllDevices(perPage, page + 1, deviceAccu.ids);
4214
4123
  }
4215
- } else {
4216
- customColumns = columns;
4217
- }
4218
- window.localStorage.setItem(storageKey, JSON.stringify(customColumns));
4219
- return Promise.resolve(dispatch(actions8.setCustomColumns(customColumns)));
4124
+ return Promise.resolve(dispatch(actions3.addGroup({ group: { deviceIds: deviceAccu.ids, total: deviceAccu.ids.length }, groupName: group })));
4125
+ });
4126
+ return getAllDevices();
4220
4127
  });
4221
- var userActions = {
4222
- add: {
4223
- successMessage: "The user was added successfully.",
4224
- errorMessage: "adding"
4225
- },
4226
- create: {
4227
- successMessage: "The user was created successfully.",
4228
- errorMessage: "creating"
4229
- },
4230
- edit: {
4231
- successMessage: "The user has been updated.",
4232
- errorMessage: "editing"
4233
- },
4234
- remove: {
4235
- successMessage: "The user was removed from the system.",
4236
- errorMessage: "removing"
4128
+ var getAllDynamicGroupDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getAllDynamicGroupDevices`, (group, { dispatch, getState }) => {
4129
+ if (!!group && (!getGroupsById(getState())[group] || !getGroupsById(getState())[group].filters.length)) {
4130
+ return Promise.resolve();
4237
4131
  }
4238
- };
4239
- var userActionErrorHandler = (err, type, dispatch) => commonErrorHandler(err, `There was an error ${userActions[type].errorMessage} the user.`, dispatch);
4240
- var createUser = (0, import_toolkit21.createAsyncThunk)(
4241
- `${sliceName8}/createUser`,
4242
- ({ shouldResetPassword, ...userData }, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/users`, { ...userData, send_reset_password: shouldResetPassword }).then(() => Promise.all([dispatch(actions8.createdUser(userData)), dispatch(getUserList()), dispatch(setSnackbar4(userActions.create.successMessage))])).catch((err) => userActionErrorHandler(err, "create", dispatch))
4243
- );
4244
- var removeUser = (0, import_toolkit21.createAsyncThunk)(
4245
- `${sliceName8}/removeUser`,
4246
- (userId, { dispatch }) => (
4247
- // @ts-ignore
4248
- general_api_default.delete(`${useradmApiUrlv1}/users/${userId}`).then(() => Promise.all([dispatch(actions8.removedUser(userId)), dispatch(getUserList()), dispatch(setSnackbar4(userActions.remove.successMessage))])).catch((err) => userActionErrorHandler(err, "remove", dispatch))
4249
- )
4250
- );
4251
- var editUser = (0, import_toolkit21.createAsyncThunk)(
4252
- `${sliceName8}/editUser`,
4253
- ({ id, ...userData }, { dispatch, getState }) => general_api_default.put(`${useradmApiUrlv1}/users/${id}`, userData).then(
4254
- () => Promise.all([
4255
- dispatch(actions8.updatedUser({ ...userData, id: id === OWN_USER_ID ? getCurrentUser(getState()).id : id })),
4256
- dispatch(setSnackbar4(userActions.edit.successMessage))
4257
- ])
4258
- )
4259
- );
4260
- var addUserToCurrentTenant = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/addUserToTenant`, (userId, { dispatch, getState }) => {
4261
- const { id } = getOrganization(getState());
4262
- return general_api_default.post(`${useradmApiUrlv1}/users/${userId}/assign`, { tenant_ids: [id] }).catch((err) => commonErrorHandler(err, `There was an error adding the user to your organization:`, dispatch)).then(() => Promise.all([dispatch(setSnackbar4(userActions.add.successMessage)), dispatch(getUserList())]));
4132
+ const { attributes, filterTerms: filters } = prepareSearchArguments({
4133
+ filters: getState().devices.groups.byId[group].filters,
4134
+ state: getState(),
4135
+ status: DEVICE_STATES.accepted
4136
+ });
4137
+ const getAllDevices = (perPage = MAX_PAGE_SIZE, page = defaultPage3, devices = []) => general_api_default.post(getSearchEndpoint(getState()), { page, per_page: perPage, filters, attributes }).then((res) => {
4138
+ const state = getState();
4139
+ const deviceAccu = reduceReceivedDevices(res.data, devices, state);
4140
+ dispatch(actions3.receivedDevices(deviceAccu.devicesById));
4141
+ const total = Number(res.headers[headerNames.total]);
4142
+ if (total > deviceAccu.ids.length) {
4143
+ return getAllDevices(perPage, page + 1, deviceAccu.ids);
4144
+ }
4145
+ return Promise.resolve(dispatch(actions3.addGroup({ group: { deviceIds: deviceAccu.ids, total }, groupName: group })));
4146
+ });
4147
+ return getAllDevices();
4263
4148
  });
4264
- var enableUser2fa = (0, import_toolkit21.createAsyncThunk)(
4265
- `${sliceName8}/enableUser2fa`,
4266
- (userId = OWN_USER_ID, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/users/${userId}/2fa/enable`).catch((err) => commonErrorHandler(err, `There was an error enabling Two Factor authentication for the user.`, dispatch)).then(() => Promise.resolve(dispatch(getUser(userId))))
4267
- );
4268
- var disableUser2fa = (0, import_toolkit21.createAsyncThunk)(
4269
- `${sliceName8}/disableUser2fa`,
4270
- (userId = OWN_USER_ID, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/users/${userId}/2fa/disable`).catch((err) => commonErrorHandler(err, `There was an error disabling Two Factor authentication for the user.`, dispatch)).then(() => Promise.resolve(dispatch(getUser(userId))))
4271
- );
4272
- var mapHttpPermission = (permission) => Object.entries(uiPermissionsByArea).reduce(
4273
- (accu, [area, definition]) => {
4274
- const endpointMatches = definition.endpoints.filter(
4275
- (endpoint) => endpoint.path.test(permission.value) && (endpoint.types.includes(permission.type) || permission.type === PermissionTypes.Any)
4276
- );
4277
- if (permission.value === PermissionTypes.Any || permission.value.includes(apiRoot) && endpointMatches.length) {
4278
- const endpointUiPermission = endpointMatches.reduce((endpointAccu, endpoint) => [...endpointAccu, ...endpoint.uiPermissions], []);
4279
- const collector = (endpointUiPermission || definition.uiPermissions).reduce((permissionsAccu, uiPermission) => {
4280
- if (permission.type === PermissionTypes.Any || !endpointMatches.length && uiPermission.verbs.some((verb) => verb === permission.type)) {
4281
- permissionsAccu.push(uiPermission.value);
4282
- }
4283
- return permissionsAccu;
4284
- }, []).filter(import_helpers10.duplicateFilter);
4285
- if (Array.isArray(accu[area])) {
4286
- accu[area] = [...accu[area], ...collector].filter(import_helpers10.duplicateFilter);
4287
- } else {
4288
- accu[area] = mergePermissions(accu[area], { [scopedPermissionAreas[area].excessiveAccessSelector]: collector });
4289
- }
4149
+ var getDeviceById2 = (0, import_toolkit21.createAsyncThunk)(
4150
+ `${sliceName3}/getDeviceById`,
4151
+ (id, { dispatch, getState }) => general_api_default.get(`${inventoryApiUrl}/devices/${id}`).then((res) => {
4152
+ const device = reduceReceivedDevices([res.data], [], getState()).devicesById[id];
4153
+ device.etag = res.headers.etag;
4154
+ dispatch(actions3.receivedDevice(device));
4155
+ return Promise.resolve(device);
4156
+ }).catch((err) => {
4157
+ const errMsg = (0, import_helpers10.extractErrorMessage)(err);
4158
+ if (errMsg.includes("Not Found")) {
4159
+ console.log(`${id} does not have any inventory information`);
4160
+ const device = reduceReceivedDevices(
4161
+ [
4162
+ {
4163
+ id,
4164
+ attributes: [
4165
+ { name: "status", value: "decomissioned", scope: "identity" },
4166
+ { name: "decomissioned", value: "true", scope: "inventory" }
4167
+ ]
4168
+ }
4169
+ ],
4170
+ [],
4171
+ getState()
4172
+ ).devicesById[id];
4173
+ dispatch(actions3.receivedDevice(device));
4290
4174
  }
4291
- return accu;
4292
- },
4293
- { ...emptyUiPermissions }
4175
+ })
4294
4176
  );
4295
- var permissionActionTypes = {
4296
- any: mapHttpPermission,
4297
- CREATE_DEPLOYMENT: (permission) => permission.type === PermissionTypes.DeviceGroup ? {
4298
- deployments: [uiPermissionsById.deploy.value],
4299
- groups: { [permission.value]: [uiPermissionsById.deploy.value] }
4300
- } : {},
4301
- http: mapHttpPermission,
4302
- REMOTE_TERMINAL: (permission) => permission.type === PermissionTypes.DeviceGroup ? {
4303
- groups: { [permission.value]: [uiPermissionsById.connect.value] }
4304
- } : {},
4305
- VIEW_DEVICE: (permission) => permission.type === PermissionTypes.DeviceGroup ? {
4306
- groups: { [permission.value]: [uiPermissionsById.read.value] }
4307
- } : {}
4308
- };
4309
- var combinePermissions = (existingPermissions, additionalPermissions = {}) => Object.entries(additionalPermissions).reduce((accu, [name, permissions]) => {
4310
- let maybeExistingPermissions = accu[name] || [];
4311
- accu[name] = [...permissions, ...maybeExistingPermissions].filter(import_helpers10.duplicateFilter);
4312
- return accu;
4313
- }, existingPermissions);
4314
- var tryParseCustomPermission = (permission) => {
4315
- const uiPermissions = permissionActionTypes[permission.action](permission.object);
4316
- const result = mergePermissions({ ...emptyUiPermissions }, uiPermissions);
4317
- return { isCustom: true, permission, result };
4318
- };
4319
- var customPermissionHandler = (accu, permission) => {
4320
- let processor = tryParseCustomPermission(permission);
4321
- return {
4322
- ...accu,
4323
- isCustom: accu.isCustom || processor.isCustom,
4324
- uiPermissions: mergePermissions(accu.uiPermissions, processor.result)
4325
- };
4326
- };
4327
- var mapPermissionSet = (permissionSetName, names, scope, existingGroupsPermissions = {}) => {
4328
- const permission = Object.values(uiPermissionsById).find((permission2) => permission2.permissionSets[scope] === permissionSetName).value;
4329
- const scopedPermissions = names.reduce((accu, name) => combinePermissions(accu, { [name]: [permission] }), existingGroupsPermissions);
4330
- return Object.entries(scopedPermissions).reduce((accu, [key, permissions]) => ({ ...accu, [key]: deriveImpliedAreaPermissions(scope, permissions) }), {});
4331
- };
4332
- var isEmptyPermissionSet = (permissionSet) => !Object.values(permissionSet).reduce((accu, permissions) => {
4333
- if (Array.isArray(permissions)) {
4334
- return accu || !!permissions.length;
4177
+ var getDeviceInfo = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getDeviceInfo`, (deviceId, { dispatch, getState }) => {
4178
+ const device = getDeviceById(getState(), deviceId);
4179
+ const { hasDeviceConfig, hasDeviceConnect, hasMonitor } = getTenantCapabilities(getState());
4180
+ const { canConfigure } = getUserCapabilities(getState());
4181
+ const integrations = getDeviceTwinIntegrations(getState());
4182
+ let tasks = [dispatch(getDeviceAuth(deviceId)), ...integrations.map((integration) => dispatch(getDeviceTwin({ deviceId, integration })))];
4183
+ if (hasDeviceConfig && canConfigure && [DEVICE_STATES.accepted, DEVICE_STATES.preauth].includes(device.status)) {
4184
+ tasks.push(dispatch(getDeviceConfig(deviceId)));
4335
4185
  }
4336
- return accu || !(0, import_helpers10.isEmpty)(permissions);
4337
- }, false);
4338
- var parseRolePermissions = ({ permission_sets_with_scope = [], permissions = [] }, permissionSets) => {
4339
- const preliminaryResult = permission_sets_with_scope.reduce(
4340
- (accu, permissionSet) => {
4341
- let processor = permissionSets[permissionSet.name];
4342
- if (!processor) {
4343
- return accu;
4344
- }
4345
- const scope = Object.keys(scopedPermissionAreas).find((scope2) => uiPermissionsByArea[scope2].scope === permissionSet.scope?.type);
4346
- if (scope) {
4347
- const result = mapPermissionSet(permissionSet.name, permissionSet.scope.value, scope, accu.uiPermissions[scope]);
4348
- return { ...accu, uiPermissions: { ...accu.uiPermissions, [scope]: result } };
4349
- } else if (isEmptyPermissionSet(processor.result)) {
4350
- return processor.permissions.reduce(customPermissionHandler, accu);
4186
+ if (device.status === DEVICE_STATES.accepted) {
4187
+ tasks.push(dispatch(getDeviceById2(deviceId)));
4188
+ if (hasDeviceConnect) {
4189
+ tasks.push(dispatch(getDeviceConnect(deviceId)));
4190
+ }
4191
+ if (hasMonitor) {
4192
+ tasks.push(dispatch(getLatestDeviceAlerts({ id: deviceId })));
4193
+ tasks.push(dispatch(getDeviceMonitorConfig(deviceId)));
4194
+ }
4195
+ }
4196
+ return Promise.all(tasks);
4197
+ });
4198
+ var deriveInactiveDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/deriveInactiveDevices`, (deviceIds, { dispatch, getState }) => {
4199
+ const yesterday = /* @__PURE__ */ new Date();
4200
+ yesterday.setDate(yesterday.getDate() - 1);
4201
+ const yesterdaysIsoString = yesterday.toISOString();
4202
+ const devices = deviceIds.reduce(
4203
+ (accu, id) => {
4204
+ const device = getDeviceById(getState(), id);
4205
+ if (device && device.updated_ts > yesterdaysIsoString) {
4206
+ accu.active.push(id);
4207
+ } else {
4208
+ accu.inactive.push(id);
4351
4209
  }
4352
- return {
4353
- ...accu,
4354
- isCustom: accu.isCustom || processor.isCustom,
4355
- uiPermissions: mergePermissions(accu.uiPermissions, processor.result)
4356
- };
4210
+ return accu;
4357
4211
  },
4358
- { isCustom: false, uiPermissions: { ...emptyUiPermissions, groups: {}, releases: {} } }
4212
+ { active: [], inactive: [] }
4359
4213
  );
4360
- return permissions.reduce(customPermissionHandler, preliminaryResult);
4361
- };
4362
- var normalizeRbacRoles = (roles, rolesById2, permissionSets) => roles.reduce(
4363
- (accu, role) => {
4364
- let normalizedPermissions;
4365
- let isCustom = false;
4366
- if (rolesById2[role.name]) {
4367
- normalizedPermissions = {
4368
- ...rolesById2[role.name].uiPermissions,
4369
- groups: { ...rolesById2[role.name].uiPermissions.groups },
4370
- releases: { ...rolesById2[role.name].uiPermissions.releases }
4371
- };
4372
- } else {
4373
- const result = parseRolePermissions(role, permissionSets);
4374
- normalizedPermissions = result.uiPermissions;
4375
- isCustom = result.isCustom;
4214
+ return dispatch(actions3.setInactiveDevices({ activeDeviceTotal: devices.active.length, inactiveDeviceTotal: devices.inactive.length }));
4215
+ });
4216
+ var getDeviceCount = (0, import_toolkit21.createAsyncThunk)(
4217
+ `${sliceName3}/getDeviceCount`,
4218
+ (status, { dispatch, getState }) => general_api_default.post(getSearchEndpoint(getState()), {
4219
+ page: 1,
4220
+ per_page: 1,
4221
+ filters: mapFiltersToTerms([{ key: "status", value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: "identity" }]),
4222
+ attributes: defaultAttributes
4223
+ }).then((response) => {
4224
+ const count = Number(response.headers[headerNames.total]);
4225
+ if (status) {
4226
+ return dispatch(actions3.setDevicesCountByStatus({ count, status }));
4376
4227
  }
4377
- const roleState = accu[role.name] ?? { ...emptyRole };
4378
- accu[role.name] = {
4379
- ...roleState,
4380
- ...role,
4381
- description: roleState.description ? roleState.description : role.description,
4382
- editable: !rolesById[role.name] && !isCustom && (typeof roleState.editable !== "undefined" ? roleState.editable : true),
4383
- isCustom,
4384
- name: roleState.name ? roleState.name : role.name,
4385
- uiPermissions: normalizedPermissions
4228
+ return dispatch(actions3.setTotalDevices(count));
4229
+ })
4230
+ );
4231
+ var getAllDeviceCounts = (0, import_toolkit21.createAsyncThunk)(
4232
+ `${sliceName3}/getAllDeviceCounts`,
4233
+ (_, { dispatch }) => Promise.all([DEVICE_STATES.accepted, DEVICE_STATES.pending].map((status) => dispatch(getDeviceCount(status))))
4234
+ );
4235
+ var getDeviceLimit2 = (0, import_toolkit21.createAsyncThunk)(
4236
+ `${sliceName3}/getDeviceLimit`,
4237
+ (_, { dispatch }) => general_api_default.get(`${deviceAuthV2}/limits/max_devices`).then((res) => dispatch(actions3.setDeviceLimit(res.data.limit)))
4238
+ );
4239
+ var setDeviceListState = (0, import_toolkit21.createAsyncThunk)(
4240
+ `${sliceName3}/setDeviceListState`,
4241
+ ({ shouldSelectDevices = true, forceRefresh, fetchAuth = true, ...selectionState }, { dispatch, getState }) => {
4242
+ const currentState = getDeviceListState(getState());
4243
+ const refreshTrigger = forceRefresh ? !currentState.refreshTrigger : selectionState.refreshTrigger;
4244
+ let nextState = {
4245
+ ...currentState,
4246
+ setOnly: false,
4247
+ refreshTrigger,
4248
+ ...selectionState,
4249
+ sort: { ...currentState.sort, ...selectionState.sort }
4386
4250
  };
4251
+ let tasks = [];
4252
+ const { isLoading: currentLoading, deviceIds: currentDevices, selection: currentSelection, ...currentRequestState } = currentState;
4253
+ const { isLoading: nextLoading, deviceIds: nextDevices, selection: nextSelection, ...nextRequestState } = nextState;
4254
+ if (!nextState.setOnly && !(0, import_helpers10.deepCompare)(currentRequestState, nextRequestState)) {
4255
+ const { direction: sortDown = SORTING_OPTIONS.desc, key: sortCol, scope: sortScope } = nextState.sort ?? {};
4256
+ const sortBy = sortCol ? [{ attribute: sortCol, order: sortDown, scope: sortScope }] : void 0;
4257
+ const applicableSelectedState = nextState.state === ALL_DEVICE_STATES ? void 0 : nextState.state;
4258
+ nextState.isLoading = true;
4259
+ tasks.push(
4260
+ dispatch(getDevicesByStatus2({ ...nextState, status: applicableSelectedState, sortOptions: sortBy, fetchAuth })).unwrap().then((results) => {
4261
+ const { deviceAccu, total } = results[results.length - 1];
4262
+ const devicesState = shouldSelectDevices ? { deviceIds: deviceAccu.ids, total, isLoading: false } : { isLoading: false };
4263
+ return Promise.resolve(dispatch(actions3.setDeviceListState(devicesState)));
4264
+ }).catch(() => Promise.resolve({ isLoading: false }))
4265
+ );
4266
+ }
4267
+ tasks.push(dispatch(actions3.setDeviceListState(nextState)));
4268
+ return Promise.all(tasks);
4269
+ }
4270
+ );
4271
+ var getDevicesByStatus2 = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getDevicesByStatus`, (options, { dispatch, getState }) => {
4272
+ const {
4273
+ status,
4274
+ fetchAuth = true,
4275
+ filterSelection,
4276
+ group,
4277
+ selectedIssues = [],
4278
+ page = defaultPage3,
4279
+ perPage = defaultPerPage3,
4280
+ sortOptions = [],
4281
+ selectedAttributes = getSelectedDeviceAttribute(getState())
4282
+ } = options;
4283
+ const state = getState();
4284
+ const { applicableFilters, filterTerms } = convertDeviceListStateToFilters({
4285
+ filters: filterSelection ?? getDeviceFilters(state),
4286
+ group: group ?? getSelectedGroup(state),
4287
+ groups: state.devices.groups,
4288
+ offlineThreshold: state.app.offlineThreshold,
4289
+ selectedIssues,
4290
+ status
4291
+ });
4292
+ const attributes = [...defaultAttributes, getIdAttribute(getState()), ...selectedAttributes];
4293
+ return general_api_default.post(getSearchEndpoint(getState()), {
4294
+ page,
4295
+ per_page: perPage,
4296
+ filters: filterTerms,
4297
+ sort: sortOptions,
4298
+ attributes
4299
+ }).then((response) => {
4300
+ const state2 = getState();
4301
+ const deviceAccu = reduceReceivedDevices(response.data, [], state2, status);
4302
+ let total = !applicableFilters.length ? Number(response.headers[headerNames.total]) : null;
4303
+ if (status && state2.devices.byStatus[status].total === deviceAccu.ids.length) {
4304
+ total = deviceAccu.ids.length;
4305
+ }
4306
+ let tasks = [dispatch(actions3.receivedDevices(deviceAccu.devicesById))];
4307
+ if (status) {
4308
+ tasks.push(dispatch(actions3.setDevicesByStatus({ deviceIds: deviceAccu.ids, status, total })));
4309
+ }
4310
+ const receivedDevices = Object.values(deviceAccu.devicesById);
4311
+ if (receivedDevices.length && fetchAuth) {
4312
+ tasks.push(dispatch(getDevicesWithAuth(receivedDevices)));
4313
+ }
4314
+ tasks.push(Promise.resolve({ deviceAccu, total: Number(response.headers[headerNames.total]) }));
4315
+ return Promise.all(tasks);
4316
+ }).catch((err) => commonErrorHandler(err, `${status} devices couldn't be loaded.`, dispatch, commonErrorFallback));
4317
+ });
4318
+ var getAllDevicesByStatus = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getAllDevicesByStatus`, (status, { dispatch, getState }) => {
4319
+ const attributes = [...defaultAttributes, getIdAttribute(getState())];
4320
+ const getAllDevices = (perPage = MAX_PAGE_SIZE, page = 1, devices = []) => general_api_default.post(getSearchEndpoint(getState()), {
4321
+ page,
4322
+ per_page: perPage,
4323
+ filters: mapFiltersToTerms([{ key: "status", value: status, operator: DEVICE_FILTERING_OPTIONS.$eq.key, scope: "identity" }]),
4324
+ attributes
4325
+ }).then((res) => {
4326
+ const state = getState();
4327
+ const deviceAccu = reduceReceivedDevices(res.data, devices, state, status);
4328
+ dispatch(actions3.receivedDevices(deviceAccu.devicesById));
4329
+ const total = Number(res.headers[headerNames.total]);
4330
+ if (total > state.deployments.deploymentDeviceLimit) {
4331
+ return Promise.resolve();
4332
+ }
4333
+ if (total > perPage * page) {
4334
+ return getAllDevices(perPage, page + 1, deviceAccu.ids);
4335
+ }
4336
+ let tasks = [dispatch(actions3.setDevicesByStatus({ deviceIds: deviceAccu.ids, forceUpdate: true, status, total: deviceAccu.ids.length }))];
4337
+ if (status === DEVICE_STATES.accepted && deviceAccu.ids.length === total) {
4338
+ tasks.push(dispatch(deriveInactiveDevices(deviceAccu.ids)));
4339
+ tasks.push(dispatch(deriveReportsData()));
4340
+ }
4341
+ return Promise.all(tasks);
4342
+ });
4343
+ return getAllDevices();
4344
+ });
4345
+ var searchDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/searchDevices`, (passedOptions = {}, { dispatch, getState }) => {
4346
+ const state = getState();
4347
+ let options = { ...state.app.searchState, ...passedOptions };
4348
+ const { page = defaultPage3, searchTerm, sortOptions = [] } = options;
4349
+ const { columnSelection = [] } = getUserSettings(state);
4350
+ const selectedAttributes = columnSelection.map((column) => ({ attribute: column.key, scope: column.scope }));
4351
+ const attributes = (0, import_helpers10.attributeDuplicateFilter)([...defaultAttributes, getIdAttribute(state), ...selectedAttributes], "attribute");
4352
+ return general_api_default.post(getSearchEndpoint(getState()), {
4353
+ page,
4354
+ per_page: 10,
4355
+ filters: [],
4356
+ sort: sortOptions,
4357
+ text: searchTerm,
4358
+ attributes
4359
+ }).then((response) => {
4360
+ const deviceAccu = reduceReceivedDevices(response.data, [], getState());
4361
+ return Promise.all([
4362
+ dispatch(actions3.receivedDevices(deviceAccu.devicesById)),
4363
+ Promise.resolve({ deviceIds: deviceAccu.ids, searchTotal: Number(response.headers[headerNames.total]) })
4364
+ ]);
4365
+ }).catch((err) => commonErrorHandler(err, `devices couldn't be searched.`, dispatch, commonErrorFallback));
4366
+ });
4367
+ var ATTRIBUTE_LIST_CUTOFF = 100;
4368
+ var attributeReducer = (attributes = []) => attributes.slice(0, ATTRIBUTE_LIST_CUTOFF).reduce(
4369
+ (accu, { name, scope }) => {
4370
+ if (!accu[scope]) {
4371
+ accu[scope] = [];
4372
+ }
4373
+ accu[scope].push(name);
4387
4374
  return accu;
4388
4375
  },
4389
- { ...rolesById2 }
4376
+ { identity: [], inventory: [], system: [], tags: [] }
4390
4377
  );
4391
- var getPermissionSets = (0, import_toolkit21.createAsyncThunk)(
4392
- `${sliceName8}/getPermissionSets`,
4393
- (_, { dispatch, getState }) => general_api_default.get(`${useradmApiUrlv2}/permission_sets?per_page=500`).then(({ data }) => {
4394
- const permissionSets = data.reduce(
4395
- (accu, permissionSet) => {
4396
- const permissionSetState = accu[permissionSet.name] ?? {};
4397
- let permissionSetObject = { ...permissionSetState, ...permissionSet };
4398
- permissionSetObject.result = Object.values(uiPermissionsById).reduce(
4399
- (accu2, item) => Object.entries(item.permissionSets).reduce((collector, [area, permissionSet2]) => {
4400
- if (scopedPermissionAreas[area]) {
4401
- return collector;
4402
- }
4403
- if (permissionSet2 === permissionSetObject.name) {
4404
- collector[area] = [...collector[area], item.value].filter(import_helpers10.duplicateFilter);
4405
- }
4406
- return collector;
4407
- }, accu2),
4408
- { ...emptyUiPermissions, ...permissionSetObject.result ?? {} }
4409
- );
4410
- const scopes = Object.values(scopedPermissionAreas).reduce((accu2, { key, scopeType }) => {
4411
- if (permissionSetObject.supported_scope_types?.includes(key) || permissionSetObject.supported_scope_types?.includes(scopeType)) {
4412
- accu2.push(key);
4413
- }
4414
- return accu2;
4415
- }, []);
4416
- permissionSetObject = scopes.reduce((accu2, scope) => {
4417
- accu2.result[scope] = mapPermissionSet(permissionSetObject.name, [scopedPermissionAreas[scope].excessiveAccessSelector], scope);
4418
- return accu2;
4419
- }, permissionSetObject);
4420
- accu[permissionSet.name] = permissionSetObject;
4421
- return accu;
4422
- },
4423
- // @ts-ignore
4424
- { ...getState().users.permissionSetsById }
4425
- );
4426
- return Promise.all([dispatch(actions8.receivedPermissionSets(permissionSets)), permissionSets]);
4427
- }).catch(() => console.log("Permission set retrieval failed - likely accessing a non-RBAC backend"))
4378
+ var getDeviceAttributes = (0, import_toolkit21.createAsyncThunk)(
4379
+ `${sliceName3}/getDeviceAttributes`,
4380
+ (_, { dispatch, getState }) => general_api_default.get(getAttrsEndpoint(getState())).then(({ data }) => {
4381
+ const { identity: identityAttributes, inventory: inventoryAttributes, system: systemAttributes, tags: tagAttributes } = attributeReducer(data || []);
4382
+ return dispatch(actions3.setFilterAttributes({ identityAttributes, inventoryAttributes, systemAttributes, tagAttributes }));
4383
+ })
4428
4384
  );
4429
- var getRoles = (0, import_toolkit21.createAsyncThunk)(
4430
- `${sliceName8}/getRoles`,
4431
- (_, { dispatch, getState }) => Promise.all([general_api_default.get(`${useradmApiUrlv2}/roles?per_page=500`), dispatch(getPermissionSets())]).then((results) => {
4432
- if (!results) {
4433
- return Promise.resolve();
4434
- }
4435
- const [{ data: roles }, { payload: permissionSetTasks }] = results;
4436
- const rolesById2 = normalizeRbacRoles(roles, getRolesById(getState()), permissionSetTasks[permissionSetTasks.length - 1]);
4437
- return Promise.resolve(dispatch(actions8.receivedRoles(rolesById2)));
4438
- }).catch(() => console.log("Role retrieval failed - likely accessing a non-RBAC backend"))
4385
+ var getReportingLimits = (0, import_toolkit21.createAsyncThunk)(
4386
+ `${sliceName3}/getReportingLimits`,
4387
+ (_, { dispatch }) => general_api_default.get(`${reportingApiUrl}/devices/attributes`).catch((err) => commonErrorHandler(err, `filterable attributes limit & usage could not be retrieved.`, dispatch, commonErrorFallback)).then(({ data }) => {
4388
+ const { attributes, count, limit } = data;
4389
+ const groupedAttributes = attributeReducer(attributes);
4390
+ return Promise.resolve(dispatch(actions3.setFilterablesConfig({ count, limit, attributes: groupedAttributes })));
4391
+ })
4439
4392
  );
4440
- var deriveImpliedAreaPermissions = (area, areaPermissions, skipPermissions = []) => {
4441
- const highestAreaPermissionLevelSelected = areaPermissions.reduce(
4442
- (highest, current) => uiPermissionsById[current].permissionLevel > highest ? uiPermissionsById[current].permissionLevel : highest,
4443
- 1
4444
- );
4445
- return uiPermissionsByArea[area].uiPermissions.reduce((permissions, current) => {
4446
- if ((current.permissionLevel < highestAreaPermissionLevelSelected || areaPermissions.includes(current.value)) && !skipPermissions.includes(current.value)) {
4447
- permissions.push(current.value);
4448
- }
4449
- return permissions;
4450
- }, []);
4393
+ var ensureVersionString = (software, fallback) => software.length && software !== "artifact_name" ? software.endsWith(".version") ? software : `${software}.version` : fallback;
4394
+ var getSingleReportData = (reportConfig, groups) => {
4395
+ const { attribute, group, software = "" } = reportConfig;
4396
+ const filters = [{ key: "status", scope: "identity", operator: DEVICE_FILTERING_OPTIONS.$eq.key, value: "accepted" }];
4397
+ if (group) {
4398
+ const staticGroupFilter = { key: "group", scope: "system", operator: DEVICE_FILTERING_OPTIONS.$eq.key, value: group };
4399
+ const { cleanedFilters: groupFilters } = getGroupFilters(group, groups);
4400
+ filters.push(...groupFilters.length ? groupFilters : [staticGroupFilter]);
4401
+ }
4402
+ const aggregationAttribute = ensureVersionString(software, attribute);
4403
+ return general_api_default.post(`${reportingApiUrl}/devices/aggregate`, {
4404
+ aggregations: [{ attribute: aggregationAttribute, name: "*", scope: "inventory", size: REPORT_CHART_SIZE_LIMIT }],
4405
+ filters: mapFiltersToTerms(filters)
4406
+ }).then(({ data }) => ({ data, reportConfig }));
4451
4407
  };
4452
- var transformAreaRoleDataToScopedPermissionsSets = (area, areaPermissions, excessiveAccessSelector) => {
4453
- const permissionSetObject = areaPermissions.reduce((accu, { item, uiPermissions }) => {
4454
- const skipPermissions = scopedPermissionAreas.releases.key === area && item !== ALL_RELEASES ? [uiPermissionsById.upload.value] : [];
4455
- const impliedPermissions = deriveImpliedAreaPermissions(area, uiPermissions, skipPermissions);
4456
- accu = impliedPermissions.reduce((itemPermissionAccu, impliedPermission) => {
4457
- const permissionSetState = itemPermissionAccu[uiPermissionsById[impliedPermission].permissionSets[area]] ?? {
4458
- type: uiPermissionsByArea[area].scope,
4459
- value: []
4460
- };
4461
- itemPermissionAccu[uiPermissionsById[impliedPermission].permissionSets[area]] = {
4462
- ...permissionSetState,
4463
- value: [...permissionSetState.value, item]
4464
- };
4465
- return itemPermissionAccu;
4466
- }, accu);
4408
+ var getReportsData = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getReportsData`, (_, { dispatch, getState }) => {
4409
+ const state = getState();
4410
+ const currentUserId = getCurrentUser(state).id;
4411
+ const reports = getUserSettings(state).reports || getGlobalSettings(state)[`${currentUserId}-reports`] || (Object.keys(getDevicesById(state)).length ? defaultReports : []);
4412
+ return Promise.all(reports.map((report) => getSingleReportData(report, getState().devices.groups))).then((results) => {
4413
+ const devicesState = getState().devices;
4414
+ const totalDeviceCount = devicesState.byStatus.accepted.total;
4415
+ const newReports = results.map(({ data, reportConfig }) => {
4416
+ let { items, other_count } = data[0];
4417
+ const { attribute, group, software = "" } = reportConfig;
4418
+ const dataCount = items.reduce((accu, item) => accu + item.count, 0);
4419
+ const otherCount = !group && (software === rootfsImageVersion || attribute === "artifact_name") ? totalDeviceCount - dataCount : other_count;
4420
+ return { items, otherCount, total: otherCount + dataCount };
4421
+ });
4422
+ return Promise.resolve(dispatch(actions3.setDeviceReports(newReports)));
4423
+ });
4424
+ });
4425
+ var initializeDistributionData = (report, groups, devices, totalDeviceCount) => {
4426
+ const { attribute, group = "", software = "" } = report;
4427
+ const effectiveAttribute = software ? software : attribute;
4428
+ const { deviceIds, total = 0 } = groups[group] || {};
4429
+ const relevantDevices = groups[group] ? deviceIds.map((id) => devices[id]) : Object.values(devices);
4430
+ const distributionByAttribute = relevantDevices.reduce((accu, item) => {
4431
+ if (!item.attributes || item.status !== DEVICE_STATES.accepted) return accu;
4432
+ if (!accu[item.attributes[effectiveAttribute]]) {
4433
+ accu[item.attributes[effectiveAttribute]] = 0;
4434
+ }
4435
+ accu[item.attributes[effectiveAttribute]] = accu[item.attributes[effectiveAttribute]] + 1;
4467
4436
  return accu;
4468
4437
  }, {});
4469
- return Object.entries(permissionSetObject).map(([name, { value, ...scope }]) => {
4470
- if (value.includes(excessiveAccessSelector)) {
4471
- return { name };
4472
- }
4473
- return { name, scope: { ...scope, value: value.filter(import_helpers10.duplicateFilter) } };
4474
- });
4438
+ const distributionByAttributeSorted = Object.entries(distributionByAttribute).sort((pairA, pairB) => pairB[1] - pairA[1]);
4439
+ const items = distributionByAttributeSorted.map(([key, count]) => ({ key, count }));
4440
+ const dataCount = items.reduce((accu, item) => accu + item.count, 0);
4441
+ const otherCount = (groups[group] ? total : totalDeviceCount) - dataCount;
4442
+ return { items, otherCount, total: otherCount + dataCount };
4475
4443
  };
4476
- var transformRoleDataToRole = (roleData, roleState = {}) => {
4477
- const role = { ...roleState, ...roleData };
4478
- const { description = "", name, uiPermissions = emptyUiPermissions } = role;
4479
- const { maybeUiPermissions, remainderKeys } = Object.entries(emptyUiPermissions).reduce(
4480
- (accu, [key, emptyPermissions]) => {
4481
- if (!scopedPermissionAreas[key]) {
4482
- accu.remainderKeys.push(key);
4483
- } else if (uiPermissions[key]) {
4484
- accu.maybeUiPermissions[key] = uiPermissions[key].reduce(itemUiPermissionsReducer, emptyPermissions);
4485
- }
4486
- return accu;
4487
- },
4488
- { maybeUiPermissions: {}, remainderKeys: [] }
4489
- );
4490
- const { permissionSetsWithScope, roleUiPermissions } = remainderKeys.reduce(
4491
- (accu, area) => {
4492
- const areaPermissions = role.uiPermissions[area];
4493
- if (!Array.isArray(areaPermissions)) {
4494
- return accu;
4495
- }
4496
- const impliedPermissions = deriveImpliedAreaPermissions(area, areaPermissions);
4497
- accu.roleUiPermissions[area] = impliedPermissions;
4498
- const mappedPermissions = impliedPermissions.map((uiPermission) => ({ name: uiPermissionsById[uiPermission].permissionSets[area] }));
4499
- accu.permissionSetsWithScope.push(...mappedPermissions);
4500
- return accu;
4501
- },
4502
- { permissionSetsWithScope: [{ name: defaultPermissionSets.Basic.name }], roleUiPermissions: {} }
4503
- );
4504
- const scopedPermissionSets = Object.values(scopedPermissionAreas).reduce((accu, { key, excessiveAccessSelector }) => {
4505
- if (!uiPermissions[key]) {
4506
- return accu;
4444
+ var deriveReportsData = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/deriveReportsData`, (_, { dispatch, getState }) => {
4445
+ const state = getState();
4446
+ const {
4447
+ groups: { byId: groupsById },
4448
+ byId,
4449
+ byStatus: {
4450
+ accepted: { total }
4507
4451
  }
4508
- accu.push(...transformAreaRoleDataToScopedPermissionsSets(key, uiPermissions[key], excessiveAccessSelector));
4509
- return accu;
4510
- }, []);
4511
- return {
4512
- permissionSetsWithScope: [...permissionSetsWithScope, ...scopedPermissionSets],
4513
- role: {
4514
- ...emptyRole,
4515
- name,
4516
- // @ts-ignore
4517
- description: description ? description : roleState.description,
4518
- uiPermissions: {
4519
- ...emptyUiPermissions,
4520
- ...roleUiPermissions,
4521
- ...maybeUiPermissions
4522
- }
4452
+ } = state.devices;
4453
+ const reports = getUserSettings(state).reports || state.users.globalSettings[`${state.users.currentUser}-reports`] || (Object.keys(byId).length ? defaultReports : []);
4454
+ const newReports = reports.map((report) => initializeDistributionData(report, groupsById, byId, total));
4455
+ return Promise.resolve(dispatch(actions3.setDeviceReports(newReports)));
4456
+ });
4457
+ var getReportsDataWithoutBackendSupport = (0, import_toolkit21.createAsyncThunk)(
4458
+ `${sliceName3}/getReportsDataWithoutBackendSupport`,
4459
+ (_, { dispatch, getState }) => Promise.all([dispatch(getAllDevicesByStatus(DEVICE_STATES.accepted)), dispatch(getGroups2()), dispatch(getDynamicGroups())]).then(() => {
4460
+ const { dynamic: dynamicGroups, static: staticGroups } = getGroups(getState());
4461
+ return Promise.all([
4462
+ ...staticGroups.map(({ groupId }) => dispatch(getAllGroupDevices(groupId))),
4463
+ ...dynamicGroups.map(({ groupId }) => dispatch(getAllDynamicGroupDevices(groupId)))
4464
+ ]).then(() => dispatch(deriveReportsData()));
4465
+ })
4466
+ );
4467
+ var getDeviceConnect = (0, import_toolkit21.createAsyncThunk)(
4468
+ `${sliceName3}/getDeviceConnect`,
4469
+ (id, { dispatch }) => general_api_default.get(`${deviceConnect}/devices/${id}`).then(
4470
+ ({ data }) => Promise.all([dispatch(actions3.receivedDevice({ connect_status: data.status, connect_updated_ts: data.updated_ts, id })), Promise.resolve(data)])
4471
+ )
4472
+ );
4473
+ var updateTypeMap = { deploymentUpdate: "check-update", inventoryUpdate: "send-inventory" };
4474
+ var triggerDeviceUpdate = (0, import_toolkit21.createAsyncThunk)(
4475
+ `${sliceName3}/triggerDeviceUpdate`,
4476
+ ({ id, type }, { dispatch }) => general_api_default.post(`${deviceConnect}/devices/${id}/${updateTypeMap[type] ?? updateTypeMap.deploymentUpdate}`).then(
4477
+ () => new Promise((resolve) => setTimeout(() => resolve(dispatch(getDeviceById2(id))), TIMEOUTS.threeSeconds))
4478
+ )
4479
+ );
4480
+ var getSessionDetails = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getSessionDetails`, ({ sessionId, deviceId, userId, startDate, endDate }) => {
4481
+ const { start: startUnix, end: endUnix } = (0, import_helpers10.dateRangeToUnix)(startDate, endDate);
4482
+ const createdAfter = startDate ? `&created_after=${startUnix}` : "";
4483
+ const createdBefore = endDate ? `&created_before=${endUnix}` : "";
4484
+ const objectSearch = `&object_id=${deviceId}`;
4485
+ return general_api_default.get(`${auditLogsApiUrl}/logs?per_page=500${createdAfter}${createdBefore}&actor_id=${userId}${objectSearch}`).then(
4486
+ ({ data: auditLogEntries }) => {
4487
+ const { start, end } = auditLogEntries.reduce(
4488
+ (accu, item) => {
4489
+ if (item.meta?.session_id?.includes(sessionId)) {
4490
+ accu.start = new Date(item.action.startsWith("open") ? item.time : accu.start);
4491
+ accu.end = new Date(item.action.startsWith("close") ? item.time : accu.end);
4492
+ }
4493
+ return accu;
4494
+ },
4495
+ { start: startDate || endDate, end: endDate || startDate }
4496
+ );
4497
+ return Promise.resolve({ start, end });
4523
4498
  }
4524
- };
4525
- };
4526
- var roleActions = {
4527
- create: {
4528
- successMessage: "The role was created successfully.",
4529
- errorMessage: "creating"
4530
- },
4531
- edit: {
4532
- successMessage: "The role has been updated.",
4533
- errorMessage: "editing"
4534
- },
4535
- remove: {
4536
- successMessage: "The role was deleted successfully.",
4537
- errorMessage: "removing"
4538
- }
4539
- };
4540
- var roleActionErrorHandler = (err, type, dispatch) => commonErrorHandler(err, `There was an error ${roleActions[type].errorMessage} the role.`, dispatch);
4541
- var createRole = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/createRole`, (roleData, { dispatch }) => {
4542
- const { permissionSetsWithScope, role } = transformRoleDataToRole(roleData);
4543
- return general_api_default.post(`${useradmApiUrlv2}/roles`, {
4544
- name: role.name,
4545
- description: role.description,
4546
- permission_sets_with_scope: permissionSetsWithScope
4547
- }).then(() => Promise.all([dispatch(actions8.createdRole(role)), dispatch(getRoles()), dispatch(setSnackbar4(roleActions.create.successMessage))])).catch((err) => roleActionErrorHandler(err, "create", dispatch));
4499
+ );
4548
4500
  });
4549
- var editRole = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/editRole`, (roleData, { dispatch, getState }) => {
4550
- const { permissionSetsWithScope, role } = transformRoleDataToRole(roleData, getRolesById(getState())[roleData.name]);
4551
- return general_api_default.put(`${useradmApiUrlv2}/roles/${role.name}`, {
4552
- description: role.description,
4553
- name: role.name,
4554
- permission_sets_with_scope: permissionSetsWithScope
4555
- }).then(() => Promise.all([dispatch(actions8.createdRole(role)), dispatch(getRoles()), dispatch(setSnackbar4(roleActions.edit.successMessage))])).catch((err) => roleActionErrorHandler(err, "edit", dispatch));
4501
+ var getDeviceFileDownloadLink = (0, import_toolkit21.createAsyncThunk)(
4502
+ `${sliceName3}/getDeviceFileDownloadLink`,
4503
+ ({ deviceId, path }) => Promise.resolve(`${window.location.origin}${deviceConnect}/devices/${deviceId}/download?path=${encodeURIComponent(path)}`)
4504
+ );
4505
+ var deviceFileUpload = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/deviceFileUpload`, ({ deviceId, path, file }, { dispatch }) => {
4506
+ let formData = new FormData();
4507
+ formData.append("path", path);
4508
+ formData.append("file", file);
4509
+ const uploadId = (0, import_uuid.v4)();
4510
+ const cancelSource = new AbortController();
4511
+ return Promise.all([
4512
+ dispatch(setSnackbar4("Uploading file")),
4513
+ dispatch(initUpload({ id: uploadId, upload: { inprogress: true, uploadProgress: 0, cancelSource } })),
4514
+ general_api_default.uploadPut(
4515
+ `${deviceConnect}/devices/${deviceId}/upload`,
4516
+ formData,
4517
+ (e) => dispatch(uploadProgress2({ id: uploadId, progress: progress(e) })),
4518
+ cancelSource.signal
4519
+ )
4520
+ ]).then(() => Promise.resolve(dispatch(setSnackbar4("Upload successful", TIMEOUTS.fiveSeconds)))).catch((err) => {
4521
+ if ((0, import_axios3.isCancel)(err)) {
4522
+ return dispatch(setSnackbar4("The upload has been cancelled", TIMEOUTS.fiveSeconds));
4523
+ }
4524
+ return commonErrorHandler(err, `Error uploading file to device.`, dispatch);
4525
+ }).finally(() => dispatch(cleanUpUpload(uploadId)));
4526
+ });
4527
+ var getDeviceAuth = (0, import_toolkit21.createAsyncThunk)(
4528
+ `${sliceName3}/getDeviceAuth`,
4529
+ (id, { dispatch }) => dispatch(getDevicesWithAuth([{ id }])).unwrap().then((results) => {
4530
+ if (results[results.length - 1]) {
4531
+ return Promise.resolve(results[results.length - 1][0]);
4532
+ }
4533
+ return Promise.resolve();
4534
+ })
4535
+ );
4536
+ var getDevicesWithAuth = (0, import_toolkit21.createAsyncThunk)(
4537
+ `${sliceName3}/getDevicesWithAuth`,
4538
+ (devices, { dispatch, getState }) => devices.length ? general_api_default.get(`${deviceAuthV2}/devices?id=${devices.map((device) => device.id).join("&id=")}`).then(({ data: receivedDevices }) => {
4539
+ const { devicesById } = reduceReceivedDevices(receivedDevices, [], getState());
4540
+ return Promise.all([dispatch(actions3.receivedDevices(devicesById)), Promise.resolve(receivedDevices)]);
4541
+ }).catch((err) => commonErrorHandler(err, `Error: ${err}`, dispatch)) : Promise.resolve([[], []])
4542
+ );
4543
+ var updateDeviceAuth = (0, import_toolkit21.createAsyncThunk)(
4544
+ `${sliceName3}/updateDeviceAuth`,
4545
+ ({ deviceId, authId, status }, { dispatch, getState }) => general_api_default.put(`${deviceAuthV2}/devices/${deviceId}/auth/${authId}/status`, { status }).then(() => Promise.all([dispatch(getDeviceAuth(deviceId)), dispatch(setSnackbar4("Device authorization status was updated successfully"))])).catch((err) => commonErrorHandler(err, "There was a problem updating the device authorization status:", dispatch)).then(() => Promise.resolve(dispatch(actions3.maybeUpdateDevicesByStatus({ deviceId, authId })))).finally(() => dispatch(setDeviceListState({ refreshTrigger: !getDeviceListState(getState()).refreshTrigger })))
4546
+ );
4547
+ var updateDevicesAuth = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/updateDevicesAuth`, ({ deviceIds, status }, { dispatch, getState }) => {
4548
+ let devices = getDevicesById(getState());
4549
+ const deviceIdsWithoutAuth = deviceIds.reduce((accu, id) => devices[id].auth_sets ? accu : [...accu, { id }], []);
4550
+ return dispatch(getDevicesWithAuth(deviceIdsWithoutAuth)).then(() => {
4551
+ devices = getDevicesById(getState());
4552
+ const deviceAuthUpdates = deviceIds.map((id) => {
4553
+ const device = devices[id];
4554
+ if (device.auth_sets.length !== 1) {
4555
+ return Promise.reject();
4556
+ }
4557
+ return dispatch(updateDeviceAuth({ authId: device.auth_sets[0].id, deviceId: device.id, status })).unwrap().catch((err) => commonErrorHandler(err, "The action was stopped as there was a problem updating a device authorization status: ", dispatch, "", false));
4558
+ });
4559
+ return Promise.allSettled(deviceAuthUpdates).then((results) => {
4560
+ const { skipped, count } = results.reduce(
4561
+ (accu, item) => {
4562
+ if (item.status === "rejected") {
4563
+ accu.skipped = accu.skipped + 1;
4564
+ } else {
4565
+ accu.count = accu.count + 1;
4566
+ }
4567
+ return accu;
4568
+ },
4569
+ { skipped: 0, count: 0 }
4570
+ );
4571
+ const message = (0, import_helpers10.getSnackbarMessage)(skipped, count);
4572
+ return dispatch(setSnackbar4(message));
4573
+ });
4574
+ });
4556
4575
  });
4557
- var removeRole = (0, import_toolkit21.createAsyncThunk)(
4558
- `${sliceName8}/removeRole`,
4559
- (roleId, { dispatch }) => (
4560
- // @ts-ignore
4561
- general_api_default.delete(`${useradmApiUrlv2}/roles/${roleId}`).then(() => Promise.all([dispatch(actions8.removedRole(roleId)), dispatch(getRoles()), dispatch(setSnackbar4(roleActions.remove.successMessage))])).catch((err) => roleActionErrorHandler(err, "remove", dispatch))
4562
- )
4576
+ var deleteAuthset = (0, import_toolkit21.createAsyncThunk)(
4577
+ `${sliceName3}/deleteAuthset`,
4578
+ ({ deviceId, authId }, { dispatch, getState }) => general_api_default.delete(`${deviceAuthV2}/devices/${deviceId}/auth/${authId}`).then(() => Promise.all([dispatch(setSnackbar4("Device authorization status was updated successfully"))])).catch((err) => commonErrorHandler(err, "There was a problem updating the device authorization status:", dispatch)).then(() => Promise.resolve(dispatch(actions3.maybeUpdateDevicesByStatus({ deviceId, authId })))).finally(() => dispatch(setDeviceListState({ refreshTrigger: !getState().devices.deviceList.refreshTrigger })))
4563
4579
  );
4564
- var getGlobalSettings2 = (0, import_toolkit21.createAsyncThunk)(
4565
- `${sliceName8}/getGlobalSettings`,
4566
- (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/settings`).then(({ data: settings, headers: { etag } }) => {
4567
- window.sessionStorage.setItem(settingsKeys.initialized, true);
4568
- return Promise.all([dispatch(actions8.setGlobalSettings(settings)), dispatch(setOfflineThreshold()), etag]);
4580
+ var preauthDevice = (0, import_toolkit21.createAsyncThunk)(
4581
+ `${sliceName3}/preauthDevice`,
4582
+ (authset, { dispatch, rejectWithValue }) => general_api_default.post(`${deviceAuthV2}/devices`, authset).then(() => Promise.resolve(dispatch(setSnackbar4("Device was successfully added to the preauthorization list", TIMEOUTS.fiveSeconds)))).catch((err) => {
4583
+ if (err.response.status === 409) {
4584
+ return rejectWithValue("A device with a matching identity data set already exists");
4585
+ }
4586
+ return commonErrorHandler(err, "The device could not be added:", dispatch);
4569
4587
  })
4570
4588
  );
4571
- var saveGlobalSettings = (0, import_toolkit21.createAsyncThunk)(
4572
- `${sliceName8}/saveGlobalSettings`,
4573
- // @ts-ignore
4574
- ({ beOptimistic = false, notify = false, ...settings }, { dispatch, getState }) => {
4575
- if (!window.sessionStorage.getItem(settingsKeys.initialized) && !beOptimistic) {
4576
- return;
4589
+ var decommissionDevice = (0, import_toolkit21.createAsyncThunk)(
4590
+ `${sliceName3}/decommissionDevice`,
4591
+ ({ deviceId, authId }, { dispatch, getState }) => general_api_default.delete(`${deviceAuthV2}/devices/${deviceId}`).then(() => Promise.resolve(dispatch(setSnackbar4("Device was decommissioned successfully")))).catch((err) => commonErrorHandler(err, "There was a problem decommissioning the device:", dispatch)).then(() => Promise.resolve(dispatch(actions3.maybeUpdateDevicesByStatus({ deviceId, authId })))).finally(() => dispatch(setDeviceListState({ refreshTrigger: !getState().devices.deviceList.refreshTrigger })))
4592
+ );
4593
+ var getDeviceConfig = (0, import_toolkit21.createAsyncThunk)(
4594
+ `${sliceName3}/getDeviceConfig`,
4595
+ (deviceId, { dispatch }) => general_api_default.get(`${deviceConfig}/${deviceId}`).then(({ data }) => Promise.all([dispatch(actions3.receivedDevice({ id: deviceId, config: data })), Promise.resolve(data)])).catch((err) => {
4596
+ if (err.response?.data?.error.status_code !== 404) {
4597
+ return commonErrorHandler(err, `There was an error retrieving the configuration for device ${deviceId}.`, dispatch, commonErrorFallback);
4577
4598
  }
4578
- return dispatch(getGlobalSettings2()).unwrap().then((result) => {
4579
- let updatedSettings = { ...getState().users.globalSettings, ...settings };
4580
- if (getCurrentUser(getState()).verified) {
4581
- updatedSettings["2fa"] = twoFAStates.enabled;
4582
- } else {
4583
- delete updatedSettings["2fa"];
4584
- }
4585
- let tasks = [dispatch(actions8.setGlobalSettings(updatedSettings))];
4586
- const headers = result[result.length - 1] ? { "If-Match": result[result.length - 1] } : {};
4587
- return general_api_default.post(`${useradmApiUrlv1}/settings`, updatedSettings, { headers }).then(() => {
4588
- if (notify) {
4589
- tasks.push(dispatch(setSnackbar4("Settings saved successfully")));
4590
- }
4591
- return Promise.all(tasks);
4592
- }).catch((err) => {
4593
- if (beOptimistic) {
4594
- return Promise.all([tasks]);
4595
- }
4596
- console.log(err);
4597
- return commonErrorHandler(err, `The settings couldn't be saved.`, dispatch);
4598
- });
4599
- });
4600
- }
4599
+ })
4601
4600
  );
4602
- var getUserSettings2 = (0, import_toolkit21.createAsyncThunk)(
4603
- `${sliceName8}/getUserSettings`,
4604
- (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/settings/me`).then(({ data: settings, headers: { etag } }) => {
4605
- window.sessionStorage.setItem(settingsKeys.initialized, true);
4606
- return Promise.all([dispatch(actions8.setUserSettings(settings)), etag]);
4601
+ var setDeviceConfig = (0, import_toolkit21.createAsyncThunk)(
4602
+ `${sliceName3}/setDeviceConfig`,
4603
+ ({ deviceId, config }, { dispatch }) => general_api_default.put(`${deviceConfig}/${deviceId}`, config).catch((err) => commonErrorHandler(err, `There was an error setting the configuration for device ${deviceId}.`, dispatch, commonErrorFallback)).then(() => Promise.resolve(dispatch(getDeviceConfig(deviceId))))
4604
+ );
4605
+ var applyDeviceConfig = (0, import_toolkit21.createAsyncThunk)(
4606
+ `${sliceName3}/applyDeviceConfig`,
4607
+ ({ deviceId, configDeploymentConfiguration, isDefault, config }, { dispatch, getState }) => general_api_default.post(`${deviceConfig}/${deviceId}/deploy`, configDeploymentConfiguration).catch((err) => commonErrorHandler(err, `There was an error deploying the configuration to device ${deviceId}.`, dispatch, commonErrorFallback)).then(({ data }) => {
4608
+ const device = getDeviceById(getState(), deviceId);
4609
+ const { canManageUsers } = getUserCapabilities(getState());
4610
+ let tasks = [
4611
+ dispatch(actions3.receivedDevice({ ...device, config: { ...device.config, deployment_id: data.deployment_id } })),
4612
+ new Promise((resolve) => setTimeout(() => resolve(dispatch(getSingleDeployment(data.deployment_id))), TIMEOUTS.oneSecond))
4613
+ ];
4614
+ if (isDefault && canManageUsers) {
4615
+ const { previous } = getGlobalSettings(getState()).defaultDeviceConfig ?? {};
4616
+ tasks.push(dispatch(saveGlobalSettings({ defaultDeviceConfig: { current: config, previous } })));
4617
+ }
4618
+ return Promise.all(tasks);
4607
4619
  })
4608
4620
  );
4609
- var saveUserSettings = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/saveUserSettings`, (settings = { onboarding: {} }, { dispatch, getState }) => {
4610
- if (!getCurrentUser(getState()).id) {
4611
- return Promise.resolve();
4612
- }
4613
- return dispatch(getUserSettings2()).unwrap().then((result) => {
4614
- const userSettings = getUserSettings(getState());
4615
- const onboardingState = getOnboardingState(getState());
4616
- const tooltipState = getTooltipsState(getState());
4617
- const updatedSettings = {
4618
- ...userSettings,
4619
- // @ts-ignore
4620
- ...settings,
4621
- onboarding: {
4622
- ...onboardingState,
4623
- // @ts-ignore
4624
- ...settings.onboarding
4625
- },
4626
- tooltips: tooltipState
4621
+ var setDeviceTags = (0, import_toolkit21.createAsyncThunk)(
4622
+ `${sliceName3}/setDeviceTags`,
4623
+ ({ deviceId, tags }, { dispatch }) => (
4624
+ // to prevent tag set failures, retrieve the device & use the freshest etag we can get
4625
+ Promise.resolve(dispatch(getDeviceById2(deviceId))).then((device) => {
4626
+ const headers = device.etag ? { "If-Match": device.etag } : {};
4627
+ return general_api_default.put(
4628
+ `${inventoryApiUrl}/devices/${deviceId}/tags`,
4629
+ Object.entries(tags).map(([name, value]) => ({ name, value })),
4630
+ { headers }
4631
+ ).catch((err) => commonErrorHandler(err, `There was an error setting tags for device ${deviceId}.`, dispatch, "Please check your connection.")).then(() => Promise.all([dispatch(actions3.receivedDevice({ ...device, id: deviceId, tags })), dispatch(setSnackbar4("Device name changed"))]));
4632
+ })
4633
+ )
4634
+ );
4635
+ var getDeviceTwin = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getDeviceTwin`, ({ deviceId, integration }, { dispatch, getState }) => {
4636
+ let providerResult = {};
4637
+ return general_api_default.get(`${iotManagerBaseURL}/devices/${deviceId}/state`).then(({ data }) => {
4638
+ providerResult = { ...data, twinError: "" };
4639
+ }).catch((err) => {
4640
+ providerResult = {
4641
+ twinError: `There was an error getting the ${EXTERNAL_PROVIDER[integration.provider].twinTitle.toLowerCase()} for device ${deviceId}. ${err}`
4627
4642
  };
4628
- const headers = result[result.length - 1] ? { "If-Match": result[result.length - 1] } : {};
4629
- return Promise.all([
4630
- Promise.resolve(dispatch(actions8.setUserSettings(updatedSettings))),
4631
- general_api_default.post(`${useradmApiUrlv1}/settings/me`, updatedSettings, { headers })
4632
- ]).catch(() => dispatch(actions8.setUserSettings(userSettings)));
4643
+ }).finally(() => {
4644
+ const device = getDeviceById(getState(), deviceId);
4645
+ Promise.resolve(dispatch(actions3.receivedDevice({ ...device, twinsByIntegration: { ...device.twinsByIntegration, ...providerResult } })));
4633
4646
  });
4634
4647
  });
4635
- var get2FAQRCode = (0, import_toolkit21.createAsyncThunk)(
4636
- `${sliceName8}/get2FAQRCode`,
4637
- (_, { dispatch }) => general_api_default.get(`${useradmApiUrlv1}/2faqr`).then((res) => dispatch(actions8.receivedQrCode(res.data.qr)))
4638
- );
4639
- var setHideAnnouncement = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/setHideAnnouncement`, ({ shouldHide, userId }, { dispatch, getState }) => {
4640
- const currentUserId = userId || getCurrentUser(getState()).id;
4641
- const hash = getState().app.hostedAnnouncement ? (0, import_md5.default)(getState().app.hostedAnnouncement) : "";
4642
- const announceCookie = cookies3.get(`${currentUserId}${hash}`);
4643
- if (shouldHide || hash.length && typeof announceCookie !== "undefined") {
4644
- cookies3.set(`${currentUserId}${hash}`, true, { maxAge: 604800 });
4645
- return Promise.resolve(dispatch(setAnnouncement()));
4646
- }
4647
- return Promise.resolve();
4648
- });
4649
- var getTokens = (0, import_toolkit21.createAsyncThunk)(
4650
- `${sliceName8}/getTokens`,
4651
- (_, { dispatch, getState }) => general_api_default.get(`${useradmApiUrlv1}/settings/tokens`).then(({ data: tokens }) => {
4652
- const user = getCurrentUser(getState());
4653
- const updatedUser = {
4654
- ...user,
4655
- tokens
4656
- };
4657
- return Promise.resolve(dispatch(actions8.updatedUser(updatedUser)));
4648
+ var setDeviceTwin = (0, import_toolkit21.createAsyncThunk)(
4649
+ `${sliceName3}/setDeviceTwin`,
4650
+ ({ deviceId, integration, settings }, { dispatch, getState }) => general_api_default.put(`${iotManagerBaseURL}/devices/${deviceId}/state/${integration.id}`, { desired: settings }).catch(
4651
+ (err) => commonErrorHandler(
4652
+ err,
4653
+ `There was an error updating the ${EXTERNAL_PROVIDER[integration.provider].twinTitle.toLowerCase()} for device ${deviceId}.`,
4654
+ dispatch
4655
+ )
4656
+ ).then(() => {
4657
+ const device = getDeviceById(getState(), deviceId);
4658
+ const { twinsByIntegration = {} } = device;
4659
+ const { [integration.id]: currentState = {} } = twinsByIntegration;
4660
+ return Promise.resolve(
4661
+ dispatch(actions3.receivedDevice({ ...device, twinsByIntegration: { ...twinsByIntegration, [integration.id]: { ...currentState, desired: settings } } }))
4662
+ );
4658
4663
  })
4659
4664
  );
4660
- var ONE_YEAR = 31536e3;
4661
- var generateToken = (0, import_toolkit21.createAsyncThunk)(
4662
- `${sliceName8}/generateToken`,
4663
- ({ expiresIn = ONE_YEAR, name }, { dispatch }) => general_api_default.post(`${useradmApiUrlv1}/settings/tokens`, { name, expires_in: expiresIn }).then(({ data: token }) => Promise.all([dispatch(getTokens()), token])).catch((err) => commonErrorHandler(err, "There was an error creating the token:", dispatch))
4664
- );
4665
- var revokeToken = (0, import_toolkit21.createAsyncThunk)(
4666
- `${sliceName8}/revokeToken`,
4667
- (token, { dispatch }) => (
4668
- // @ts-ignore
4669
- general_api_default.delete(`${useradmApiUrlv1}/settings/tokens/${token.id}`).then(() => Promise.resolve(dispatch(getTokens())))
4670
- )
4671
- );
4672
- var setTooltipReadState = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/setTooltipReadState`, ({ persist, ...remainder }, { dispatch }) => {
4673
- let tasks = [dispatch(actions8.setTooltipState(remainder))];
4674
- if (persist) {
4675
- tasks.push(dispatch(saveUserSettings()));
4665
+ var prepareSearchArguments = ({ filters, group, state, status }) => {
4666
+ const { filterTerms } = convertDeviceListStateToFilters({ filters, group, offlineThreshold: state.app.offlineThreshold, selectedIssues: [], status });
4667
+ const { columnSelection = [] } = getUserSettings(state);
4668
+ const selectedAttributes = columnSelection.map((column) => ({ attribute: column.key, scope: column.scope }));
4669
+ const attributes = [...defaultAttributes, getIdAttribute(state), ...selectedAttributes];
4670
+ return { attributes, filterTerms };
4671
+ };
4672
+ var getSystemDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getSystemDevices`, (options, { dispatch, getState }) => {
4673
+ const { id, page = defaultPage3, perPage = defaultPerPage3, sortOptions = [] } = options;
4674
+ const state = getState();
4675
+ const { hasFullFiltering } = getTenantCapabilities(state);
4676
+ if (!hasFullFiltering) {
4677
+ return Promise.resolve();
4676
4678
  }
4677
- return Promise.all(tasks);
4679
+ const { attributes: deviceAttributes = {} } = getDeviceById(state, id);
4680
+ const { mender_gateway_system_id = "" } = deviceAttributes;
4681
+ const filters = [
4682
+ { ...emptyFilter, key: "mender_is_gateway", operator: DEVICE_FILTERING_OPTIONS.$ne.key, value: "true", scope: "inventory" },
4683
+ { ...emptyFilter, key: "mender_gateway_system_id", value: mender_gateway_system_id, scope: "inventory" }
4684
+ ];
4685
+ const { attributes, filterTerms } = prepareSearchArguments({ filters, state });
4686
+ return general_api_default.post(getSearchEndpoint(getState()), {
4687
+ page,
4688
+ per_page: perPage,
4689
+ filters: filterTerms,
4690
+ sort: sortOptions,
4691
+ attributes
4692
+ }).catch((err) => commonErrorHandler(err, `There was an error getting system devices device ${id}.`, dispatch, "Please check your connection.")).then(({ data, headers }) => {
4693
+ const state2 = getState();
4694
+ const { devicesById, ids } = reduceReceivedDevices(data, [], state2);
4695
+ const device = {
4696
+ ...getDeviceById(state2, id),
4697
+ systemDeviceIds: ids,
4698
+ systemDeviceTotal: Number(headers[headerNames.total])
4699
+ };
4700
+ return Promise.resolve(dispatch(actions3.receivedDevices({ ...devicesById, [id]: device })));
4701
+ });
4678
4702
  });
4679
- var setAllTooltipsReadState = (0, import_toolkit21.createAsyncThunk)(`${sliceName8}/toggleHelptips`, ({ readState = READ_STATES.read, tooltips }, { dispatch }) => {
4680
- const updatedTips = tooltips.reduce((accu, id) => ({ ...accu, [id]: { readState } }), {});
4681
- return Promise.resolve(dispatch(actions8.setTooltipsState(updatedTips))).then(() => dispatch(saveUserSettings()));
4703
+ var getGatewayDevices = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getGatewayDevices`, (deviceId, { dispatch, getState }) => {
4704
+ const state = getState();
4705
+ const { attributes = {} } = getDeviceById(state, deviceId);
4706
+ const { mender_gateway_system_id = "" } = attributes;
4707
+ const filters = [
4708
+ { ...emptyFilter, key: "id", operator: DEVICE_FILTERING_OPTIONS.$ne.key, value: deviceId, scope: "identity" },
4709
+ { ...emptyFilter, key: "mender_is_gateway", value: "true", scope: "inventory" },
4710
+ { ...emptyFilter, key: "mender_gateway_system_id", value: mender_gateway_system_id, scope: "inventory" }
4711
+ ];
4712
+ const { attributes: attributeSelection, filterTerms } = prepareSearchArguments({ filters, state });
4713
+ return general_api_default.post(getSearchEndpoint(getState()), {
4714
+ page: 1,
4715
+ per_page: MAX_PAGE_SIZE,
4716
+ filters: filterTerms,
4717
+ attributes: attributeSelection
4718
+ }).then(({ data }) => {
4719
+ const { ids } = reduceReceivedDevices(data, [], getState());
4720
+ let tasks = ids.map((deviceId2) => dispatch(getDeviceInfo(deviceId2)));
4721
+ tasks.push(dispatch(actions3.receivedDevice({ id: deviceId, gatewayIds: ids })));
4722
+ return Promise.all(tasks);
4723
+ });
4724
+ });
4725
+ var getDevicesInBounds = (0, import_toolkit21.createAsyncThunk)(`${sliceName3}/getDevicesInBounds`, ({ bounds, group }, { dispatch, getState }) => {
4726
+ const state = getState();
4727
+ const { filterTerms } = convertDeviceListStateToFilters({
4728
+ group: group === ALL_DEVICES ? void 0 : group,
4729
+ groups: state.devices.groups,
4730
+ status: DEVICE_STATES.accepted
4731
+ });
4732
+ return general_api_default.post(getSearchEndpoint(getState()), {
4733
+ page: 1,
4734
+ per_page: MAX_PAGE_SIZE,
4735
+ filters: filterTerms,
4736
+ attributes: geoAttributes,
4737
+ geo_bounding_box_filter: {
4738
+ geo_bounding_box: {
4739
+ location: {
4740
+ top_left: { lat: bounds._northEast.lat, lon: bounds._southWest.lng },
4741
+ bottom_right: { lat: bounds._southWest.lat, lon: bounds._northEast.lng }
4742
+ }
4743
+ }
4744
+ }
4745
+ }).then(({ data }) => {
4746
+ const { devicesById } = reduceReceivedDevices(data, [], getState());
4747
+ return Promise.resolve(dispatch(actions3.receivedDevices(devicesById)));
4748
+ });
4682
4749
  });
4683
- var submitFeedback = (0, import_toolkit21.createAsyncThunk)(
4684
- `${sliceName8}/submitFeedback`,
4685
- // @ts-ignore
4686
- ({ satisfaction, feedback, ...meta }, { dispatch }) => {
4687
- return general_api_default.post(`${tenantadmApiUrlv2}/contact/support`, {
4688
- subject: "feedback submission",
4689
- body: JSON.stringify({ feedback, satisfaction, meta })
4690
- }).then(() => {
4691
- const today = /* @__PURE__ */ new Date();
4692
- dispatch(saveUserSettings({ feedbackCollectedAt: today.toISOString().split("T")[0] }));
4693
- setTimeout(() => dispatch(actions8.setShowFeedbackDialog(false)), TIMEOUTS.threeSeconds);
4694
- });
4695
- }
4696
- );
4697
4750
 
4698
4751
  // src/organizationSlice/thunks.ts
4699
4752
  var import_helpers11 = require("@northern.tech/utils/helpers");
@@ -4770,7 +4823,7 @@ var startUpgrade = (0, import_toolkit22.createAsyncThunk)(
4770
4823
  var cancelUpgrade = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/cancelUpgrade`, (tenantId) => general_api_default.post(`${tenantadmApiUrlv2}/tenants/${tenantId}/upgrade/cancel`));
4771
4824
  var completeUpgrade = (0, import_toolkit22.createAsyncThunk)(
4772
4825
  `${sliceName6}/completeUpgrade`,
4773
- ({ tenantId, plan }, { dispatch }) => general_api_default.post(`${tenantadmApiUrlv2}/tenants/${tenantId}/upgrade/complete`, { plan }).catch((err) => commonErrorHandler(err, `There was an error upgrading your account:`, dispatch)).then(() => Promise.resolve(dispatch(getUserOrganization())))
4826
+ ({ tenantId, plan, billing_profile }, { dispatch }) => general_api_default.post(`${tenantadmApiUrlv2}/tenants/${tenantId}/upgrade/complete`, { plan, billing_profile }).catch((err) => commonErrorHandler(err, `There was an error upgrading your account:`, dispatch)).then(() => Promise.all([dispatch(getDeviceLimit2()), dispatch(getUserOrganization())]))
4774
4827
  );
4775
4828
  var prepareAuditlogQuery = ({ startDate, endDate, user: userFilter, type, detail: detailFilter, sort = {} }) => {
4776
4829
  const userId = userFilter?.id || userFilter;
@@ -4819,7 +4872,12 @@ var setAuditlogsState = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/se
4819
4872
  });
4820
4873
  var tenantDataDivergedMessage = "The system detected there is a change in your plan or purchased add-ons. Please log out and log in again";
4821
4874
  var addTenant = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/createTenant`, (selectionState, { dispatch }) => {
4822
- return general_api_default.post(`${tenantadmApiUrlv2}/tenants`, selectionState).then(() => Promise.all([dispatch(getTenants()), dispatch(setSnackbar5("Tenant was created successfully."))])).catch((err) => commonErrorHandler(err, "There was an error creating tenant", dispatch, commonErrorFallback));
4875
+ return general_api_default.post(`${tenantadmApiUrlv2}/tenants`, selectionState).then(
4876
+ () => Promise.all([
4877
+ dispatch(setSnackbar5("Tenant was created successfully.")),
4878
+ new Promise((resolve) => setTimeout(() => resolve(dispatch(getTenants())), TIMEOUTS.oneSecond))
4879
+ ])
4880
+ ).catch((err) => commonErrorHandler(err, "There was an error creating tenant", dispatch, commonErrorFallback));
4823
4881
  });
4824
4882
  var tenantListRetrieval = async (config) => {
4825
4883
  const { page, perPage } = config;
@@ -4847,15 +4905,20 @@ var setTenantsListState = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/
4847
4905
  });
4848
4906
  var editTenantDeviceLimit = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/editDeviceLimit`, ({ newLimit, id, name }, { dispatch }) => {
4849
4907
  return general_api_default.put(`${tenantadmApiUrlv2}/tenants/${id}/child`, { device_limit: newLimit, name }).catch((err) => commonErrorHandler(err, `Device Limit cannot be changed`, dispatch)).then(() => {
4850
- const tasks = [Promise.resolve(dispatch(setSnackbar5("Device Limit was changed successfully")))];
4851
- tasks.push(dispatch(getTenants()));
4852
- tasks.push(dispatch(getUserOrganization()));
4853
- return Promise.all(tasks);
4908
+ return Promise.all([
4909
+ dispatch(setSnackbar5("Device Limit was changed successfully")),
4910
+ dispatch(getUserOrganization()),
4911
+ new Promise((resolve) => setTimeout(() => resolve(dispatch(getTenants())), TIMEOUTS.oneSecond))
4912
+ ]);
4854
4913
  });
4855
4914
  });
4856
4915
  var removeTenant = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/editDeviceLimit`, ({ id }, { dispatch }) => {
4857
4916
  return general_api_default.post(`${tenantadmApiUrlv2}/tenants/${id}/remove/start`).catch((err) => commonErrorHandler(err, `There was an error removing the tenant`, dispatch)).then(
4858
- () => Promise.all([Promise.resolve(dispatch(setSnackbar5("Device Limit was changed successfully"))), dispatch(getTenants()), dispatch(getUserOrganization())])
4917
+ () => Promise.all([
4918
+ dispatch(setSnackbar5("The tenant was removed successfully")),
4919
+ dispatch(getUserOrganization()),
4920
+ new Promise((resolve) => setTimeout(() => resolve(dispatch(getTenants())), TIMEOUTS.oneSecond))
4921
+ ])
4859
4922
  );
4860
4923
  });
4861
4924
  var getUserOrganization = (0, import_toolkit22.createAsyncThunk)(`${sliceName6}/getUserOrganization`, (_, { dispatch, getState }) => {
@@ -4879,7 +4942,10 @@ var sendSupportMessage = (0, import_toolkit22.createAsyncThunk)(
4879
4942
  );
4880
4943
  var requestPlanChange = (0, import_toolkit22.createAsyncThunk)(
4881
4944
  `${sliceName6}/requestPlanChange`,
4882
- ({ content, tenantId }, { dispatch }) => general_api_default.post(`${tenantadmApiUrlv2}/tenants/${tenantId}/plan`, content).catch((err) => commonErrorHandler(err, "There was an error sending your request", dispatch, commonErrorFallback)).then(() => Promise.resolve(dispatch(setSnackbar5({ message: "Your request was sent successfully", autoHideDuration: TIMEOUTS.fiveSeconds }))))
4945
+ ({ content, tenantId }, { dispatch, rejectWithValue }) => general_api_default.post(`${tenantadmApiUrlv2}/tenants/${tenantId}/plan`, content).catch(async (err) => {
4946
+ await commonErrorHandler(err, "There was an error sending your request", dispatch, commonErrorFallback);
4947
+ rejectWithValue(err);
4948
+ }).then(() => Promise.resolve(dispatch(setSnackbar5({ message: "Your request was sent successfully", autoHideDuration: TIMEOUTS.fiveSeconds }))))
4883
4949
  );
4884
4950
  var downloadLicenseReport = (0, import_toolkit22.createAsyncThunk)(
4885
4951
  `${sliceName6}/downloadLicenseReport`,