Skip to content

Commit

Permalink
update ossettings table for ddm
Browse files Browse the repository at this point in the history
  • Loading branch information
ghernandez345 committed Mar 20, 2024
1 parent 2e14aa3 commit 96f6555
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 83 deletions.
2 changes: 1 addition & 1 deletion frontend/__mocks__/hostMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const DEFAULT_HOST_PROFILE_MOCK: IHostMdmProfile = {
detail: "This is verified",
};

export const createMockHostMacMdmProfile = (
export const createMockHostMdmProfile = (
overrides?: Partial<IHostMdmProfile>
): IHostMdmProfile => {
return { ...DEFAULT_HOST_PROFILE_MOCK, ...overrides };
Expand Down
7 changes: 6 additions & 1 deletion frontend/interfaces/mdm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ export interface IMdmProfile {
}

export type MdmProfileStatus = "verified" | "verifying" | "pending" | "failed";
export type MdmDDMProfileStatus =
| "success"
| "pending"
| "failed"
| "acknowledged";

export type ProfileOperationType = "remove" | "install";

Expand All @@ -89,7 +94,7 @@ export interface IHostMdmProfile {
name: string;
operation_type: ProfileOperationType | null;
platform: ProfilePlatform;
status: MdmProfileStatus;
status: MdmProfileStatus | MdmDDMProfileStatus;
detail: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import FileSaver from "file-saver";
import classnames from "classnames";

import { IMdmProfile } from "interfaces/mdm";
import mdmAPI from "services/entities/mdm";
import mdmAPI, { isDDMProfile } from "services/entities/mdm";

import Button from "components/buttons/Button";
import Graphic from "components/Graphic";
import Icon from "components/Icon";

import strUtils from "utilities/strings";
import { is } from "date-fns/locale";

const baseClass = "profile-list-item";

Expand All @@ -30,17 +29,17 @@ const LabelCount = ({
interface IProfileDetailsProps {
platform: string;
createdAt: string;
isDDMProfile?: boolean;
isDDM?: boolean;
}

const ProfileDetails = ({
platform,
createdAt,
isDDMProfile,
isDDM,
}: IProfileDetailsProps) => {
const getPlatformName = () => {
if (platform === "windows") return "Windows";
return isDDMProfile ? "macOS (declaration)" : "macOS";
return isDDM ? "macOS (declaration)" : "macOS";
};

return (
Expand All @@ -63,10 +62,6 @@ interface IProfileListItemProps {
>;
}

const isDDMProfile = (profile: IMdmProfile) => {
return profile.name.includes(".json");
};

const ProfileListItem = ({
isPremium,
profile,
Expand Down Expand Up @@ -95,7 +90,7 @@ const ProfileListItem = ({
<ProfileDetails
platform={platform}
createdAt={created_at}
isDDMProfile={isDDMProfile(profile)}
isDDM={isDDMProfile(name)}
/>
</div>
</div>
Expand Down
25 changes: 24 additions & 1 deletion frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { QueryContext } from "context/query";
import { NotificationContext } from "context/notification";

import activitiesAPI, {
IActivitiesResponse,
IPastActivitiesResponse,
IUpcomingActivitiesResponse,
} from "services/entities/activities";
Expand Down Expand Up @@ -53,6 +52,7 @@ import {
HOST_ABOUT_DATA,
HOST_OSQUERY_DATA,
} from "utilities/constants";
import { createMockHostMdmProfile } from "__mocks__/hostMock";

import Spinner from "components/Spinner";
import TabsWrapper from "components/TabsWrapper";
Expand Down Expand Up @@ -753,6 +753,29 @@ const HostDetailsPage = ({
name: host?.mdm.macos_setup?.bootstrap_package_name,
};

if (!host.mdm.profiles) {
host.mdm.profiles = [];
} else {
host.mdm.profiles = [
createMockHostMdmProfile({
name: "test.json",
status: "success",
}),
createMockHostMdmProfile({
name: "test2.json",
status: "pending",
}),
createMockHostMdmProfile({
name: "test3.json",
status: "failed",
}),
createMockHostMdmProfile({
name: "test4.json",
status: "acknowledged",
}),
];
}

return (
<MainContent className={baseClass}>
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,35 @@ type OperationTypeOption = Record<

type ProfileDisplayConfig = Record<ProfileOperationType, OperationTypeOption>;

const MAC_PROFILE_VERIFIED_DISPLAY_CONFIG: ProfileDisplayOption = {
statusText: "Verified",
iconName: "success",
tooltip: (innerProps) =>
innerProps.isDiskEncryptionProfile
? "The host turned disk encryption on and sent the key to Fleet. " +
"Fleet verified with osquery."
: "The host applied the setting. Fleet verified with osquery. " +
"Declaration profiles are verified with DDM.",
};

const MAC_PROFILE_VERIFYING_DISPLAY_CONFIG: ProfileDisplayOption = {
statusText: "Verifying",
iconName: "success-outline",
tooltip: (innerProps) =>
innerProps.isDiskEncryptionProfile
? "The host acknowledged the MDM command to turn on disk encryption. " +
"Fleet is verifying with osquery and retrieving the disk encryption key. " +
"This may take up to one hour."
: "The host acknowledged the MDM command to apply the setting. Fleet is " +
"verifying with osquery.",
};

export const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
install: {
verified: {
statusText: "Verified",
iconName: "success",
tooltip: (innerProps) =>
innerProps.isDiskEncryptionProfile
? "The host turned disk encryption on and sent the key to Fleet. " +
"Fleet verified with osquery."
: "The host applied the setting. Fleet verified with osquery. " +
"Declaration profiles are verified with DDM.",
},
verifying: {
statusText: "Verifying",
iconName: "success-outline",
tooltip: (innerProps) =>
innerProps.isDiskEncryptionProfile
? "The host acknowledged the MDM command to turn on disk encryption. " +
"Fleet is verifying with osquery and retrieving the disk encryption key. " +
"This may take up to one hour."
: "The host acknowledged the MDM command to apply the setting. Fleet is " +
"verifying with osquery.",
},
verified: MAC_PROFILE_VERIFIED_DISPLAY_CONFIG,
success: MAC_PROFILE_VERIFIED_DISPLAY_CONFIG,
verifying: MAC_PROFILE_VERIFYING_DISPLAY_CONFIG,
acknowledged: MAC_PROFILE_VERIFYING_DISPLAY_CONFIG,
pending: {
statusText: "Enforcing (pending)",
iconName: "pending-outline",
Expand Down Expand Up @@ -80,6 +86,8 @@ export const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
action_required: null, // should not be reached
verified: null, // should not be reached
verifying: null, // should not be reached
success: null, // should not be reached
acknowledged: null, // should not be reached
failed: {
statusText: "Failed",
iconName: "error",
Expand All @@ -90,7 +98,8 @@ export const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {

type WindowsDiskEncryptionDisplayConfig = Omit<
OperationTypeOption,
"action_required"
// windows disk encryption does not have these states
"action_required" | "success" | "acknowledged"
>;

export const WINDOWS_DISK_ENCRYPTION_DISPLAY_CONFIG: WindowsDiskEncryptionDisplayConfig = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from "react";
import TableContainer from "components/TableContainer";

import tableHeaders, { ITableRowOsSettings } from "./OSSettingsTableConfig";
import tableHeaders, {
IHostMdmProfileWithAddedStatus,
} from "./OSSettingsTableConfig";

const baseClass = "os-settings-table";

interface IOSSettingsTableProps {
tableData?: ITableRowOsSettings[];
tableData?: IHostMdmProfileWithAddedStatus[];
}

const OSSettingsTable = ({ tableData }: IOSSettingsTableProps) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,45 @@
import TextCell from "components/TableContainer/DataTable/TextCell";
import React from "react";
import { Column } from "react-table";

import { IStringCellProps } from "interfaces/datatable_config";
import { IHostMdmData } from "interfaces/host";
import {
FLEET_FILEVAULT_PROFILE_DISPLAY_NAME,
// FLEET_FILEVAULT_PROFILE_IDENTIFIER,
IHostMdmProfile,
MdmDDMProfileStatus,
MdmProfileStatus,
ProfilePlatform,
isWindowsDiskEncryptionStatus,
} from "interfaces/mdm";
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import { isDDMProfile } from "services/entities/mdm";

import TextCell from "components/TableContainer/DataTable/TextCell";
import TooltipTruncatedTextCell from "components/TableContainer/DataTable/TooltipTruncatedTextCell";

import OSSettingStatusCell from "./OSSettingStatusCell";
import { generateWinDiskEncryptionProfile } from "../../helpers";

export interface ITableRowOsSettings extends Omit<IHostMdmProfile, "status"> {
status: OsSettingsTableStatusValue;
}

export type OsSettingsTableStatusValue = MdmProfileStatus | "action_required";

export const isMdmProfileStatus = (
status: string
): status is MdmProfileStatus => {
return status !== "action_required";
};

interface IHeaderProps {
column: {
title: string;
isSortedDesc: boolean;
};
export interface IHostMdmProfileWithAddedStatus
extends Omit<IHostMdmProfile, "status"> {
status: OsSettingsTableStatusValue;
}

interface ICellProps {
cell: {
value: string;
};
row: {
original: ITableRowOsSettings;
};
}
type ITableColumnConfig = Column<IHostMdmProfileWithAddedStatus>;
type ITableStringCellProps = IStringCellProps<IHostMdmProfileWithAddedStatus>;

interface IDataColumn {
Header: ((props: IHeaderProps) => JSX.Element) | string;
Cell: (props: ICellProps) => JSX.Element;
id?: string;
title?: string;
accessor?: string;
disableHidden?: boolean;
disableSortBy?: boolean;
sortType?: string;
}
export type INonDDMProfileStatus = MdmProfileStatus | "action_required";

export type OsSettingsTableStatusValue =
| MdmDDMProfileStatus
| INonDDMProfileStatus;

/**
* generates the formatted tooltip for the error column.
Expand Down Expand Up @@ -107,22 +94,24 @@ const generateErrorTooltip = (
return generateFormattedTooltip(detail);
};

const tableHeaders: IDataColumn[] = [
const tableHeaders: ITableColumnConfig[] = [
{
title: "Name",
Header: "Name",
disableSortBy: true,
accessor: "name",
Cell: (cellProps: ICellProps): JSX.Element => (
<TextCell value={cellProps.cell.value} />
),
Cell: (cellProps: ITableStringCellProps) => {
let profileTitle = cellProps.cell.value;
if (isDDMProfile(cellProps.cell.value)) {
profileTitle = cellProps.cell.value.replace(".json", "");
}
return <TextCell value={profileTitle} />;
},
},
{
title: "Status",
Header: "Status",
disableSortBy: true,
accessor: "statusText",
Cell: (cellProps: ICellProps) => {
accessor: "status",
Cell: (cellProps: ITableStringCellProps) => {
return (
<OSSettingStatusCell
status={cellProps.row.original.status}
Expand All @@ -133,11 +122,10 @@ const tableHeaders: IDataColumn[] = [
},
},
{
title: "Error",
Header: "Error",
disableSortBy: true,
accessor: "detail",
Cell: (cellProps: ICellProps): JSX.Element => {
Cell: (cellProps: ITableStringCellProps): JSX.Element => {
const profile = cellProps.row.original;

const value =
Expand Down Expand Up @@ -165,7 +153,7 @@ const tableHeaders: IDataColumn[] = [
];

const makeWindowsRows = ({ profiles, os_settings }: IHostMdmData) => {
const rows: ITableRowOsSettings[] = [];
const rows: IHostMdmProfileWithAddedStatus[] = [];

if (profiles) {
rows.push(...profiles);
Expand All @@ -190,15 +178,12 @@ const makeWindowsRows = ({ profiles, os_settings }: IHostMdmData) => {
return rows;
};

const makeDarwinRows = ({
profiles,
macos_settings,
}: IHostMdmData): ITableRowOsSettings[] | null => {
const makeDarwinRows = ({ profiles, macos_settings }: IHostMdmData) => {
if (!profiles) {
return null;
}

let rows: ITableRowOsSettings[] = profiles;
let rows: IHostMdmProfileWithAddedStatus[] = profiles;
if (macos_settings?.disk_encryption === "action_required") {
rows = profiles.map((p) => {
// TODO: this is a brittle check for the filevault profile
Expand Down
4 changes: 4 additions & 0 deletions frontend/services/entities/mdm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export interface IUploadProfileApiParams {
labels?: string[];
}

export const isDDMProfile = (name: string) => {
return name.includes(".json");
};

const mdmService = {
downloadDeviceUserEnrollmentProfile: (token: string) => {
const { DEVICE_USER_MDM_ENROLLMENT_PROFILE } = endpoints;
Expand Down
13 changes: 13 additions & 0 deletions frontend/utilities/date_format/date_format.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { uploadedFromNow } from ".";

describe("date_format", () => {
describe("uploadedFromNow util", () => {
it("returns an user friendly uploaded at message", () => {
const currentDate = new Date();
currentDate.setDate(currentDate.getDate() - 2);
const twoDaysAgo = currentDate.toISOString();

expect(uploadedFromNow(twoDaysAgo)).toEqual("Uploaded 2 days ago");
});
});
});

0 comments on commit 96f6555

Please sign in to comment.