feat(core): Add scopes to API Keys (#14176)

Co-authored-by: Charlie Kolb <charlie@n8n.io>
Co-authored-by: Danny Martini <danny@n8n.io>
This commit is contained in:
Ricardo Espinoza
2025-04-16 09:03:16 -04:00
committed by GitHub
parent bc12f662e7
commit e1b9407fe9
65 changed files with 3216 additions and 125 deletions

View File

@@ -31,17 +31,20 @@ describe('ApiKeysController', () => {
label: 'My API Key',
apiKey: 'apiKey123',
createdAt: new Date(),
scopes: ['user:create'],
} as ApiKey;
const req = mock<AuthenticatedRequest>({ user: mock<User>({ id: '123' }) });
publicApiKeyService.apiKeyHasValidScopesForRole.mockReturnValue(true);
publicApiKeyService.createPublicApiKeyForUser.mockResolvedValue(apiKeyData);
publicApiKeyService.redactApiKey.mockImplementation(() => '***123');
// Act
const newApiKey = await controller.createAPIKey(req, mock(), mock());
const newApiKey = await controller.createApiKey(req, mock(), mock());
// Assert
@@ -54,6 +57,7 @@ describe('ApiKeysController', () => {
apiKey: '***123',
createdAt: expect.any(Date),
rawApiKey: 'apiKey123',
scopes: ['user:create'],
}),
);
expect(eventService.emit).toHaveBeenCalledWith(
@@ -61,6 +65,32 @@ describe('ApiKeysController', () => {
expect.objectContaining({ user: req.user, publicApi: false }),
);
});
it('should fail to create API key if user uses a scope not allow for its role', async () => {
// Arrange
const req = mock<AuthenticatedRequest>({ user: mock<User>({ id: '123' }) });
publicApiKeyService.apiKeyHasValidScopesForRole.mockReturnValue(false);
// Act and Assert
await expect(controller.createApiKey(req, mock(), mock())).rejects.toThrowError();
});
});
describe('updateApiKey', () => {
it('should fail to update API key if user uses a scope not allow for its role', async () => {
// Arrange
const req = mock<AuthenticatedRequest>({ user: mock<User>({ id: '123' }) });
publicApiKeyService.apiKeyHasValidScopesForRole.mockReturnValue(false);
// Act and Assert
await expect(controller.updateApiKey(req, mock(), mock(), mock())).rejects.toThrowError();
});
});
describe('getAPIKeys', () => {
@@ -82,7 +112,7 @@ describe('ApiKeysController', () => {
// Act
const apiKeys = await controller.getAPIKeys(req);
const apiKeys = await controller.getApiKeys(req);
// Assert
@@ -109,7 +139,7 @@ describe('ApiKeysController', () => {
// Act
await controller.deleteAPIKey(req, mock(), user.id);
await controller.deleteApiKey(req, mock(), user.id);
publicApiKeyService.deleteApiKeyForUser.mockResolvedValue();