mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-28 22:19:41 -08:00
179 lines
5.6 KiB
TypeScript
179 lines
5.6 KiB
TypeScript
|
import { GlobalConfig } from '@n8n/config';
|
||
|
import { Container } from 'typedi';
|
||
|
|
||
|
import type { ApiKey } from '@/databases/entities/api-key';
|
||
|
import type { User } from '@/databases/entities/user';
|
||
|
import { ApiKeyRepository } from '@/databases/repositories/api-key.repository';
|
||
|
import { PublicApiKeyService } from '@/services/public-api-key.service';
|
||
|
import { mockInstance } from '@test/mocking';
|
||
|
|
||
|
import { createOwnerWithApiKey, createUser, createUserShell } from './shared/db/users';
|
||
|
import { randomValidPassword } from './shared/random';
|
||
|
import * as testDb from './shared/test-db';
|
||
|
import type { SuperAgentTest } from './shared/types';
|
||
|
import * as utils from './shared/utils/';
|
||
|
|
||
|
const testServer = utils.setupTestServer({ endpointGroups: ['apiKeys'] });
|
||
|
let publicApiKeyService: PublicApiKeyService;
|
||
|
|
||
|
beforeAll(() => {
|
||
|
publicApiKeyService = Container.get(PublicApiKeyService);
|
||
|
});
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
await testDb.truncate(['User']);
|
||
|
mockInstance(GlobalConfig, { publicApi: { disabled: false } });
|
||
|
});
|
||
|
|
||
|
describe('When public API is disabled', () => {
|
||
|
let owner: User;
|
||
|
let authAgent: SuperAgentTest;
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
owner = await createOwnerWithApiKey();
|
||
|
|
||
|
authAgent = testServer.authAgentFor(owner);
|
||
|
mockInstance(GlobalConfig, { publicApi: { disabled: true } });
|
||
|
});
|
||
|
|
||
|
test('POST /api-keys should 404', async () => {
|
||
|
await authAgent.post('/api-keys').expect(404);
|
||
|
});
|
||
|
|
||
|
test('GET /api-keys should 404', async () => {
|
||
|
await authAgent.get('/api-keys').expect(404);
|
||
|
});
|
||
|
|
||
|
test('DELETE /api-key/:id should 404', async () => {
|
||
|
await authAgent.delete(`/api-keys/${1}`).expect(404);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('Owner shell', () => {
|
||
|
let ownerShell: User;
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
ownerShell = await createUserShell('global:owner');
|
||
|
});
|
||
|
|
||
|
test('POST /api-keys should create an api key', async () => {
|
||
|
const newApiKeyResponse = await testServer.authAgentFor(ownerShell).post('/api-keys');
|
||
|
|
||
|
const newApiKey = newApiKeyResponse.body.data as ApiKey;
|
||
|
|
||
|
expect(newApiKeyResponse.statusCode).toBe(200);
|
||
|
expect(newApiKey).toBeDefined();
|
||
|
|
||
|
const newStoredApiKey = await Container.get(ApiKeyRepository).findOneByOrFail({
|
||
|
userId: ownerShell.id,
|
||
|
});
|
||
|
|
||
|
expect(newStoredApiKey).toEqual({
|
||
|
id: expect.any(String),
|
||
|
label: 'My API Key',
|
||
|
userId: ownerShell.id,
|
||
|
apiKey: newApiKey.apiKey,
|
||
|
createdAt: expect.any(Date),
|
||
|
updatedAt: expect.any(Date),
|
||
|
});
|
||
|
});
|
||
|
|
||
|
test('GET /api-keys should fetch the api key redacted', async () => {
|
||
|
const newApiKeyResponse = await testServer.authAgentFor(ownerShell).post('/api-keys');
|
||
|
|
||
|
const retrieveAllApiKeysResponse = await testServer.authAgentFor(ownerShell).get('/api-keys');
|
||
|
|
||
|
expect(retrieveAllApiKeysResponse.statusCode).toBe(200);
|
||
|
|
||
|
expect(retrieveAllApiKeysResponse.body.data[0]).toEqual({
|
||
|
id: newApiKeyResponse.body.data.id,
|
||
|
label: 'My API Key',
|
||
|
userId: ownerShell.id,
|
||
|
apiKey: publicApiKeyService.redactApiKey(newApiKeyResponse.body.data.apiKey),
|
||
|
createdAt: expect.any(String),
|
||
|
updatedAt: expect.any(String),
|
||
|
});
|
||
|
});
|
||
|
|
||
|
test('DELETE /api-keys/:id should delete the api key', async () => {
|
||
|
const newApiKeyResponse = await testServer.authAgentFor(ownerShell).post('/api-keys');
|
||
|
|
||
|
const deleteApiKeyResponse = await testServer
|
||
|
.authAgentFor(ownerShell)
|
||
|
.delete(`/api-keys/${newApiKeyResponse.body.data.id}`);
|
||
|
|
||
|
const retrieveAllApiKeysResponse = await testServer.authAgentFor(ownerShell).get('/api-keys');
|
||
|
|
||
|
expect(deleteApiKeyResponse.body.data.success).toBe(true);
|
||
|
expect(retrieveAllApiKeysResponse.body.data.length).toBe(0);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('Member', () => {
|
||
|
const memberPassword = randomValidPassword();
|
||
|
let member: User;
|
||
|
|
||
|
beforeEach(async () => {
|
||
|
member = await createUser({
|
||
|
password: memberPassword,
|
||
|
role: 'global:member',
|
||
|
});
|
||
|
await utils.setInstanceOwnerSetUp(true);
|
||
|
});
|
||
|
|
||
|
test('POST /api-keys should create an api key', async () => {
|
||
|
const newApiKeyResponse = await testServer.authAgentFor(member).post('/api-keys');
|
||
|
|
||
|
expect(newApiKeyResponse.statusCode).toBe(200);
|
||
|
expect(newApiKeyResponse.body.data.apiKey).toBeDefined();
|
||
|
expect(newApiKeyResponse.body.data.apiKey).not.toBeNull();
|
||
|
|
||
|
const newStoredApiKey = await Container.get(ApiKeyRepository).findOneByOrFail({
|
||
|
userId: member.id,
|
||
|
});
|
||
|
|
||
|
expect(newStoredApiKey).toEqual({
|
||
|
id: expect.any(String),
|
||
|
label: 'My API Key',
|
||
|
userId: member.id,
|
||
|
apiKey: newApiKeyResponse.body.data.apiKey,
|
||
|
createdAt: expect.any(Date),
|
||
|
updatedAt: expect.any(Date),
|
||
|
});
|
||
|
});
|
||
|
|
||
|
test('GET /api-keys should fetch the api key redacted', async () => {
|
||
|
const newApiKeyResponse = await testServer.authAgentFor(member).post('/api-keys');
|
||
|
|
||
|
const retrieveAllApiKeysResponse = await testServer.authAgentFor(member).get('/api-keys');
|
||
|
|
||
|
expect(retrieveAllApiKeysResponse.statusCode).toBe(200);
|
||
|
|
||
|
expect(retrieveAllApiKeysResponse.body.data[0]).toEqual({
|
||
|
id: newApiKeyResponse.body.data.id,
|
||
|
label: 'My API Key',
|
||
|
userId: member.id,
|
||
|
apiKey: publicApiKeyService.redactApiKey(newApiKeyResponse.body.data.apiKey),
|
||
|
createdAt: expect.any(String),
|
||
|
updatedAt: expect.any(String),
|
||
|
});
|
||
|
|
||
|
expect(newApiKeyResponse.body.data.apiKey).not.toEqual(
|
||
|
retrieveAllApiKeysResponse.body.data[0].apiKey,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('DELETE /api-keys/:id should delete the api key', async () => {
|
||
|
const newApiKeyResponse = await testServer.authAgentFor(member).post('/api-keys');
|
||
|
|
||
|
const deleteApiKeyResponse = await testServer
|
||
|
.authAgentFor(member)
|
||
|
.delete(`/api-keys/${newApiKeyResponse.body.data.id}`);
|
||
|
|
||
|
const retrieveAllApiKeysResponse = await testServer.authAgentFor(member).get('/api-keys');
|
||
|
|
||
|
expect(deleteApiKeyResponse.body.data.success).toBe(true);
|
||
|
expect(retrieveAllApiKeysResponse.body.data.length).toBe(0);
|
||
|
});
|
||
|
});
|