import { UserPermission } from '../../services/userManagementService/index.js'; import { Mutation as MutationResolvers, Query as QueryResolvers, } from './apiKey.js'; const Query = QueryResolvers as { apiKey: ( parent: unknown, args: Record, ctx: unknown, ) => Promise; }; const Mutation = MutationResolvers as { rotateApiKey: ( parent: unknown, args: { input: { name: string; description?: string | null } }, ctx: unknown, ) => Promise; rotateWebhookSigningKey: ( parent: unknown, args: Record, ctx: unknown, ) => Promise; }; describe('apiKey resolvers', () => { function makeCtx(permissions: readonly UserPermission[]) { const getActiveApiKeyForOrg = jest.fn(async () => ({ key: 'secret' })); const rotateApiKey = jest.fn(); const rotateWebhookSigningKey = jest.fn(); const ctx = { getUser: () => ({ id: 'user-1', orgId: 'org-1', getPermissions: () => permissions, }), services: { ApiKeyService: { getActiveApiKeyForOrg, rotateApiKey }, }, dataSources: { orgAPI: { rotateWebhookSigningKey } }, }; return { ctx, getActiveApiKeyForOrg, rotateApiKey, rotateWebhookSigningKey, }; } describe('Query.apiKey', () => { it('throws unauthenticatedError when caller is not authenticated', async () => { const { ctx, getActiveApiKeyForOrg } = makeCtx([ UserPermission.MANAGE_ORG, ]); const unauthenticatedCtx = { ...ctx, getUser: () => null }; await expect(Query.apiKey({}, {}, unauthenticatedCtx)).rejects.toThrow( 'Authenticated user required', ); expect(getActiveApiKeyForOrg).not.toHaveBeenCalled(); }); it('throws forbiddenError when caller lacks MANAGE_ORG', async () => { const { ctx, getActiveApiKeyForOrg } = makeCtx([UserPermission.VIEW_MRT]); await expect(Query.apiKey({}, {}, ctx)).rejects.toThrow( 'User does not have permission to view the org API key', ); expect(getActiveApiKeyForOrg).not.toHaveBeenCalled(); }); it('returns the existence indicator when caller has MANAGE_ORG', async () => { const { ctx, getActiveApiKeyForOrg } = makeCtx([ UserPermission.MANAGE_ORG, ]); await expect(Query.apiKey({}, {}, ctx)).resolves.toBe( 'API key exists (hidden for security)', ); expect(getActiveApiKeyForOrg).toHaveBeenCalledWith('org-1'); }); }); describe('Mutation.rotateApiKey', () => { it('throws unauthenticatedError when caller is not authenticated', async () => { const { ctx, rotateApiKey } = makeCtx([UserPermission.MANAGE_ORG]); const unauthenticatedCtx = { ...ctx, getUser: () => null }; await expect( Mutation.rotateApiKey( {}, { input: { name: 'k', description: null } }, unauthenticatedCtx, ), ).rejects.toThrow('Authenticated user required'); expect(rotateApiKey).not.toHaveBeenCalled(); }); it('throws forbiddenError when caller lacks MANAGE_ORG', async () => { const { ctx, rotateApiKey } = makeCtx([UserPermission.VIEW_MRT]); await expect( Mutation.rotateApiKey( {}, { input: { name: 'k', description: null } }, ctx, ), ).rejects.toThrow('User does not have permission to rotate the API key'); expect(rotateApiKey).not.toHaveBeenCalled(); }); }); describe('Mutation.rotateWebhookSigningKey', () => { it('throws unauthenticatedError when caller is not authenticated', async () => { const { ctx, rotateWebhookSigningKey } = makeCtx([ UserPermission.MANAGE_ORG, ]); const unauthenticatedCtx = { ...ctx, getUser: () => null }; await expect( Mutation.rotateWebhookSigningKey({}, {}, unauthenticatedCtx), ).rejects.toThrow('Authenticated user required'); expect(rotateWebhookSigningKey).not.toHaveBeenCalled(); }); it('throws forbiddenError when caller lacks MANAGE_ORG', async () => { const { ctx, rotateWebhookSigningKey } = makeCtx([ UserPermission.VIEW_MRT, ]); await expect( Mutation.rotateWebhookSigningKey({}, {}, ctx), ).rejects.toThrow( 'User does not have permission to rotate the webhook signing key', ); expect(rotateWebhookSigningKey).not.toHaveBeenCalled(); }); }); });