Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Refactor HostTableConfig to gate selection by capability, not role#45990

Draft
nulmete wants to merge 1 commit into
mainfrom
nulmete/refactor-host-table-can-select-hosts
Draft

Refactor HostTableConfig to gate selection by capability, not role#45990
nulmete wants to merge 1 commit into
mainfrom
nulmete/refactor-host-table-can-select-hosts

Conversation

@nulmete
Copy link
Copy Markdown
Member

@nulmete nulmete commented May 21, 2026

Summary by CodeRabbit

  • Tests

    • Added comprehensive tests for host table column configuration across subscription tiers and user permissions.
  • Refactor

    • Updated host table column visibility logic to enforce tier-specific restrictions. Free tier users now have limited access to certain columns, while host selection capability is properly controlled based on user roles and permissions.

Review Change Stack

Rename the `isOnlyObserver` parameter on `generateAvailableTableHeaders`
and `generateVisibleTableColumns` to `canSelectHosts` (inverted meaning).
The parameter only ever gated the leading checkbox column, so naming it
after a role forced callers to negate role checks to express a
capability. The new name reflects what the flag actually controls.

Also flattens the nested reduce into a single filter and removes a dead
`team_name` mention from the old observer branch (free tier already
skips it via the next branch).

Adds HostTableConfig.tests.tsx locking behavior across tier × capability
permutations.
@nulmete nulmete requested a review from a team as a code owner May 21, 2026 17:04
Copilot AI review requested due to automatic review settings May 21, 2026 17:04
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@nulmete nulmete marked this pull request as draft May 21, 2026 17:05
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Walkthrough

This PR refactors the host table column generation utility to replace the isOnlyObserver parameter with a more semantic canSelectHosts boolean. The utilities generateAvailableTableHeaders and generateVisibleTableColumns now accept canSelectHosts to control whether the host selection column is included. A new FREE_TIER_HIDDEN_COLUMN_IDS constant explicitly defines which columns are hidden for free-tier accounts. All three callsites in ManageHostsPage (edit columns modal, CSV export, and table rendering) are updated to compute canSelectHosts from the user's roles and permissions before invoking the refactored utilities. Comprehensive test coverage validates the column filtering behavior across tier and selection eligibility combinations.

Possibly related PRs

  • fleetdm/fleet#45020: Modifies CSV export flow in ManageHostsPage, specifically column inclusion logic based on hiddenColumns and selection rules when building the export payload.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided. The template requires sections like related issue, checklist items, testing details, and other important information. Add a detailed pull request description following the repository template, including related issue number, relevant checklist items, and testing information.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: refactoring HostTableConfig to use capability-based gating (canSelectHosts) instead of role-based logic (isOnlyObserver).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nulmete/refactor-host-table-can-select-hosts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx`:
- Around line 1445-1448: Unify the derivation of canSelectHosts by computing it
once with the stricter capability logic currently used around the selection
column (replace the ad-hoc uses of !isOnlyObserver). Create a single local
constant (e.g., canSelectHosts) derived using the stricter check that mirrors
the logic at lines ~1828-1831, then pass that constant into every
generateAvailableTableHeaders call (and any other callsites that currently use
!isOnlyObserver) so the Edit Columns UI and table column generation use the
exact same permission check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aa6fd804-ca10-4c84-ac0a-74c9bb6a15ee

📥 Commits

Reviewing files that changed from the base of the PR and between 8441136 and 1aabbb5.

📒 Files selected for processing (3)
  • frontend/pages/hosts/ManageHostsPage/HostTableConfig.tests.tsx
  • frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
  • frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx

Comment on lines +1445 to +1448
columns={generateAvailableTableHeaders({
isFreeTier,
canSelectHosts: !isOnlyObserver,
})}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Unify canSelectHosts derivation across callsites.

Line 1447 and Line 1579 use !isOnlyObserver, but Line 1828-Line 1831 uses stricter capability logic. This can expose the selection column in Edit Columns for users who cannot actually select hosts in the table.

Suggested fix
@@
   const canRunScriptBatch =
     isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer;
