mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	 d8e6ed1c5b
			
		
	
	d8e6ed1c5b
	
	
	
		
			
			* remove yarn script that no longer works in yarn 3 * delete other deprecated yarn script * add acme_clients to mirage handler and utils * consolidate client names * revert changes to homogenizeClientNaming, wait until confirmation from backend * remove flattenDataset helper * revert deleting flattendataset method (done in separate PR) * move response to helper file * cleanup utils based on test changes * add acme_clients to tests * rename variables and add comments! * refactor homogenizeClientNaming and rename * move by_namespace to test helper as well * add comments and finally delete flattenDataset * add more comments and update response to match no mounts shape * update test selector * finish updates for removing clients: null from serialized response * final comments! * remove arrayOfCounts helper * Update ui/tests/integration/components/clients/page/sync-test.js Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com> --------- Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com>
		
			
				
	
	
		
			214 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) HashiCorp, Inc.
 | |
|  * SPDX-License-Identifier: BUSL-1.1
 | |
|  */
 | |
| 
 | |
| import { parseAPITimestamp } from 'core/utils/date-formatters';
 | |
| import { compareAsc, getUnixTime, isWithinInterval } from 'date-fns';
 | |
| 
 | |
| // add new types here
 | |
| export const CLIENT_TYPES = [
 | |
|   'acme_clients',
 | |
|   'clients', // summation of total clients
 | |
|   'entity_clients',
 | |
|   'non_entity_clients',
 | |
|   'secret_syncs',
 | |
| ];
 | |
| 
 | |
| // returns array of VersionHistoryModels for noteworthy upgrades: 1.9, 1.10
 | |
| // that occurred between timestamps (i.e. queried activity data)
 | |
| export const filterVersionHistory = (versionHistory, start, end) => {
 | |
|   if (versionHistory) {
 | |
|     const upgrades = versionHistory.reduce((array, upgradeData) => {
 | |
|       const includesVersion = (v) =>
 | |
|         // only add first match, disregard subsequent patch releases of the same version
 | |
|         upgradeData.version.match(v) && !array.some((d) => d.version.match(v));
 | |
| 
 | |
|       ['1.9', '1.10'].forEach((v) => {
 | |
|         if (includesVersion(v)) array.push(upgradeData);
 | |
|       });
 | |
| 
 | |
|       return array;
 | |
|     }, []);
 | |
| 
 | |
|     // if there are noteworthy upgrades, only return those during queried date range
 | |
|     if (upgrades.length) {
 | |
|       const startDate = parseAPITimestamp(start);
 | |
|       const endDate = parseAPITimestamp(end);
 | |
|       return upgrades.filter(({ timestampInstalled }) => {
 | |
|         const upgradeDate = parseAPITimestamp(timestampInstalled);
 | |
|         return isWithinInterval(upgradeDate, { start: startDate, end: endDate });
 | |
|       });
 | |
|     }
 | |
|   }
 | |
|   return [];
 | |
| };
 | |
| 
 | |
| export const formatDateObject = (dateObj, isEnd) => {
 | |
|   if (dateObj) {
 | |
|     const { year, monthIdx } = dateObj;
 | |
|     // day=0 for Date.UTC() returns the last day of the month before
 | |
|     // increase monthIdx by one to get last day of queried month
 | |
|     const utc = isEnd ? Date.UTC(year, monthIdx + 1, 0) : Date.UTC(year, monthIdx, 1);
 | |
|     return getUnixTime(utc);
 | |
|   }
 | |
| };
 | |
| 
 | |
| export const formatByMonths = (monthsArray) => {
 | |
|   // the monthsArray will always include a timestamp of the month and either new/total client data or counts = null
 | |
|   if (!Array.isArray(monthsArray)) return monthsArray;
 | |
| 
 | |
|   const sortedPayload = sortMonthsByTimestamp(monthsArray);
 | |
|   return sortedPayload?.map((m) => {
 | |
|     const month = parseAPITimestamp(m.timestamp, 'M/yy');
 | |
|     const totalClientsByNamespace = formatByNamespace(m.namespaces);
 | |
|     const newClientsByNamespace = formatByNamespace(m.new_clients?.namespaces);
 | |
|     return {
 | |
|       month,
 | |
|       timestamp: m.timestamp,
 | |
|       ...destructureClientCounts(m?.counts),
 | |
|       namespaces: formatByNamespace(m.namespaces) || [],
 | |
|       namespaces_by_key: namespaceArrayToObject(
 | |
|         totalClientsByNamespace,
 | |
|         newClientsByNamespace,
 | |
|         month,
 | |
|         m.timestamp
 | |
|       ),
 | |
|       new_clients: {
 | |
|         month,
 | |
|         timestamp: m.timestamp,
 | |
|         ...destructureClientCounts(m?.new_clients?.counts),
 | |
|         namespaces: formatByNamespace(m.new_clients?.namespaces) || [],
 | |
|       },
 | |
|     };
 | |
|   });
 | |
| };
 | |
| 
 | |
