diff --git a/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx b/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
index e29924f2e0..28a4d722ca 100644
--- a/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
+++ b/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
@@ -17,7 +17,10 @@ import {
humanHostLastSeen,
humanHostDetailUpdated,
} from "kolide/helpers";
-import PATHS from "../../../router/paths";
+import { IConfig } from "interfaces/config";
+import { IUser } from "interfaces/user";
+import PATHS from "router/paths";
+import permissionUtils from "utilities/permissions";
interface IHeaderProps {
column: {
@@ -56,7 +59,7 @@ const lastSeenTime = (status: string, seenTime: string): string => {
return "Online";
};
-const hostTableHeaders: IHostDataColumn[] = [
+const allHostTableHeaders: IHostDataColumn[] = [
// We are using React Table useRowSelect functionality for the selection header.
// More information on its API can be found here
// https://react-table.tanstack.com/docs/api/useRowSelect
@@ -102,6 +105,12 @@ const hostTableHeaders: IHostDataColumn[] = [
),
disableHidden: true,
},
+ {
+ title: "Team",
+ Header: "Team",
+ accessor: "team_name",
+ Cell: (cellProps) => ,
+ },
{
title: "Status",
Header: "Status",
@@ -261,12 +270,58 @@ const defaultHiddenColumns = [
"hardware_serial",
];
-const generateVisibleHostColumns = (
- hiddenColumns: string[]
+/**
+ * Will generate a host table column configuration based off of the current user
+ * permissions and license tier of fleet they are on.
+ */
+const generateAvailableTableHeaders = (
+ config: IConfig,
+ currentUser: IUser
): IHostDataColumn[] => {
- return hostTableHeaders.filter((column) => {
+ return allHostTableHeaders.reduce(
+ (columns: IHostDataColumn[], currentColumn: IHostDataColumn) => {
+ // skip over column headers that are not shown in core tier
+ if (permissionUtils.isCoreTier(config)) {
+ if (
+ currentColumn.accessor === "team_name" ||
+ currentColumn.id === "selection"
+ ) {
+ return columns;
+ }
+ // In base tier, we want to check user role to enable/disable select column
+ } else if (
+ !permissionUtils.isGlobalAdmin(currentUser) &&
+ !permissionUtils.isGlobalMaintainer(currentUser)
+ ) {
+ if (currentColumn.id === "selection") {
+ return columns;
+ }
+ }
+
+ columns.push(currentColumn);
+ return columns;
+ },
+ []
+ );
+};
+
+/**
+ * Will generate a host table column configuration that a user currently sees.
+ *
+ */
+const generateVisibleTableColumns = (
+ hiddenColumns: string[],
+ config: IConfig,
+ currentUser: IUser
+): IHostDataColumn[] => {
+ // remove columns set as hidden by the user.
+ return generateAvailableTableHeaders(config, currentUser).filter((column) => {
return !hiddenColumns.includes(column.accessor as string);
});
};
-export { hostTableHeaders, defaultHiddenColumns, generateVisibleHostColumns };
+export {
+ defaultHiddenColumns,
+ generateAvailableTableHeaders,
+ generateVisibleTableColumns,
+};
diff --git a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx
index 3135983f99..8fc5993097 100644
--- a/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx
+++ b/frontend/pages/hosts/ManageHostsPage/ManageHostsPage.jsx
@@ -14,6 +14,7 @@ import TableContainer from "components/TableContainer";
import labelInterface from "interfaces/label";
import hostInterface from "interfaces/host";
import teamInterface from "interfaces/team";
+import userInterface from "interfaces/user";
import osqueryTableInterface from "interfaces/osquery_table";
import statusLabelsInterface from "interfaces/status_labels";
import enrollSecretInterface from "interfaces/enroll_secret";
@@ -33,8 +34,8 @@ import deepDifference from "utilities/deep_difference";
import permissionUtils from "utilities/permissions";
import {
defaultHiddenColumns,
- hostTableHeaders,
- generateVisibleHostColumns,
+ generateVisibleTableColumns,
+ generateAvailableTableHeaders,
} from "./HostTableConfig";
import AddHostModal from "./components/AddHostModal";
import NoHosts from "./components/NoHosts";
@@ -69,6 +70,7 @@ export class ManageHostsPage extends PureComponent {
canAddNewHosts: PropTypes.bool,
teams: PropTypes.arrayOf(teamInterface),
isGlobalAdmin: PropTypes.bool,
+ currentUser: userInterface,
};
static defaultProps = {
@@ -168,7 +170,7 @@ export class ManageHostsPage extends PureComponent {
};
// NOTE: this is called once on the initial rendering. The initial render of
- // the TableContainer child component.
+ // the TableContainer child component will call this handler.
onTableQueryChange = (queryData) => {
const { selectedFilter, dispatch } = this.props;
const {
@@ -260,7 +262,7 @@ export class ManageHostsPage extends PureComponent {
"success",
`Hosts successfully transferred to ${team.name}.`
)
- ); // TODO: update team name
+ );
})
.catch(() => {
dispatch(
@@ -294,6 +296,7 @@ export class ManageHostsPage extends PureComponent {
};
renderEditColumnsModal = () => {
+ const { config, currentUser } = this.props;
const { showEditColumnsModal, hiddenColumns } = this.state;
if (!showEditColumnsModal) return null;
@@ -305,7 +308,7 @@ export class ManageHostsPage extends PureComponent {
className={`${baseClass}__invite-modal`}
>
{
- const { selectedFilter, selectedLabel, hosts, loadingHosts } = this.props;
+ const {
+ config,
+ currentUser,
+ selectedFilter,
+ selectedLabel,
+ hosts,
+ loadingHosts,
+ } = this.props;
const { hiddenColumns } = this.state;
const {
onTableQueryChange,
@@ -567,7 +577,11 @@ export class ManageHostsPage extends PureComponent {
return (
{
permissionUtils.isGlobalAdmin(currentUser) ||
permissionUtils.isGlobalMaintainer(currentUser);
const isGlobalAdmin = permissionUtils.isGlobalAdmin(currentUser);
-
const teams = memoizedGetEntity(state.entities.teams.data);
return {
@@ -682,6 +695,7 @@ const mapStateToProps = (state, { location, params }) => {
selectedOsqueryTable,
statusLabels,
config,
+ currentUser,
hosts,
loadingHosts,
canAddNewHosts,
diff --git a/frontend/utilities/permissions/permissions.ts b/frontend/utilities/permissions/permissions.ts
index 91dd96a7a0..458e15f25e 100644
--- a/frontend/utilities/permissions/permissions.ts
+++ b/frontend/utilities/permissions/permissions.ts
@@ -1,5 +1,5 @@
import { IUser } from "interfaces/user";
-import { IConfig } from "../../interfaces/config";
+import { IConfig } from "interfaces/config";
const isCoreTier = (config: IConfig): boolean => {
return config.tier === "core";