+  const canSelectHosts =
+    !isOnlyObserver &&
+    !isGlobalTechnician &&
+    (isOnGlobalTeam || isTeamMaintainerOrTeamAdmin);
@@
         columns={generateAvailableTableHeaders({
           isFreeTier,
-          canSelectHosts: !isOnlyObserver,
+          canSelectHosts,
         })}
@@
         const tableColumns = generateVisibleTableColumns({
           hiddenColumns,
           isFreeTier,
-          canSelectHosts: !isOnlyObserver,
+          canSelectHosts,
           teamId: teamIdForApi,
         });
@@
     const tableColumns = generateVisibleTableColumns({
       hiddenColumns,
       isFreeTier,
-      canSelectHosts:
-        !isOnlyObserver &&
-        !isGlobalTechnician &&
-        (isOnGlobalTeam || isTeamMaintainerOrTeamAdmin),
+      canSelectHosts,
       teamId: teamIdForApi,
     });

Also applies to: 1576-1580, 1825-1833

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx` around lines 1445 -
1448, Unify the derivation of canSelectHosts by computing it once with the
stricter capability logic currently used around the selection column (replace
the ad-hoc uses of !isOnlyObserver). Create a single local constant (e.g.,
canSelectHosts) derived using the stricter check that mirrors the logic at lines
~1828-1831, then pass that constant into every generateAvailableTableHeaders
call (and any other callsites that currently use !isOnlyObserver) so the Edit
Columns UI and table column generation use the exact same permission check.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 21, 2026

Codecov Report

❌ Patch coverage is 84.61538% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.80%. Comparing base (0c112d7) to head (1aabbb5).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...nd/pages/hosts/ManageHostsPage/HostTableConfig.tsx 80.00% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main   #45990    +/-   ##
========================================
  Coverage   66.80%   66.80%            
========================================
  Files        2752     2752            
  Lines      219903   219895     -8     
  Branches    10890    11012   +122     
========================================
- Hits       146910   146906     -4     
+ Misses      59721    59716     -5     
- Partials    13272    13273     +1     
Flag Coverage Δ
frontend 55.80% <84.61%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the hosts table column configuration to gate the leading selection/checkbox column by an explicit capability (canSelectHosts) rather than by a specific role flag, and adds unit tests around the new behavior. This improves reuse/clarity of HostTableConfig by making callers responsible for computing the appropriate “can bulk select” conditions.

Changes:

  • Updated HostTableConfig to accept canSelectHosts and filter out the selection column when selection isn’t allowed.
  • Updated ManageHostsPage call sites to pass canSelectHosts instead of isOnlyObserver.
  • Added unit tests covering free vs premium tier behavior and selection-column visibility.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
frontend/pages/hosts/ManageHostsPage/ManageHostsPage.tsx Passes canSelectHosts into host table header/column generation.
frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx Replaces role-based checks with capability-based filtering for the selection column and centralizes free-tier hidden IDs.
frontend/pages/hosts/ManageHostsPage/HostTableConfig.tests.tsx Adds unit tests validating the new canSelectHosts behavior for available/visible columns.
Comments suppressed due to low confidence (1)

frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx:743

  • generateVisibleTableColumns currently hides any column whose id is in hiddenColumns, even if the column is marked disableHidden. Since disableHidden is documented/used to prevent certain columns from being hidden (e.g. selection and display_name), it would be safer to ignore hiddenColumns for disableHidden columns so required columns can’t disappear due to persisted/legacy settings.
  return generateAvailableTableHeaders({
    isFreeTier,
    canSelectHosts,
    teamId,
  }).filter((column) => {
    return !hiddenColumns.includes(column.id as string);
  });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1445 to +1448
columns={generateAvailableTableHeaders({
isFreeTier,
canSelectHosts: !isOnlyObserver,
})}
Comment on lines 1576 to 1580
const tableColumns = generateVisibleTableColumns({
hiddenColumns,
isFreeTier,
isOnlyObserver,
canSelectHosts: !isOnlyObserver,
teamId: teamIdForApi,
Comment on lines +111 to +115
it("can hide the selection column via hiddenColumns even when canSelectHosts is true", () => {
const ids = getIds(
generateVisibleTableColumns({
hiddenColumns: ["selection"],
isFreeTier: false,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants