File tree Expand file tree Collapse file tree 7 files changed +298
-99
lines changed
website/docs/configuration Expand file tree Collapse file tree 7 files changed +298
-99
lines changed Original file line number Diff line number Diff line change 2424 "description" : " Provide domains to use alternative to the defaults" ,
2525 "type" : " object"
2626 },
27+ "rateLimit" : {
28+ "description" : " API Rate limiting configuration." ,
29+ "type" : " object" ,
30+ "properties" : {
31+ "windowMs" : {
32+ "type" : " number" ,
33+ "description" : " How long to remember requests for, in milliseconds (default 10 mins)."
34+ },
35+ "limit" : {
36+ "type" : " number" ,
37+ "description" : " How many requests to allow (default 150)."
38+ },
39+ "statusCode" : {
40+ "type" : " number" ,
41+ "description" : " HTTP status code after limit is reached (default is 429)."
42+ },
43+ "message" : {
44+ "type" : " string" ,
45+ "description" : " Response to return after limit is reached."
46+ }
47+ },
48+ "required" : [" windowMs" , " limit" ],
49+ "additionalProperties" : false
50+ },
2751 "privateOrganizations" : {
2852 "description" : " Pattern searches for listed private organizations are disabled" ,
2953 "type" : " array"
Original file line number Diff line number Diff line change 22 "proxyUrl" : " https://github.com" ,
33 "cookieSecret" : " cookie secret" ,
44 "sessionMaxAgeHours" : 12 ,
5+ "rateLimit" : {
6+ "windowMs" : 60000 ,
7+ "limit" : 150
8+ },
59 "tempPassword" : {
610 "sendEmail" : false ,
711 "emailConfig" : {}
Original file line number Diff line number Diff line change 66 Authentication ,
77 AuthorisedRepo ,
88 Database ,
9+ RateLimitConfig ,
910 TempPasswordConfig ,
1011 UserSettings ,
1112} from './types' ;
@@ -30,6 +31,8 @@ let _urlShortener: string = defaultSettings.urlShortener;
3031let _contactEmail : string = defaultSettings . contactEmail ;
3132let _csrfProtection : boolean = defaultSettings . csrfProtection ;
3233let _domains : Record < string , unknown > = defaultSettings . domains ;
34+ let _rateLimit : RateLimitConfig = defaultSettings . rateLimit ;
35+
3336// These are not always present in the default config file, so casting is required
3437let _tlsEnabled = defaultSettings . tls . enabled ;
3538let _tlsKeyPemPath = defaultSettings . tls . key ;
@@ -99,6 +102,7 @@ export const logConfiguration = () => {
99102 console . log ( `authorisedList = ${ JSON . stringify ( getAuthorisedList ( ) ) } ` ) ;
100103 console . log ( `data sink = ${ JSON . stringify ( getDatabase ( ) ) } ` ) ;
101104 console . log ( `authentication = ${ JSON . stringify ( getAuthentication ( ) ) } ` ) ;
105+ console . log ( `rateLimit = ${ JSON . stringify ( getRateLimit ( ) ) } ` ) ;
102106} ;
103107
104108export const getAPIs = ( ) => {
@@ -217,3 +221,10 @@ export const getDomains = () => {
217221 }
218222 return _domains ;
219223} ;
224+
225+ export const getRateLimit = ( ) => {
226+ if ( _userSettings && _userSettings . rateLimit ) {
227+ _rateLimit = _userSettings . rateLimit ;
228+ }
229+ return _rateLimit ;
230+ } ;
Original file line number Diff line number Diff line change 1+ import { Options as RateLimitOptions } from 'express-rate-limit' ;
2+
13export interface UserSettings {
24 authorisedList : AuthorisedRepo [ ] ;
35 sink : Database [ ] ;
@@ -18,6 +20,7 @@ export interface UserSettings {
1820 contactEmail : string ;
1921 csrfProtection : boolean ;
2022 domains : Record < string , unknown > ;
23+ rateLimit : RateLimitConfig ;
2124}
2225
2326export interface TLSConfig {
@@ -50,3 +53,7 @@ export interface TempPasswordConfig {
5053 sendEmail : boolean ;
5154 emailConfig : Record < string , unknown > ;
5255}
56+
57+ export type RateLimitConfig = Partial <
58+ Pick < RateLimitOptions , 'windowMs' | 'limit' | 'message' | 'statusCode' >
59+ > ;
Original file line number Diff line number Diff line change @@ -9,10 +9,7 @@ const db = require('../db');
99const rateLimit = require ( 'express-rate-limit' ) ;
1010const lusca = require ( 'lusca' ) ;
1111
12- const limiter = rateLimit ( {
13- windowMs : 15 * 60 * 1000 , // 15 minutes
14- max : 100 , // limit each IP to 100 requests per windowMs
15- } ) ;
12+ const limiter = rateLimit ( config . getRateLimit ( ) ) ;
1613
1714const { GIT_PROXY_UI_PORT : uiPort } = require ( '../config/env' ) . serverConfig ;
1815
Original file line number Diff line number Diff line change @@ -16,6 +16,7 @@ describe('default configuration', function () {
1616 expect ( config . getDatabase ( ) ) . to . be . eql ( defaultSettings . sink [ 0 ] ) ;
1717 expect ( config . getTempPasswordConfig ( ) ) . to . be . eql ( defaultSettings . tempPassword ) ;
1818 expect ( config . getAuthorisedList ( ) ) . to . be . eql ( defaultSettings . authorisedList ) ;
19+ expect ( config . getRateLimit ( ) ) . to . be . eql ( defaultSettings . rateLimit ) ;
1920 expect ( config . getTLSKeyPemPath ( ) ) . to . be . eql ( defaultSettings . tls . key ) ;
2021 expect ( config . getTLSCertPemPath ( ) ) . to . be . eql ( defaultSettings . tls . cert ) ;
2122 } ) ;
@@ -107,6 +108,21 @@ describe('user configuration', function () {
107108 expect ( config . getTLSCertPemPath ( ) ) . to . be . eql ( user . tls . cert ) ;
108109 } ) ;
109110
111+ it ( 'should override default settings for rate limiting' , function ( ) {
112+ const limitConfig = {
113+ rateLimit : {
114+ windowMs : 60000 ,
115+ limit : 1500 ,
116+ } ,
117+ } ;
118+ fs . writeFileSync ( tempUserFile , JSON . stringify ( limitConfig ) ) ;
119+
120+ const config = require ( '../src/config' ) ;
121+
122+ expect ( config . getRateLimit ( ) . windowMs ) . to . be . eql ( limitConfig . rateLimit . windowMs ) ;
123+ expect ( config . getRateLimit ( ) . limit ) . to . be . eql ( limitConfig . rateLimit . limit ) ;
124+ } ) ;
125+
110126 afterEach ( function ( ) {
111127 fs . rmSync ( tempUserFile ) ;
112128 fs . rmdirSync ( tempDir ) ;
You can’t perform that action at this time.
0 commit comments