fix(core): Block Public API related REST calls when Public API is not enabled (#9521)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-05-28 14:43:22 +02:00 committed by GitHub
parent e07de837b9
commit ac4e0fbb47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 15 deletions

View file

@ -153,11 +153,6 @@ export const loadPublicApiVersions = async (
};
};
function isApiEnabledByLicense(): boolean {
const license = Container.get(License);
return !license.isAPIDisabled();
}
export function isApiEnabled(): boolean {
return !config.get('publicApi.disabled') && isApiEnabledByLicense();
return !config.get('publicApi.disabled') && !Container.get(License).isAPIDisabled();
}

View file

@ -1,6 +1,6 @@
import validator from 'validator';
import { plainToInstance } from 'class-transformer';
import { Response } from 'express';
import { type RequestHandler, Response } from 'express';
import { randomBytes } from 'crypto';
import { AuthService } from '@/auth/auth.service';
@ -22,6 +22,15 @@ import { ExternalHooks } from '@/ExternalHooks';
import { InternalHooks } from '@/InternalHooks';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { UserRepository } from '@/databases/repositories/user.repository';
import { isApiEnabled } from '@/PublicApi';
export const isApiEnabledMiddleware: RequestHandler = (_, res, next) => {
if (isApiEnabled()) {
next();
} else {
res.status(404).end();
}
};
@RestController('/me')
export class MeController {
@ -185,7 +194,7 @@ export class MeController {
/**
* Creates an API Key
*/
@Post('/api-key')
@Post('/api-key', { middlewares: [isApiEnabledMiddleware] })
async createAPIKey(req: AuthenticatedRequest) {
const apiKey = `n8n_api_${randomBytes(40).toString('hex')}`;
@ -202,7 +211,7 @@ export class MeController {
/**
* Get an API Key
*/
@Get('/api-key')
@Get('/api-key', { middlewares: [isApiEnabledMiddleware] })
async getAPIKey(req: AuthenticatedRequest) {
return { apiKey: req.user.apiKey };
}
@ -210,7 +219,7 @@ export class MeController {
/**
* Deletes an API Key
*/
@Delete('/api-key')
@Delete('/api-key', { middlewares: [isApiEnabledMiddleware] })
async deleteAPIKey(req: AuthenticatedRequest) {
await this.userService.update(req.user.id, { apiKey: null });

View file

@ -31,6 +31,7 @@ import type { CommunityPackagesService } from '@/services/communityPackages.serv
import { Logger } from '@/Logger';
import { UrlService } from './url.service';
import { InternalHooks } from '@/InternalHooks';
import { isApiEnabled } from '@/PublicApi';
@Service()
export class FrontendService {
@ -143,7 +144,7 @@ export class FrontendService {
},
},
publicApi: {
enabled: !config.get('publicApi.disabled') && !this.license.isAPIDisabled(),
enabled: isApiEnabled(),
latestVersion: 1,
path: config.getEnv('publicApi.path'),
swaggerUi: {

View file

@ -1,7 +1,12 @@
import { Container } from 'typedi';
import type { SuperAgentTest } from 'supertest';
import { IsNull } from '@n8n/typeorm';
import validator from 'validator';
import type { User } from '@db/entities/User';
import { UserRepository } from '@db/repositories/user.repository';
import { ProjectRepository } from '@db/repositories/project.repository';
import { SUCCESS_RESPONSE_BODY } from './shared/constants';
import {
randomApiKey,
@ -12,15 +17,38 @@ import {
} from './shared/random';
import * as testDb from './shared/testDb';
import * as utils from './shared/utils/';
import { addApiKey, createUser, createUserShell } from './shared/db/users';
import Container from 'typedi';
import { UserRepository } from '@db/repositories/user.repository';
import { ProjectRepository } from '@/databases/repositories/project.repository';
import { addApiKey, createOwner, createUser, createUserShell } from './shared/db/users';
import config from '@/config';
const testServer = utils.setupTestServer({ endpointGroups: ['me'] });
beforeEach(async () => {
await testDb.truncate(['User']);
config.set('publicApi.disabled', false);
});
describe('When public API is disabled', () => {
let owner: User;
let authAgent: SuperAgentTest;
beforeEach(async () => {
owner = await createOwner();
await addApiKey(owner);
authAgent = testServer.authAgentFor(owner);
config.set('publicApi.disabled', true);
});
test('POST /me/api-key should 404', async () => {
await authAgent.post('/me/api-key').expect(404);
});
test('GET /me/api-key should 404', async () => {
await authAgent.get('/me/api-key').expect(404);
});
test('DELETE /me/api-key should 404', async () => {
await authAgent.delete('/me/api-key').expect(404);
});
});
describe('Owner shell', () => {