diff --git a/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.test.tsx b/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.test.tsx
index 3f0e7f924d..73f9ec6680 100644
--- a/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.test.tsx
+++ b/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.test.tsx
@@ -1,7 +1,68 @@
import { render } from 'utils/testRenderer';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import { ApiTokenIcon } from './ApiTokenIcon';
+import { ApiTokenIcon, isOrphanedToken } from './ApiTokenIcon';
+
+describe('isOrphanedToken', () => {
+ it('should be true for wildcard tokens with secret indicating it is orphaned', () => {
+ expect(
+ isOrphanedToken({
+ secret: '[]:development.be7536c3a160ff15e3a92da45de531dd54bc1ae15d8455c0476f086b',
+ projects: ['*'],
+ project: '*',
+ }),
+ ).toBe(true);
+ expect(
+ isOrphanedToken({
+ secret: 'test:development.be7536c3a160ff15e3a92da45de531dd54bc1ae15d8455c0476f086b',
+ projects: ['*'],
+ project: '*',
+ }),
+ ).toBe(true);
+ });
+
+ it('should be false for true wildcard tokens', () => {
+ expect(
+ isOrphanedToken({
+ secret: '*:development.be7536c3a160ff15e3a92da45de531dd54bc1ae15d8455c0476f086b',
+ projects: ['*'],
+ project: '*',
+ }),
+ ).toBe(false);
+ });
+
+ it('should be false for secrets in v1 format', () => {
+ expect(
+ isOrphanedToken({
+ secret: 'be44368985f7fb3237c584ef86f3d6bdada42ddbd63a019d26955178',
+ projects: ['*'],
+ project: '*',
+ }),
+ ).toBe(false);
+ });
+
+ it('should be false if there are projects assigned to a token', () => {
+ expect(
+ isOrphanedToken({
+ secret: 'test:development.be7536c3a160ff15e3a92da45de531dd54bc1ae15d8455c0476f086b',
+ projects: ['test'],
+ project: 'test',
+ }),
+ ).toBe(false);
+ expect(
+ isOrphanedToken({
+ secret: '[]:development.be7536c3a160ff15e3a92da45de531dd54bc1ae15d8455c0476f086b',
+ projects: ['a', 'b'],
+ }),
+ ).toBe(false);
+ expect(
+ isOrphanedToken({
+ secret: '[]:development.be7536c3a160ff15e3a92da45de531dd54bc1ae15d8455c0476f086b',
+ projects: ['a'],
+ }),
+ ).toBe(false);
+ });
+});
describe('ApiTokenIcon', () => {
it('should show warning icon if it is an orphaned token', async () => {
@@ -16,7 +77,10 @@ describe('ApiTokenIcon', () => {
it('should show tooltip with warning message if it is an orphaned token', async () => {
const user = userEvent.setup();
render(
- ,
+ ,
);
const errorIcon = await screen.findByTestId('orphaned-token-icon');
@@ -26,18 +90,13 @@ describe('ApiTokenIcon', () => {
expect(tooltip).toHaveTextContent(/orphaned token/);
});
- it('should not show warning icon if token is in v1 format', async () => {
- render(
- ,
- );
-
- const errorIcon = await screen.queryByTestId('orphaned-token-icon');
- expect(errorIcon).toBeNull();
- });
-
it('should not show warning for true wildcard tokens', async () => {
render(
- ,
+ ,
);
const errorIcon = await screen.queryByTestId('orphaned-token-icon');
diff --git a/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.tsx b/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.tsx
index ab828d3b38..3f1df514f5 100644
--- a/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.tsx
+++ b/frontend/src/component/admin/apiToken/ApiTokenIcon/ApiTokenIcon.tsx
@@ -11,12 +11,23 @@ interface IApiTokenIconProps {
secret?: string;
}
-export const ApiTokenIcon: FC = ({ secret }) => {
+export const isOrphanedToken = ({
+ secret,
+ project,
+ projects,
+}: IApiTokenIconProps): boolean => {
const tokenFormat = secret?.includes(':') ? 'v2' : 'v1'; // see https://docs.getunleash.io/reference/api-tokens-and-client-keys#format
- const isWildcardToken = secret?.startsWith('*:');
- const isOrphanedToken = tokenFormat === 'v2' && !isWildcardToken;
+ const isWildcardSecret = secret?.startsWith('*:');
+ const hasProjects =
+ (projects && projects?.length > 1) ||
+ (projects?.length === 1 && projects[0] !== '*') ||
+ (project && project !== '*');
- if (isOrphanedToken) {
+ return tokenFormat === 'v2' && !isWildcardSecret && !hasProjects;
+};
+
+export const ApiTokenIcon: FC = ({ ...props }) => {
+ if (isOrphanedToken(props)) {
return (
(
-
+
),
disableSortBy: true,
disableGlobalFilter: true,