mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
fix: Put static types files behind authentication (#18660)
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
import type { GlobalConfig } from '@n8n/config';
|
||||||
|
import type { InvalidAuthTokenRepository, UserRepository } from '@n8n/db';
|
||||||
|
import { mock } from 'jest-mock-extended';
|
||||||
|
|
||||||
|
import { AuthService } from '@/auth/auth.service';
|
||||||
|
import type { MfaService } from '@/mfa/mfa.service';
|
||||||
|
import type { JwtService } from '@/services/jwt.service';
|
||||||
|
import type { UrlService } from '@/services/url.service';
|
||||||
|
|
||||||
|
describe('AuthService Browser ID Whitelist', () => {
|
||||||
|
let authService: AuthService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const globalConfig = mock<GlobalConfig>({
|
||||||
|
endpoints: { rest: 'rest' },
|
||||||
|
});
|
||||||
|
const jwtService = mock<JwtService>();
|
||||||
|
const urlService = mock<UrlService>();
|
||||||
|
const userRepository = mock<UserRepository>();
|
||||||
|
const invalidAuthTokenRepository = mock<InvalidAuthTokenRepository>();
|
||||||
|
const mfaService = mock<MfaService>();
|
||||||
|
|
||||||
|
authService = new AuthService(
|
||||||
|
globalConfig,
|
||||||
|
mock(),
|
||||||
|
mock(),
|
||||||
|
jwtService,
|
||||||
|
urlService,
|
||||||
|
userRepository,
|
||||||
|
invalidAuthTokenRepository,
|
||||||
|
mfaService,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('skipBrowserIdCheckEndpoints', () => {
|
||||||
|
it('should include type files in the skip browser ID check endpoints', () => {
|
||||||
|
// Access the private property for testing
|
||||||
|
const skipEndpoints = (authService as any).skipBrowserIdCheckEndpoints;
|
||||||
|
|
||||||
|
expect(skipEndpoints).toContain('/types/nodes.json');
|
||||||
|
expect(skipEndpoints).toContain('/types/credentials.json');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include oauth callback urls in the skip browser ID check endpoints', () => {
|
||||||
|
// Access the private property for testing
|
||||||
|
const skipEndpoints = (authService as any).skipBrowserIdCheckEndpoints;
|
||||||
|
|
||||||
|
expect(skipEndpoints).toContain('/rest/oauth1-credential/callback');
|
||||||
|
expect(skipEndpoints).toContain('/rest/oauth2-credential/callback');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -65,6 +65,10 @@ export class AuthService {
|
|||||||
// oAuth callback urls aren't called by the frontend. therefore we can't send custom header on these requests
|
// oAuth callback urls aren't called by the frontend. therefore we can't send custom header on these requests
|
||||||
`/${restEndpoint}/oauth1-credential/callback`,
|
`/${restEndpoint}/oauth1-credential/callback`,
|
||||||
`/${restEndpoint}/oauth2-credential/callback`,
|
`/${restEndpoint}/oauth2-credential/callback`,
|
||||||
|
|
||||||
|
// Skip browser ID check for type files
|
||||||
|
'/types/nodes.json',
|
||||||
|
'/types/credentials.json',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { jsonParse } from 'n8n-workflow';
|
|||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
|
|
||||||
import { AbstractServer } from '@/abstract-server';
|
import { AbstractServer } from '@/abstract-server';
|
||||||
|
import { AuthService } from '@/auth/auth.service';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { CLI_DIR, EDITOR_UI_DIST_DIR, inE2ETests } from '@/constants';
|
import { CLI_DIR, EDITOR_UI_DIST_DIR, inE2ETests } from '@/constants';
|
||||||
import { ControllerRegistry } from '@/controller.registry';
|
import { ControllerRegistry } from '@/controller.registry';
|
||||||
@@ -318,6 +319,23 @@ export class Server extends AbstractServer {
|
|||||||
const maxAge = Time.days.toMilliseconds;
|
const maxAge = Time.days.toMilliseconds;
|
||||||
const cacheOptions = inE2ETests || inDevelopment ? {} : { maxAge };
|
const cacheOptions = inE2ETests || inDevelopment ? {} : { maxAge };
|
||||||
const { staticCacheDir } = Container.get(InstanceSettings);
|
const { staticCacheDir } = Container.get(InstanceSettings);
|
||||||
|
|
||||||
|
// Protect type files with authentication regardless of UI availability
|
||||||
|
const authService = Container.get(AuthService);
|
||||||
|
const protectedTypeFiles = ['/types/nodes.json', '/types/credentials.json'];
|
||||||
|
protectedTypeFiles.forEach((path) => {
|
||||||
|
this.app.get(
|
||||||
|
path,
|
||||||
|
authService.createAuthMiddleware(true),
|
||||||
|
async (_, res: express.Response) => {
|
||||||
|
res.setHeader('Cache-Control', 'no-cache, must-revalidate');
|
||||||
|
res.sendFile(path.substring(1), {
|
||||||
|
root: staticCacheDir,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
if (frontendService) {
|
if (frontendService) {
|
||||||
this.app.use(
|
this.app.use(
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user