2015-10-08 12:27:09 -04:00
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
2015-09-21 19:01:52 -07:00
// See License.txt for license information.
2015-11-19 21:12:56 -05:00
import * as Client from '../../utils/client.jsx' ;
import * as AsyncClient from '../../utils/async_client.jsx' ;
2015-09-21 19:01:52 -07:00
2016-01-27 15:49:26 -03:00
import { injectIntl , intlShape , defineMessages , FormattedMessage } from 'mm-intl' ;
const holders = defineMessages ( {
queriesExample : {
id : 'admin.rate.queriesExample' ,
defaultMessage : 'Ex "10"'
} ,
memoryExample : {
id : 'admin.rate.memoryExample' ,
defaultMessage : 'Ex "10000"'
} ,
httpHeaderExample : {
id : 'admin.rate.httpHeaderExample' ,
defaultMessage : 'Ex "X-Real-IP", "X-Forwarded-For"'
} ,
saving : {
id : 'admin.rate.saving' ,
defaultMessage : 'Saving Config...'
}
} ) ;
class RateSettings extends React . Component {
2015-09-21 19:01:52 -07:00
constructor ( props ) {
super ( props ) ;
this . handleChange = this . handleChange . bind ( this ) ;
this . handleSubmit = this . handleSubmit . bind ( this ) ;
this . state = {
EnableRateLimiter : this . props . config . RateLimitSettings . EnableRateLimiter ,
VaryByRemoteAddr : this . props . config . RateLimitSettings . VaryByRemoteAddr ,
saveNeeded : false ,
serverError : null
} ;
}
handleChange ( action ) {
var s = { saveNeeded : true , serverError : this . state . serverError } ;
if ( action === 'EnableRateLimiterTrue' ) {
s . EnableRateLimiter = true ;
}
if ( action === 'EnableRateLimiterFalse' ) {
s . EnableRateLimiter = false ;
}
if ( action === 'VaryByRemoteAddrTrue' ) {
s . VaryByRemoteAddr = true ;
}
if ( action === 'VaryByRemoteAddrFalse' ) {
s . VaryByRemoteAddr = false ;
}
this . setState ( s ) ;
}
handleSubmit ( e ) {
e . preventDefault ( ) ;
$ ( '#save-button' ) . button ( 'loading' ) ;
var config = this . props . config ;
2015-10-15 12:07:06 -04:00
config . RateLimitSettings . EnableRateLimiter = ReactDOM . findDOMNode ( this . refs . EnableRateLimiter ) . checked ;
config . RateLimitSettings . VaryByRemoteAddr = ReactDOM . findDOMNode ( this . refs . VaryByRemoteAddr ) . checked ;
config . RateLimitSettings . VaryByHeader = ReactDOM . findDOMNode ( this . refs . VaryByHeader ) . value . trim ( ) ;
2015-09-21 19:01:52 -07:00
var PerSec = 10 ;
2015-10-15 12:07:06 -04:00
if ( ! isNaN ( parseInt ( ReactDOM . findDOMNode ( this . refs . PerSec ) . value , 10 ) ) ) {
PerSec = parseInt ( ReactDOM . findDOMNode ( this . refs . PerSec ) . value , 10 ) ;
2015-09-21 19:01:52 -07:00
}
config . RateLimitSettings . PerSec = PerSec ;
2015-10-15 12:07:06 -04:00
ReactDOM . findDOMNode ( this . refs . PerSec ) . value = PerSec ;
2015-09-21 19:01:52 -07:00
var MemoryStoreSize = 10000 ;
2015-10-15 12:07:06 -04:00
if ( ! isNaN ( parseInt ( ReactDOM . findDOMNode ( this . refs . MemoryStoreSize ) . value , 10 ) ) ) {
MemoryStoreSize = parseInt ( ReactDOM . findDOMNode ( this . refs . MemoryStoreSize ) . value , 10 ) ;
2015-09-21 19:01:52 -07:00
}
config . RateLimitSettings . MemoryStoreSize = MemoryStoreSize ;
2015-10-15 12:07:06 -04:00
ReactDOM . findDOMNode ( this . refs . MemoryStoreSize ) . value = MemoryStoreSize ;
2015-09-21 19:01:52 -07:00
Client . saveConfig (
config ,
( ) => {
AsyncClient . getConfig ( ) ;
this . setState ( {
serverError : null ,
saveNeeded : false
} ) ;
$ ( '#save-button' ) . button ( 'reset' ) ;
} ,
( err ) => {
this . setState ( {
serverError : err . message ,
saveNeeded : true
} ) ;
$ ( '#save-button' ) . button ( 'reset' ) ;
}
) ;
}
render ( ) {
2016-01-27 15:49:26 -03:00
const { formatMessage } = this . props . intl ;
2015-09-21 19:01:52 -07:00
var serverError = '' ;
if ( this . state . serverError ) {
serverError = < div className = 'form-group has-error' > < label className = 'control-label' > { this . state . serverError } < / label > < / div > ;
}
var saveClass = 'btn' ;
if ( this . state . saveNeeded ) {
saveClass = 'btn btn-primary' ;
}
return (
< div className = 'wrapper--fixed' >
< div className = 'banner' >
< div className = 'banner__content' >
2016-01-27 15:49:26 -03:00
< h4 className = 'banner__heading' >
< FormattedMessage
id = 'admin.rate.noteTitle'
defaultMessage = 'Note:'
/ >
< / h4 >
< p >
< FormattedMessage
id = 'admin.rate.noteDescription'
defaultMessage = 'Changing properties in this section will require a server restart before taking effect.'
/ >
< / p >
2015-09-21 19:01:52 -07:00
< / div >
< / div >
2016-01-27 15:49:26 -03:00
< h3 >
< FormattedMessage
id = 'admin.rate.title'
defaultMessage = 'Rate Limit Settings'
/ >
< / h3 >
2015-09-21 19:01:52 -07:00
< form
className = 'form-horizontal'
role = 'form'
>
< div className = 'form-group' >
< label
className = 'control-label col-sm-4'
htmlFor = 'EnableRateLimiter'
>
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.enableLimiterTitle'
defaultMessage = 'Enable Rate Limiter: '
/ >
2015-09-21 19:01:52 -07:00
< / label >
< div className = 'col-sm-8' >
< label className = 'radio-inline' >
< input
type = 'radio'
name = 'EnableRateLimiter'
value = 'true'
ref = 'EnableRateLimiter'
defaultChecked = { this . props . config . RateLimitSettings . EnableRateLimiter }
onChange = { this . handleChange . bind ( this , 'EnableRateLimiterTrue' ) }
/ >
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.true'
defaultMessage = 'true'
/ >
2015-09-21 19:01:52 -07:00
< / label >
< label className = 'radio-inline' >
< input
type = 'radio'
name = 'EnableRateLimiter'
value = 'false'
defaultChecked = { ! this . props . config . RateLimitSettings . EnableRateLimiter }
onChange = { this . handleChange . bind ( this , 'EnableRateLimiterFalse' ) }
/ >
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.false'
defaultMessage = 'false'
/ >
2015-09-21 19:01:52 -07:00
< / label >
2016-01-27 15:49:26 -03:00
< p className = 'help-text' >
< FormattedMessage
id = 'admin.rate.enableLimiterDescription'
defaultMessage = 'When true, APIs are throttled at rates specified below.'
/ >
< / p >
2015-09-21 19:01:52 -07:00
< / div >
< / div >
< div className = 'form-group' >
< label
className = 'control-label col-sm-4'
htmlFor = 'PerSec'
>
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.queriesTitle'
defaultMessage = 'Number Of Queries Per Second:'
/ >
2015-09-21 19:01:52 -07:00
< / label >
< div className = 'col-sm-8' >
< input
type = 'text'
className = 'form-control'
id = 'PerSec'
ref = 'PerSec'
2016-01-27 15:49:26 -03:00
placeholder = { formatMessage ( holders . queriesExample ) }
2015-09-21 19:01:52 -07:00
defaultValue = { this . props . config . RateLimitSettings . PerSec }
onChange = { this . handleChange }
disabled = { ! this . state . EnableRateLimiter }
/ >
2016-01-27 15:49:26 -03:00
< p className = 'help-text' >
< FormattedMessage
id = 'admin.rate.queriesDescription'
defaultMessage = 'Throttles API at this number of requests per second.'
/ >
< / p >
2015-09-21 19:01:52 -07:00
< / div >
< / div >
< div className = 'form-group' >
< label
className = 'control-label col-sm-4'
htmlFor = 'MemoryStoreSize'
>
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.memoryTitle'
defaultMessage = 'Memory Store Size:'
/ >
2015-09-21 19:01:52 -07:00
< / label >
< div className = 'col-sm-8' >
< input
type = 'text'
className = 'form-control'
id = 'MemoryStoreSize'
ref = 'MemoryStoreSize'
2016-01-27 15:49:26 -03:00
placeholder = { formatMessage ( holders . memoryExample ) }
2015-09-21 19:01:52 -07:00
defaultValue = { this . props . config . RateLimitSettings . MemoryStoreSize }
onChange = { this . handleChange }
disabled = { ! this . state . EnableRateLimiter }
/ >
2016-01-27 15:49:26 -03:00
< p className = 'help-text' >
< FormattedMessage
id = 'admin.rate.memoryDescription'
defaultMessage = 'Maximum number of users sessions connected to the system as determined by "Vary By Remote Address" and "Vary By Header" settings below.'
/ >
< / p >
2015-09-21 19:01:52 -07:00
< / div >
< / div >
< div className = 'form-group' >
< label
className = 'control-label col-sm-4'
htmlFor = 'VaryByRemoteAddr'
>
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.remoteTitle'
defaultMessage = 'Vary By Remote Address: '
/ >
2015-09-21 19:01:52 -07:00
< / label >
< div className = 'col-sm-8' >
< label className = 'radio-inline' >
< input
type = 'radio'
name = 'VaryByRemoteAddr'
value = 'true'
ref = 'VaryByRemoteAddr'
defaultChecked = { this . props . config . RateLimitSettings . VaryByRemoteAddr }
onChange = { this . handleChange . bind ( this , 'VaryByRemoteAddrTrue' ) }
disabled = { ! this . state . EnableRateLimiter }
/ >
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.true'
defaultMessage = 'true'
/ >
2015-09-21 19:01:52 -07:00
< / label >
< label className = 'radio-inline' >
< input
type = 'radio'
name = 'VaryByRemoteAddr'
value = 'false'
defaultChecked = { ! this . props . config . RateLimitSettings . VaryByRemoteAddr }
onChange = { this . handleChange . bind ( this , 'VaryByRemoteAddrFalse' ) }
disabled = { ! this . state . EnableRateLimiter }
/ >
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.false'
defaultMessage = 'false'
/ >
2015-09-21 19:01:52 -07:00
< / label >
2016-01-27 15:49:26 -03:00
< p className = 'help-text' >
< FormattedMessage
id = 'admin.rate.remoteDescription'
defaultMessage = 'When true, rate limit API access by IP address.'
/ >
< / p >
2015-09-21 19:01:52 -07:00
< / div >
< / div >
< div className = 'form-group' >
< label
className = 'control-label col-sm-4'
htmlFor = 'VaryByHeader'
>
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.httpHeaderTitle'
defaultMessage = 'Vary By HTTP Header:'
/ >
2015-09-21 19:01:52 -07:00
< / label >
< div className = 'col-sm-8' >
< input
type = 'text'
className = 'form-control'
id = 'VaryByHeader'
ref = 'VaryByHeader'
2016-01-27 15:49:26 -03:00
placeholder = { formatMessage ( holders . httpHeaderExample ) }
2015-09-21 19:01:52 -07:00
defaultValue = { this . props . config . RateLimitSettings . VaryByHeader }
onChange = { this . handleChange }
disabled = { ! this . state . EnableRateLimiter || this . state . VaryByRemoteAddr }
/ >
2016-01-27 15:49:26 -03:00
< p className = 'help-text' >
< FormattedMessage
id = 'admin.rate.httpHeaderDescription'
defaultMessage = 'When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'
/ >
< / p >
2015-09-21 19:01:52 -07:00
< / div >
< / div >
< div className = 'form-group' >
< div className = 'col-sm-12' >
{ serverError }
< button
disabled = { ! this . state . saveNeeded }
type = 'submit'
className = { saveClass }
onClick = { this . handleSubmit }
id = 'save-button'
2016-01-27 15:49:26 -03:00
data - loading - text = { '<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage ( holders . saving ) }
2015-09-21 19:01:52 -07:00
>
2016-01-27 15:49:26 -03:00
< FormattedMessage
id = 'admin.rate.save'
defaultMessage = 'Save'
/ >
2015-09-21 19:01:52 -07:00
< / button >
< / div >
< / div >
< / form >
< / div >
) ;
}
}
RateSettings . propTypes = {
2016-01-27 15:49:26 -03:00
intl : intlShape . isRequired ,
2015-09-21 19:01:52 -07:00
config : React . PropTypes . object
} ;
2016-01-27 15:49:26 -03:00
export default injectIntl ( RateSettings ) ;