diff --git a/packages/server/test/index.test.ts b/packages/server/test/index.test.ts index 8c038f44f62..08164c7b00a 100644 --- a/packages/server/test/index.test.ts +++ b/packages/server/test/index.test.ts @@ -3,6 +3,7 @@ import { getRunningExpressApp } from '../src/utils/getRunningExpressApp' import { organizationUserRouteTest } from './routes/v1/organization-user.route.test' import { userRouteTest } from './routes/v1/user.route.test' import { apiKeyTest } from './utils/api-key.util.test' +import { validateKeyTest } from './utils/validateKey.util.test' // ⏱️ Extend test timeout to 6 minutes for long setups (increase as tests grow) jest.setTimeout(360000) @@ -25,4 +26,5 @@ describe('Routes Test', () => { describe('Utils Test', () => { apiKeyTest() + validateKeyTest() }) diff --git a/packages/server/test/utils/validateKey.util.test.ts b/packages/server/test/utils/validateKey.util.test.ts new file mode 100644 index 00000000000..307f0a57012 --- /dev/null +++ b/packages/server/test/utils/validateKey.util.test.ts @@ -0,0 +1,110 @@ +import { validateChatflowAPIKey, validateAPIKey, getAPIKeyWorkspaceID } from '../../src/utils/validateKey' +import apikeyService from '../../src/services/apikey' +import { compareKeys } from '../../src/utils/apiKey' +import { Request } from 'express' + +jest.mock('../../src/services/apikey') +jest.mock('../../src/utils/apiKey') + +const mockedCompareKeys = compareKeys as jest.Mock +const mockedApikeyService = apikeyService as jest.Mocked + +const createMockRequest = (headers: Record = {}): Request => { + return { + headers, + cookies: {}, + query: {}, + params: {}, + body: {}, + get: jest.fn() + } as unknown as Request +} + +export function validateKeyTest() { + describe('Validate Key Utils', () => { + describe('validateChatflowAPIKey', () => { + it('should return true if chatflow has no apikeyid', async () => { + const req = createMockRequest() + const result = await validateChatflowAPIKey(req, { apikeyid: null } as any) + expect(result).toBe(true) + }) + + it('should return false if apikeyid exists but no Authorization header', async () => { + const req = createMockRequest() + const result = await validateChatflowAPIKey(req, { apikeyid: 'abc' } as any) + expect(result).toBe(false) + }) + + it('should return false if no matching key is found', async () => { + mockedApikeyService.getAllApiKeys.mockResolvedValueOnce([]) + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await validateChatflowAPIKey(req, { apikeyid: 'abc' } as any) + expect(result).toBe(false) + }) + + it('should return false if key does not match', async () => { + mockedApikeyService.getAllApiKeys.mockResolvedValueOnce([{ id: 'abc', apiSecret: 'secret' }]) + mockedCompareKeys.mockReturnValueOnce(false) + + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await validateChatflowAPIKey(req, { apikeyid: 'abc' } as any) + expect(result).toBe(false) + }) + + it('should return true if key matches', async () => { + mockedApikeyService.getAllApiKeys.mockResolvedValueOnce([{ id: 'abc', apiSecret: 'secret' }]) + mockedCompareKeys.mockReturnValueOnce(true) + + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await validateChatflowAPIKey(req, { apikeyid: 'abc' } as any) + expect(result).toBe(true) + }) + }) + + describe('validateAPIKey', () => { + it('should return false if no Authorization header', async () => { + const req = createMockRequest() + const result = await validateAPIKey(req) + expect(result).toBe(false) + }) + + it('should return false if no matching apiKey', async () => { + mockedApikeyService.getAllApiKeys.mockResolvedValueOnce([]) + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await validateAPIKey(req) + expect(result).toBe(false) + }) + + it('should return false if apiKey does not match', async () => { + mockedApikeyService.getAllApiKeys.mockResolvedValueOnce([{ apiKey: 'someKey', apiSecret: 'secret' }]) + mockedCompareKeys.mockReturnValueOnce(false) + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await validateAPIKey(req) + expect(result).toBe(false) + }) + + it('should return true if apiKey matches', async () => { + mockedApikeyService.getAllApiKeys.mockResolvedValueOnce([{ apiKey: 'someKey', apiSecret: 'secret' }]) + mockedCompareKeys.mockReturnValueOnce(true) + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await validateAPIKey(req) + expect(result).toBe(true) + }) + }) + + describe('getAPIKeyWorkspaceID', () => { + it('should return undefined if no Authorization header', async () => { + const req = createMockRequest() + const result = await getAPIKeyWorkspaceID(req) + expect(result).toBeUndefined() + }) + + it('should return undefined if key is not found', async () => { + mockedApikeyService.getApiKey.mockResolvedValueOnce(undefined) + const req = createMockRequest({ authorization: 'Bearer someKey' }) + const result = await getAPIKeyWorkspaceID(req) + expect(result).toBeUndefined() + }) + }) + }) +}