Skip to content

Commit

Permalink
fix: normalize casing for API token types before insert (#7972)
Browse files Browse the repository at this point in the history
Fixes a bug where if you had API keys using different casing for the
same type, they'd come out as different types in the API token count
map. To get around it, we normalize the keys to lowercase before
inserting them into the map, taking into account any previous values
that might have existed for that type.

Should fix issues like this:

![image](https://github.com/user-attachments/assets/1fe218ed-7729-4a06-9a10-f4c8c7831bf8)
  • Loading branch information
thomasheartman authored Aug 23, 2024
1 parent 7f7891d commit 4693f7c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
53 changes: 53 additions & 0 deletions src/lib/services/api-token-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
API_TOKEN_CREATED,
API_TOKEN_DELETED,
API_TOKEN_UPDATED,
SYSTEM_USER,
TEST_AUDIT_USER,
} from '../types';
import { addDays, minutesToMilliseconds, subDays } from 'date-fns';
Expand Down Expand Up @@ -216,3 +217,55 @@ describe('API token getTokenWithCache', () => {
expect(apiTokenStoreGet).toHaveBeenCalledTimes(1);
});
});

test('normalizes api token type casing to lowercase', async () => {
const config: IUnleashConfig = createTestConfig();
const { apiTokenStore, apiTokenService, environmentStore } =
createFakeApiTokenService(config);

await environmentStore.create({
name: 'default',
enabled: true,
type: 'test',
sortOrder: 1,
});

const apiTokenStoreInsert = jest.spyOn(apiTokenStore, 'insert');

await apiTokenService.createApiTokenWithProjects(
{
environment: 'default',
// @ts-ignore
type: 'CLIENT',
projects: [],
tokenName: 'uppercase-token',
},
SYSTEM_USER,
);

await apiTokenService.createApiTokenWithProjects(
{
environment: 'default',
// @ts-ignore
type: 'client',
projects: [],
tokenName: 'lowercase-token',
},
SYSTEM_USER,
);

expect(apiTokenStoreInsert).toHaveBeenCalledWith(
expect.objectContaining({
type: 'client',
}),
);

expect(apiTokenStoreInsert).not.toHaveBeenCalledWith(
expect.objectContaining({
type: 'CLIENT',
}),
);

const tokens = await apiTokenStore.getAll();
expect(tokens.every((token) => token.type === 'client')).toBeTruthy();
});
12 changes: 11 additions & 1 deletion src/lib/services/api-token-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,22 @@ export class ApiTokenService {
return this.insertNewApiToken(createNewToken, SYSTEM_USER_AUDIT);
}

private normalizeTokenType(token: IApiTokenCreate): IApiTokenCreate {
const { type, ...rest } = token;
return {
...rest,
type: type.toLowerCase() as ApiTokenType,
};
}

private async insertNewApiToken(
newApiToken: IApiTokenCreate,
auditUser: IAuditUser,
): Promise<IApiToken> {
try {
const token = await this.store.insert(newApiToken);
const token = await this.store.insert(
this.normalizeTokenType(newApiToken),
);
this.activeTokens.push(token);
await this.eventService.storeEvent(
new ApiTokenCreatedEvent({
Expand Down

0 comments on commit 4693f7c

Please sign in to comment.