mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
163 lines
4.6 KiB
TypeScript
163 lines
4.6 KiB
TypeScript
import { HOST_LINUX_PLATFORMS } from "interfaces/platform";
|
|
import { ISoftware } from "interfaces/software";
|
|
|
|
import AcrobatReader from "./AcrobatReader";
|
|
import ChromeApp from "./ChromeApp";
|
|
import Excel from "./Excel";
|
|
import Extension from "./Extension";
|
|
import Firefox from "./Firefox";
|
|
import MacApp from "./MacApp";
|
|
import MacOS from "./MacOS";
|
|
import Package from "./Package";
|
|
import Safari from "./Safari";
|
|
import Slack from "./Slack";
|
|
import Teams from "./Teams";
|
|
import VisualStudioCode from "./VisualStudioCode";
|
|
import WindowsApp from "./WindowsApp";
|
|
import WindowsOS from "./WindowsOS";
|
|
import Word from "./Word";
|
|
import Zoom from "./Zoom";
|
|
import ChromeOS from "./ChromeOS";
|
|
import LinuxOS from "./LinuxOS";
|
|
import Falcon from "./Falcon";
|
|
import AppStore from "./AppStore";
|
|
import iOS from "./iOS";
|
|
import iPadOS from "./iPadOS";
|
|
|
|
// Maps all known Linux platforms to the LinuxOS icon
|
|
const LINUX_OS_NAME_TO_ICON_MAP = HOST_LINUX_PLATFORMS.reduce(
|
|
(a, platform) => ({ ...a, [platform]: LinuxOS }),
|
|
{}
|
|
);
|
|
|
|
// SOFTWARE_NAME_TO_ICON_MAP list "special" applications that have a defined
|
|
// icon for them, keys refer to application names, and are intended to be fuzzy
|
|
// matched in the application logic.
|
|
const SOFTWARE_NAME_TO_ICON_MAP = {
|
|
appStore: AppStore,
|
|
"adobe acrobat reader": AcrobatReader,
|
|
"microsoft excel": Excel,
|
|
falcon: Falcon,
|
|
firefox: Firefox,
|
|
package: Package,
|
|
safari: Safari,
|
|
slack: Slack,
|
|
"microsoft teams": Teams,
|
|
"visual studio code": VisualStudioCode,
|
|
"microsoft word": Word,
|
|
darwin: MacOS,
|
|
windows: WindowsOS,
|
|
chrome: ChromeOS,
|
|
ios: iOS,
|
|
ipados: iPadOS,
|
|
...LINUX_OS_NAME_TO_ICON_MAP,
|
|
} as const;
|
|
|
|
// SOFTWARE_SOURCE_TO_ICON_MAP maps different software sources to a defined
|
|
// icon.
|
|
const SOFTWARE_SOURCE_TO_ICON_MAP = {
|
|
package: Package,
|
|
apt_sources: Package,
|
|
deb_packages: Package,
|
|
rpm_packages: Package,
|
|
yum_sources: Package,
|
|
npm_packages: Package,
|
|
atom_packages: Package,
|
|
python_packages: Package,
|
|
homebrew_packages: Package,
|
|
apps: MacApp,
|
|
programs: WindowsApp,
|
|
chrome_extensions: Extension,
|
|
safari_extensions: Extension,
|
|
firefox_addons: Extension,
|
|
ie_extensions: Extension,
|
|
chocolatey_packages: Package,
|
|
pkg_packages: Package,
|
|
vscode_extensions: Extension,
|
|
} as const;
|
|
|
|
/**
|
|
* This attempts to loosely match the provided string to a key in a provided dictionary, returning the key if the
|
|
* provided string starts with the key or undefined otherwise.
|
|
*/
|
|
const matchLoosePrefixToKey = <T extends Record<string, unknown>>(
|
|
dict: T,
|
|
s: string
|
|
) => {
|
|
s = s.trim().toLowerCase();
|
|
if (!s) {
|
|
return undefined;
|
|
}
|
|
const match = Object.keys(dict).find((k) =>
|
|
s.startsWith(k.trim().toLowerCase())
|
|
);
|
|
|
|
return match ? (match as keyof T) : undefined;
|
|
};
|
|
|
|
/**
|
|
* This strictly matches the provided name and source to a software icon, returning the icon if a match is found or
|
|
* null otherwise. It is intended to be used for special cases where a strict match is required
|
|
* (e.g. Zoom). The caller should handle null cases by falling back to loose matching on name prefixes.
|
|
*/
|
|
const matchStrictNameSourceToIcon = ({
|
|
name = "",
|
|
source = "",
|
|
}: Pick<ISoftware, "name" | "source">) => {
|
|
name = name.trim().toLowerCase();
|
|
source = source.trim().toLowerCase();
|
|
switch (true) {
|
|
case name === "zoom.us.app" && source === "apps":
|
|
return Zoom;
|
|
case name === "zoom":
|
|
return Zoom;
|
|
case name === "google chrome":
|
|
return ChromeApp;
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* This returns the icon component for a given software name and source. If a strict match is found,
|
|
* it will be returned, otherwise it will fall back to loose matching on name and source prefixes.
|
|
* If no match is found, the default package icon will be returned.
|
|
*/
|
|
const getMatchedSoftwareIcon = ({
|
|
name = "",
|
|
source = "",
|
|
}: Pick<ISoftware, "name" | "source">) => {
|
|
// first, try strict matching on name and source
|
|
let Icon = matchStrictNameSourceToIcon({
|
|
name,
|
|
source,
|
|
});
|
|
|
|
// if no match, try loose matching on name prefixes
|
|
if (!Icon) {
|
|
const matchedName = matchLoosePrefixToKey(SOFTWARE_NAME_TO_ICON_MAP, name);
|
|
if (matchedName) {
|
|
Icon = SOFTWARE_NAME_TO_ICON_MAP[matchedName];
|
|
}
|
|
}
|
|
|
|
// if still no match, try loose matching on source prefixes
|
|
if (!Icon) {
|
|
const matchedSource = matchLoosePrefixToKey(
|
|
SOFTWARE_SOURCE_TO_ICON_MAP,
|
|
source
|
|
);
|
|
if (matchedSource) {
|
|
Icon = SOFTWARE_SOURCE_TO_ICON_MAP[matchedSource];
|
|
}
|
|
}
|
|
|
|
// if still no match, default to 'package'
|
|
if (!Icon) {
|
|
Icon = SOFTWARE_SOURCE_TO_ICON_MAP.package;
|
|
}
|
|
|
|
return Icon;
|
|
};
|
|
|
|
export default getMatchedSoftwareIcon;
|