diff --git a/changes/48077-observer-managed-account-action.md b/changes/48077-observer-managed-account-action.md new file mode 100644 index 0000000000..ef4ac861b9 --- /dev/null +++ b/changes/48077-observer-managed-account-action.md @@ -0,0 +1 @@ +- Fixed observers not seeing the "Show managed account" action on a macOS host's details page, even though the API already allows them to view the managed local account password. diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx index 5011bd9af1..8aaf42da98 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx @@ -2108,6 +2108,68 @@ describe("Host Actions Dropdown", () => { expect(screen.getByText("Show managed account")).toBeInTheDocument(); }); + it("renders the action for a global observer (the API authorizes any host-reader)", async () => { + const render = createCustomRenderer({ + context: { + app: { + isGlobalObserver: true, + isPremiumTier: true, + currentUser: createMockUser(), + }, + }, + }); + + const { user } = render( + + ); + + await user.click(screen.getByText("Actions")); + + expect(screen.getByText("Show managed account")).toBeInTheDocument(); + }); + + it("renders the action for a team observer", async () => { + const render = createCustomRenderer({ + context: { + app: { + isTeamObserver: true, + isPremiumTier: true, + currentUser: createMockUser(), + }, + }, + }); + + const { user } = render( + + ); + + await user.click(screen.getByText("Actions")); + + expect(screen.getByText("Show managed account")).toBeInTheDocument(); + }); + it("hides the action when managed local account is not enabled", async () => { const render = createCustomRenderer({ context: { diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx index ff8104fee2..c312706ab2 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx @@ -388,10 +388,6 @@ const canShowManagedAccount = (config: IHostActionConfigOptions) => { const { isPremiumTier, isConnectedToFleetMdm, - isGlobalAdmin, - isGlobalMaintainer, - isTeamAdmin, - isTeamMaintainer, hostPlatform, hostMdmEnrollmentStatus, isManagedLocalAccountEnabled, @@ -403,7 +399,12 @@ const canShowManagedAccount = (config: IHostActionConfigOptions) => { if (!isManagedLocalAccountEnabled && !config.managedAccountStatus) { return false; } - return isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer; + // Not role-gated: the backend authorizes this action for any user who can + // read the host (including observers), matching the other "show secret" + // actions above (disk encryption key, Recovery Lock password). Restricting + // it to admins/maintainers here hid the action from observers even though + // the API returns the managed account password to them. + return true; }; const canClearPasscode = (config: IHostActionConfigOptions) => {