From ef490b70fc0630378a40f3c41289f8b6dfe54876 Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Fri, 24 Apr 2026 09:43:03 -0400 Subject: [PATCH] Fleet UI: Users page disable checkboxes not meeting requirements (#44080) --- frontend/interfaces/config.ts | 3 +- frontend/interfaces/team.ts | 3 +- .../SetupExperience/cards/Users/Users.tsx | 33 +++-- .../components/UsersForm/UsersForm.tests.tsx | 82 ++++++++++++ .../Users/components/UsersForm/UsersForm.tsx | 119 +++++++++++++----- .../HostActionsDropdown/helpers.tsx | 4 +- 6 files changed, 189 insertions(+), 55 deletions(-) diff --git a/frontend/interfaces/config.ts b/frontend/interfaces/config.ts index 1fe9611425..5c4a0f984e 100644 --- a/frontend/interfaces/config.ts +++ b/frontend/interfaces/config.ts @@ -83,8 +83,9 @@ export interface IMdmConfig { macos_manual_agent_install: boolean | null; require_all_software_macos: boolean | null; lock_end_user_info: boolean | null; + enable_create_local_admin_account?: boolean; }; - macos_setup: { + macos_setup?: { enable_managed_local_account?: boolean; }; macos_migration: IMacOsMigrationSettings; diff --git a/frontend/interfaces/team.ts b/frontend/interfaces/team.ts index dca30c1995..ca083d1f5e 100644 --- a/frontend/interfaces/team.ts +++ b/frontend/interfaces/team.ts @@ -67,8 +67,9 @@ export interface ITeam extends ITeamSummary { macos_manual_agent_install: boolean | null; require_all_software_macos: boolean | null; lock_end_user_info: boolean | null; + enable_create_local_admin_account?: boolean; }; - macos_setup: { + macos_setup?: { enable_managed_local_account?: boolean; }; windows_updates: { diff --git a/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/Users.tsx b/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/Users.tsx index 4dff613ece..ef712fee79 100644 --- a/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/Users.tsx +++ b/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/Users.tsx @@ -9,7 +9,7 @@ import { ITeamConfig } from "interfaces/team"; import SectionHeader from "components/SectionHeader/SectionHeader"; import Spinner from "components/Spinner"; -import GenericMsgWithNavButton from "components/GenericMsgWithNavButton"; + import CustomLink from "components/CustomLink"; import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; @@ -30,11 +30,15 @@ const getEnabledManagedLocalAccount = ( if (currentTeamId === 0) { return ( - globalConfig?.mdm?.macos_setup?.enable_managed_local_account ?? false + globalConfig?.mdm?.setup_experience?.enable_create_local_admin_account ?? + false ); } - return teamConfig?.mdm?.macos_setup?.enable_managed_local_account ?? false; + return ( + teamConfig?.mdm?.setup_experience?.enable_create_local_admin_account ?? + false + ); }; const getEnabledEndUserAuth = ( @@ -129,22 +133,13 @@ const Users = ({ currentTeamId, router }: ISetupExperienceCardProps) => { const mdmConfig = globalConfig.mdm; return ( - {!isIdPConfigured(mdmConfig) ? ( - - ) : ( - - )} + ); }; diff --git a/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tests.tsx b/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tests.tsx index e45edbeb63..0790d9035e 100644 --- a/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tests.tsx +++ b/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tests.tsx @@ -10,12 +10,27 @@ describe("UsersForm", () => { defaultIsEndUserAuthEnabled: false, defaultLockEndUserInfo: false, defaultEnableManagedLocalAccount: false, + isIdPConfigured: true, }; const render = createCustomRenderer({ withBackendMock: true, }); + const renderWithMdmEnabled = createCustomRenderer({ + withBackendMock: true, + context: { + app: { isMacMdmEnabledAndConfigured: true }, + }, + }); + + const renderWithMdmDisabled = createCustomRenderer({ + withBackendMock: true, + context: { + app: { isMacMdmEnabledAndConfigured: false }, + }, + }); + it("renders the end user authentication and managed local account checkboxes", () => { render(); expect(screen.getByText("End user authentication")).toBeInTheDocument(); @@ -83,4 +98,71 @@ describe("UsersForm", () => { const saveButtons = screen.getAllByRole("button", { name: "Save" }); expect(saveButtons).toHaveLength(1); }); + + describe("disabled states", () => { + it("disables end user authentication checkbox when IdP is not configured", () => { + render(); + expect( + screen.getByRole("checkbox", { name: "End user authentication" }) + ).toHaveAttribute("aria-disabled", "true"); + }); + + it("enables end user authentication checkbox when IdP is configured", () => { + render(); + expect( + screen.getByRole("checkbox", { name: "End user authentication" }) + ).toHaveAttribute("aria-disabled", "false"); + }); + + it("disables lock end user info when IdP is not configured", () => { + render( + + ); + expect( + screen.getByRole("checkbox", { name: "Lock end user info" }) + ).toHaveAttribute("aria-disabled", "true"); + }); + + it("does not allow toggling end user auth when IdP is not configured", async () => { + const { user } = render( + + ); + + const checkbox = screen.getByRole("checkbox", { + name: "End user authentication", + }); + await user.click(checkbox); + + expect(checkbox).not.toBeChecked(); + }); + + it("disables managed local account checkbox when Apple MDM is not configured", () => { + renderWithMdmDisabled(); + expect( + screen.getByRole("checkbox", { name: "Managed local account" }) + ).toHaveAttribute("aria-disabled", "true"); + }); + + it("enables managed local account checkbox when Apple MDM is configured", () => { + renderWithMdmEnabled(); + expect( + screen.getByRole("checkbox", { name: "Managed local account" }) + ).toHaveAttribute("aria-disabled", "false"); + }); + + it("does not allow toggling managed local account when Apple MDM is not configured", async () => { + const { user } = renderWithMdmDisabled(); + + const checkbox = screen.getByRole("checkbox", { + name: "Managed local account", + }); + await user.click(checkbox); + + expect(checkbox).not.toBeChecked(); + }); + }); }); diff --git a/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tsx b/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tsx index 21dcbd2b3a..3c07ccea85 100644 --- a/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tsx +++ b/frontend/pages/ManageControlsPage/SetupExperience/cards/Users/components/UsersForm/UsersForm.tsx @@ -18,6 +18,7 @@ interface IUsersFormProps { defaultIsEndUserAuthEnabled: boolean; defaultLockEndUserInfo: boolean; defaultEnableManagedLocalAccount: boolean; + isIdPConfigured: boolean; } const UsersForm = ({ @@ -25,10 +26,11 @@ const UsersForm = ({ defaultIsEndUserAuthEnabled, defaultLockEndUserInfo, defaultEnableManagedLocalAccount, + isIdPConfigured, }: IUsersFormProps) => { const { renderFlash } = useContext(NotificationContext); - const gitOpsModeEnabled = useContext(AppContext).config?.gitops - .gitops_mode_enabled; + const { config, isMacMdmEnabledAndConfigured } = useContext(AppContext); + const gitOpsModeEnabled = config?.gitops.gitops_mode_enabled; const [isEndUserAuthEnabled, setEndUserAuthEnabled] = useState( defaultIsEndUserAuthEnabled @@ -68,7 +70,8 @@ const UsersForm = ({ setEnableManagedLocalAccount(newCheckVal); }; - const onClickSave = async () => { + const onClickSave = async (e: React.FormEvent) => { + e.preventDefault(); setIsUpdating(true); const canLockEndUserInfo = isEndUserAuthEnabled && lockEndUserInfo; @@ -91,27 +94,49 @@ const UsersForm = ({ return ( - - End users are required to authenticate with your{" "} - {" "} - when setting up new hosts. - + + To enable, first connect Fleet to + + your{" "} + + . + + ) : undefined } + disableTooltip={isIdPConfigured} + underline={false} + position="left" + showArrow > - End user authentication - + + End users are required to authenticate with your{" "} + {" "} + when setting up new hosts. + + } + > + End user authentication + + {isEndUserAuthEnabled && ( @@ -133,22 +158,50 @@ const UsersForm = ({ )} - - Fleet generates a user (_fleetadmin) and unique password for each - host, accessible in Host details >{" "} - Show managed account. - + + To enable, first turn on{" "} + + . + + ) : undefined } + disableTooltip={!!isMacMdmEnabledAndConfigured} + underline={false} + position="left" + showArrow > - - Managed local account - - + + Fleet generates a user (_fleetadmin) and unique password for + each host, accessible in Host details >{" "} + Show managed account. + + } + > + + Creates a hidden managed local admin account for + + remote troubleshooting on macOS hosts. + > + } + > + Managed local account + + + ( { if (hostPlatform !== "darwin") return false; if (!isConnectedToFleetMdm) return false; if (!isAutomaticDeviceEnrollment(hostMdmEnrollmentStatus)) return false; - if (!isManagedLocalAccountEnabled) return false; + if (!isManagedLocalAccountEnabled && !config.managedAccountStatus) { + return false; + } return isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer; };