diff --git a/changes/10879-api-only-user-badge b/changes/10879-api-only-user-badge new file mode 100644 index 0000000000..635f5fa738 --- /dev/null +++ b/changes/10879-api-only-user-badge @@ -0,0 +1 @@ +- User management table informs which users only have API accesss diff --git a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPageTableConfig.tsx b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPageTableConfig.tsx index 0a289eebdc..1f62ec5dd4 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPageTableConfig.tsx +++ b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/MembersPageTableConfig.tsx @@ -1,6 +1,8 @@ import React from "react"; +import ReactTooltip from "react-tooltip"; import TextCell from "components/TableContainer/DataTable/TextCell/TextCell"; import DropdownCell from "components/TableContainer/DataTable/DropdownCell"; +import CustomLink from "components/CustomLink"; import { IUser } from "interfaces/user"; import { ITeam } from "interfaces/team"; import { IDropdownOption } from "interfaces/dropdownOption"; @@ -64,9 +66,54 @@ const generateTableHeaders = ( disableSortBy: true, sortType: "caseInsensitive", accessor: "name", - Cell: (cellProps: ICellProps) => ( - - ), + Cell: (cellProps: ICellProps) => { + const formatter = (val: string) => { + const apiOnlyUser = + "api_only" in cellProps.row.original + ? cellProps.row.original.api_only + : false; + + return ( + <> + {val} + {apiOnlyUser && ( + <> + + API + + + <> + This user was created using fleetctl and +
only has API access.{" "} + + +
+ + )} + + ); + }; + + return ; + }, }, { title: "Role", @@ -137,6 +184,7 @@ const enhanceMembersData = ( global_role: user.global_role, actions: generateActionDropdownOptions(), id: user.id, + api_only: user.api_only, }; }); }; diff --git a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/_styles.scss b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/_styles.scss index 96e77ae4f7..07e5742d53 100644 --- a/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/_styles.scss +++ b/frontend/pages/admin/TeamManagementPage/TeamDetailsWrapper/MembersPage/_styles.scss @@ -6,6 +6,10 @@ margin: 0; } + &__api-only-user { + @include grey-badge; + } + .data-table-block { .data-table__table { thead { diff --git a/frontend/pages/admin/UserManagementPage/_styles.scss b/frontend/pages/admin/UserManagementPage/_styles.scss index b4730838e3..163dfa6e25 100644 --- a/frontend/pages/admin/UserManagementPage/_styles.scss +++ b/frontend/pages/admin/UserManagementPage/_styles.scss @@ -9,4 +9,8 @@ &__sandbox-demo-message { margin-top: 3.5rem; } + + &__api-only-user { + @include grey-badge; + } } diff --git a/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx b/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx index 8c2b52f445..22fb5ceacf 100644 --- a/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx +++ b/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx @@ -1,8 +1,10 @@ import React from "react"; +import ReactTooltip from "react-tooltip"; import HeaderCell from "components/TableContainer/DataTable/HeaderCell/HeaderCell"; import StatusIndicator from "components/StatusIndicator"; import TextCell from "components/TableContainer/DataTable/TextCell/TextCell"; +import CustomLink from "components/CustomLink"; import { IInvite } from "interfaces/invite"; import { IUser } from "interfaces/user"; import { IDropdownOption } from "interfaces/dropdownOption"; @@ -55,6 +57,7 @@ export interface IUserTableData { actions: IDropdownOption[]; id: number; type: string; + api_only: boolean; } // NOTE: cellProps come from react-table @@ -69,9 +72,54 @@ const generateTableHeaders = ( Header: "Name", disableSortBy: true, accessor: "name", - Cell: (cellProps: ICellProps) => ( - - ), + Cell: (cellProps: ICellProps) => { + const formatter = (val: string) => { + const apiOnlyUser = + "api_only" in cellProps.row.original + ? cellProps.row.original.api_only + : false; + + return ( + <> + {val} + {apiOnlyUser && ( + <> + + API + + + <> + This user was created using fleetctl and +
only has API access.{" "} + + +
+ + )} + + ); + }; + + return ; + }, }, { title: "Role", @@ -206,6 +254,7 @@ const enhanceUserData = ( ), id: user.id, type: "user", + api_only: user.api_only, }; }); }; @@ -221,6 +270,7 @@ const enhanceInviteData = (invites: IInvite[]): IUserTableData[] => { actions: generateActionDropdownOptions(false, true, invite.sso_enabled), id: invite.id, type: "invite", + api_only: false, // api only users are created through fleetctl and not invites }; }); }; diff --git a/frontend/styles/var/mixins.scss b/frontend/styles/var/mixins.scss index b37eb690c8..a6cfb7e4aa 100644 --- a/frontend/styles/var/mixins.scss +++ b/frontend/styles/var/mixins.scss @@ -36,3 +36,14 @@ $max-width: 2560px; margin: 0; padding: $pad-xxlarge 0 54px 0; } + +@mixin grey-badge { + background-color: $ui-fleet-black-25; + color: $core-white; + font-size: $xx-small; + font-weight: 700; + padding: 0 $pad-xsmall; + border-radius: $border-radius; + position: relative; + margin-left: $pad-xsmall; +}