| export const formatByNamespace = (namespaceArray) => {
 | |
|   if (!Array.isArray(namespaceArray)) return namespaceArray;
 | |
|   return namespaceArray?.map((ns) => {
 | |
|     // i.e. 'namespace_path' is an empty string for 'root', so use namespace_id
 | |
|     const label = ns.namespace_path === '' ? ns.namespace_id : ns.namespace_path;
 | |
|     // data prior to adding mount granularity will still have a mounts key,
 | |
|     // but with the value: "no mount accessor (pre-1.10 upgrade?)" (ref: vault/activity_log_util_common.go)
 | |
|     // transform to an empty array for type consistency
 | |
|     let mounts = [];
 | |
|     if (Array.isArray(ns.mounts)) {
 | |
|       mounts = ns.mounts.map((m) => ({ label: m['mount_path'], ...destructureClientCounts(m?.counts) }));
 | |
|     }
 | |
|     return {
 | |
|       label,
 | |
|       ...destructureClientCounts(ns.counts),
 | |
|       mounts,
 | |
|     };
 | |
|   });
 | |
| };
 | |
| 
 | |
| // In 1.10 'distinct_entities' changed to 'entity_clients' and 'non_entity_tokens' to 'non_entity_clients'
 | |
| // these deprecated keys still exist on the response, so only return relevant keys here
 | |
| // when querying historical data the response will always contain the latest client type keys because the activity log is
 | |
| // constructed based on the version of Vault the user is on (key values will be 0)
 | |
| export const destructureClientCounts = (verboseObject) => {
 | |
|   if (!verboseObject) return;
 | |
|   return CLIENT_TYPES.reduce((newObj, clientType) => {
 | |
|     newObj[clientType] = verboseObject[clientType];
 | |
|     return newObj;
 | |
|   }, {});
 | |
| };
 | |
| 
 | |
| export const sortMonthsByTimestamp = (monthsArray) => {
 | |
|   const sortedPayload = [...monthsArray];
 | |
|   return sortedPayload.sort((a, b) =>
 | |
|     compareAsc(parseAPITimestamp(a.timestamp), parseAPITimestamp(b.timestamp))
 | |
|   );
 | |
| };
 | |
| 
 | |
| export const namespaceArrayToObject = (totalClientsByNamespace, newClientsByNamespace, month, timestamp) => {
 | |
|   if (!totalClientsByNamespace) return {}; // return if no data for that month
 | |
|   // all 'new_client' data resides within a separate key of each month (see data structure below)
 | |
|   // FIRST: iterate and nest respective 'new_clients' data within each namespace and mount object
 | |
|   // note: this is happening within the month object
 | |
|   const nestNewClientsWithinNamespace = totalClientsByNamespace?.map((ns) => {
 | |
|     const newNamespaceCounts = newClientsByNamespace?.find((n) => n.label === ns.label);
 | |
|     if (newNamespaceCounts) {
 | |
|       const newClientsByMount = [...newNamespaceCounts.mounts];
 | |
|       const nestNewClientsWithinMounts = ns.mounts?.map((mount) => {
 | |
|         const new_clients = newClientsByMount?.find((m) => m.label === mount.label) || {};
 | |
|         return {
 | |
|           ...mount,
 | |
|           new_clients,
 | |
|         };
 | |
|       });
 | |
|       return {
 | |
|         ...ns,
 | |
|         new_clients: {
 | |
|           label: ns.label,
 | |
|           ...destructureClientCounts(newNamespaceCounts),
 | |
|           mounts: newClientsByMount,
 | |
|         },
 | |
|         mounts: [...nestNewClientsWithinMounts],
 | |
|       };
 | |
|     }
 | |
|     return {
 | |
|       ...ns,
 | |
|       new_clients: {},
 | |
|     };
 | |
|   });
 | |
|   // SECOND: create a new object (namespace_by_key) in which each namespace label is a key
 | |
|   const namespaces_by_key = {};
 | |
|   nestNewClientsWithinNamespace?.forEach((namespaceObject) => {
 | |
|     // THIRD: make another object within the namespace where each mount label is a key
 | |
|     const mounts_by_key = {};
 | |
|     namespaceObject.mounts.forEach((mountObject) => {
 | |
|       mounts_by_key[mountObject.label] = {
 | |
|         month,
 | |
|         timestamp,
 | |
|         ...mountObject,
 | |
|         new_clients: { month, ...mountObject.new_clients },
 | |
|       };
 | |
|     });
 | |
| 
 | |
|     const { label, new_clients } = namespaceObject;
 | |
|     namespaces_by_key[label] = {
 | |
|       month,
 | |
|       timestamp,
 | |
|       ...destructureClientCounts(namespaceObject),
 | |
|       new_clients: { month, ...new_clients },
 | |
|       mounts_by_key,
 | |
|     };
 | |
|   });
 | |
|   return namespaces_by_key;
 | |
|   /*
 | |
|   structure of object returned
 | |
|   namespace_by_key: {
 | |
|     "namespace_label": {
 | |
|       month: "3/22",
 | |
|       clients: 32,
 | |
|       entity_clients: 16,
 | |
|       non_entity_clients: 16,
 | |
|       new_clients: {
 | |
|         month: "3/22",
 | |
|         clients: 5,
 | |
|         entity_clients: 2,
 | |
|         non_entity_clients: 3,
 | |
|         mounts: [...array of this namespace's mounts and their new client counts],
 | |
|       },
 | |
|       mounts_by_key: {
 | |
|         "mount_label": {
 | |
|            month: "3/22",
 | |
|            clients: 3,
 | |
|            entity_clients: 2,
 | |
|            non_entity_clients: 1,
 | |
|            new_clients: {
 | |
|             month: "3/22",
 | |
|             clients: 5,
 | |
|             entity_clients: 2,
 | |
|             non_entity_clients: 3,
 | |
|           },
 | |
|         },
 | |
|       },
 | |
|     },
 | |
|   };
 | |
|   */
 | |
| };
 |