Skip to content

Commit fa749f8

Browse files
authored
Merge pull request #1599 from multiversx/resticted-routes
block swagger routes
2 parents 79b2062 + aa70442 commit fa749f8

11 files changed

Lines changed: 114 additions & 1 deletion

config/config.devnet-old.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,8 @@ inflation:
129129
nftProcess:
130130
parallelism: 1
131131
maxRetries: 3
132+
restrictedRoutes:
133+
enabled: true
134+
routes:
135+
- '/package.json'
136+
- '/docs/package.json'

config/config.devnet.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,8 @@ compression:
204204
level: 6
205205
threshold: 1024
206206
chunkSize: 16384
207+
restrictedRoutes:
208+
enabled: true
209+
routes:
210+
- '/package.json'
211+
- '/docs/package.json'

config/config.e2e-mocked.mainnet.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,8 @@ test:
8686
transaction-action:
8787
mex:
8888
microServiceUrl: 'https://graph.xexchange.com/graphql'
89+
restrictedRoutes:
90+
enabled: true
91+
routes:
92+
- '/package.json'
93+
- '/docs/package.json'

config/config.e2e.mainnet.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,9 @@ stakingV5Inflation:
197197
- 1262802
198198
nftProcess:
199199
parallelism: 1
200-
maxRetries: 3
200+
maxRetries: 3
201+
restrictedRoutes:
202+
enabled: true
203+
routes:
204+
- '/package.json'
205+
- '/docs/package.json'

config/config.mainnet.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,9 @@ customUrlHeaders:
212212
- urlPattern: ''
213213
headers:
214214
x-custom-auth: ''
215+
restrictedRoutes:
216+
enabled: true
217+
routes:
218+
- '/package.json'
219+
- '/docs/package.json'
220+

config/config.testnet.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,8 @@ compression:
207207
level: 6
208208
threshold: 1024
209209
chunkSize: 16384
210+
restrictedRoutes:
211+
enabled: true
212+
routes:
213+
- '/package.json'
214+
- '/docs/package.json'

src/common/api-config/api.config.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,4 +1104,12 @@ export class ApiConfigService {
11041104

11051105
return timestamp;
11061106
}
1107+
1108+
isRestrictedRoutesEnabled(): boolean {
1109+
return this.configService.get<boolean>('restrictedRoutes.enabled') ?? false;
1110+
}
1111+
1112+
getRestrictedRoutes(): string[] {
1113+
return this.configService.get<string[]>('restrictedRoutes.routes') ?? [];
1114+
}
11071115
}

src/main.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import * as requestIp from 'request-ip';
3838
import compression from 'compression';
3939
import { IoAdapter } from '@nestjs/platform-socket.io';
4040
import { WebsocketSubscriptionModule } from './crons/websocket/websocket.subscription.module';
41+
import { RestrictedRoutesMiddleware } from './utils/restricted.routes.middleware';
4142

4243
async function bootstrap() {
4344
const logger = new Logger('Bootstrapper');
@@ -186,9 +187,16 @@ async function bootstrap() {
186187
logger.log(`Guest caching enabled: ${apiConfigService.isGuestCacheFeatureActive()}`);
187188
logger.log(`Transaction pool enabled: ${apiConfigService.isTransactionPoolEnabled()}`);
188189
logger.log(`Transaction pool cache warmer enabled: ${apiConfigService.isTransactionPoolCacheWarmerEnabled()}`);
190+
191+
logger.log(`Restricted routes enabled: ${apiConfigService.isRestrictedRoutesEnabled()}`);
189192
}
190193

191194
async function configurePublicApp(publicApp: NestExpressApplication, apiConfigService: ApiConfigService) {
195+
if (apiConfigService.isRestrictedRoutesEnabled()) {
196+
const restrictedRoutesMiddleware = publicApp.get(RestrictedRoutesMiddleware);
197+
publicApp.use(restrictedRoutesMiddleware.use.bind(restrictedRoutesMiddleware));
198+
}
199+
192200
if (apiConfigService.getCompressionEnabled()) {
193201
publicApp.use(compression({
194202
filter: (req: any, res: any) => {

src/public.app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { GuestCacheService } from '@multiversx/sdk-nestjs-cache';
99
import { LoggingModule } from '@multiversx/sdk-nestjs-common';
1010
import { DynamicModuleUtils } from './utils/dynamic.module.utils';
1111
import { LocalCacheController } from './endpoints/caching/local.cache.controller';
12+
import { RestrictedRoutesMiddleware } from './utils/restricted.routes.middleware';
1213

1314
@Module({
1415
imports: [
@@ -23,6 +24,7 @@ import { LocalCacheController } from './endpoints/caching/local.cache.controller
2324
providers: [
2425
DynamicModuleUtils.getNestJsApiConfigService(),
2526
GuestCacheService,
27+
RestrictedRoutesMiddleware,
2628
],
2729
exports: [
2830
EndpointsServicesModule,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { NotFoundException } from '@nestjs/common';
2+
import { Request, Response } from 'express';
3+
import { ApiConfigService } from 'src/common/api-config/api.config.service';
4+
import { RestrictedRoutesMiddleware } from 'src/utils/restricted.routes.middleware';
5+
6+
describe('RestrictedRoutesMiddleware', () => {
7+
let middleware: RestrictedRoutesMiddleware;
8+
let apiConfigService: jest.Mocked<ApiConfigService>;
9+
10+
beforeEach(() => {
11+
apiConfigService = {
12+
getRestrictedRoutes: jest.fn(),
13+
} as unknown as jest.Mocked<ApiConfigService>;
14+
15+
middleware = new RestrictedRoutesMiddleware(apiConfigService);
16+
});
17+
18+
it('should throw NotFoundException when route is restricted', () => {
19+
apiConfigService.getRestrictedRoutes.mockReturnValue(['/blocked']);
20+
21+
const req = {
22+
path: '/blocked',
23+
} as Request;
24+
const res = {} as Response;
25+
const next = jest.fn();
26+
27+
expect(() => middleware.use(req, res, next)).toThrow(NotFoundException);
28+
expect(() => middleware.use(req, res, next)).toThrow('Cannot GET /blocked');
29+
expect(next).not.toHaveBeenCalled();
30+
});
31+
32+
it('should call next when route is not restricted', () => {
33+
apiConfigService.getRestrictedRoutes.mockReturnValue(['/blocked']);
34+
35+
const req = {
36+
path: '/allowed',
37+
} as Request;
38+
const res = {} as Response;
39+
const next = jest.fn();
40+
41+
middleware.use(req, res, next);
42+
43+
expect(next).toHaveBeenCalledTimes(1);
44+
});
45+
});

0 commit comments

Comments
 (0)