fleet/frontend/hooks/useSoftwareInstallerMeta.ts
Jahziel Villasana-Espinoza ac4ec2ff27
FMA version rollback (#40038)
- **Gitops specify FMA rollback version (#39582)**
- **Fleet UI: Show versions options for FMA installers (#39583)**
- **rollback: DB and core implementation (#39650)**

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #31919 

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)

## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [x] QA'd all new/changed functionality manually

---------

Co-authored-by: Jonathan Katz <44128041+jkatz01@users.noreply.github.com>
Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Co-authored-by: Carlo DiCelico <carlo@fleetdm.com>
2026-02-24 14:00:32 -05:00

147 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useContext, useMemo } from "react";
import { AppContext } from "context/app";
import { isAndroid } from "interfaces/platform";
import {
ISoftwareTitleDetails,
ISoftwarePackage,
IAppStoreApp,
isSoftwarePackage,
isIpadOrIphoneSoftwareSource,
InstallerType,
} from "interfaces/software";
import {
getInstallerCardInfo,
InstallerCardInfo,
} from "pages/SoftwarePage/SoftwareTitleDetailsPage/helpers";
import { compareVersions } from "utilities/helpers";
export interface SoftwareInstallerMeta {
installerType: InstallerType;
isAndroidPlayStoreApp: boolean;
isFleetMaintainedApp: boolean;
isLatestFmaVersion: boolean;
isCustomPackage: boolean;
isIosOrIpadosApp: boolean;
sha256?: string;
androidPlayStoreId?: string;
automaticInstallPolicies:
| ISoftwarePackage["automatic_install_policies"]
| IAppStoreApp["automatic_install_policies"];
gitOpsModeEnabled: boolean;
repoURL?: string;
canManageSoftware: boolean;
/** Raw ISoftwarePackage | IAppStoreApp data */
softwareInstaller: ISoftwarePackage | IAppStoreApp;
}
export interface UseSoftwareInstallerResult {
cardInfo: InstallerCardInfo;
meta: SoftwareInstallerMeta;
}
/** This is used to extract software installer data
* (FMA, VPP, Google Playstore Apps, custom packages)
* from ISoftwareTitleDetails to be used in the UI */
export const useSoftwareInstaller = (
softwareTitle: ISoftwareTitleDetails
): UseSoftwareInstallerResult | undefined => {
const appContext = useContext(AppContext);
return useMemo(() => {
if (!softwareTitle.software_package && !softwareTitle.app_store_app) {
return undefined;
}
const cardInfo = getInstallerCardInfo(softwareTitle);
const { softwareInstaller, source } = cardInfo;
const isIosOrIpadosApp = isIpadOrIphoneSoftwareSource(source);
const installerType: InstallerType = isSoftwarePackage(softwareInstaller)
? "package"
: "app-store";
const isAndroidPlayStoreApp =
"platform" in softwareInstaller && isAndroid(softwareInstaller.platform);
const isFleetMaintainedApp =
"fleet_maintained_app_id" in softwareInstaller &&
!!softwareInstaller.fleet_maintained_app_id;
const isLatestFmaVersion =
isFleetMaintainedApp &&
"fleet_maintained_versions" in softwareInstaller &&
!!softwareInstaller.fleet_maintained_versions &&
softwareInstaller.fleet_maintained_versions.every(
(fma) =>
// Verify that the installer version is not older than any known
// Fleetmaintained version by requiring compareVersions to return
// 0 (equal) or 1 (greater) for every entry.
compareVersions(softwareInstaller.version ?? "", fma.version ?? "") >=
0
);
const fmaVersions =
isFleetMaintainedApp && "fleet_maintained_versions" in softwareInstaller
? softwareInstaller.fleet_maintained_versions
: [];
const isCustomPackage =
installerType === "package" && !isFleetMaintainedApp;
const sha256 =
("hash_sha256" in softwareInstaller && softwareInstaller.hash_sha256) ||
undefined;
const androidPlayStoreId =
isAndroidPlayStoreApp && "app_store_id" in softwareInstaller
? softwareInstaller?.app_store_id
: undefined;
const {
automatic_install_policies: automaticInstallPolicies,
} = softwareInstaller;
const {
isGlobalAdmin,
isGlobalMaintainer,
isTeamAdmin,
isTeamMaintainer,
config,
} = appContext;
const {
gitops_mode_enabled: configGitOpsModeEnabled,
repository_url: repoURL,
} = config?.gitops || {};
const gitOpsModeEnabled = !!configGitOpsModeEnabled;
const canManageSoftware = !!(
isGlobalAdmin ||
isGlobalMaintainer ||
isTeamAdmin ||
isTeamMaintainer
);
return {
cardInfo,
meta: {
installerType,
isAndroidPlayStoreApp,
isFleetMaintainedApp,
isLatestFmaVersion,
fmaVersions,
isCustomPackage,
isIosOrIpadosApp,
sha256,
androidPlayStoreId,
automaticInstallPolicies,
gitOpsModeEnabled,
repoURL,
canManageSoftware,
softwareInstaller,
},
};
}, [softwareTitle, appContext]);
};