@ -1,6 +1,6 @@
'use strict' ;
'use strict' ;
const { Ratelimits } = require ( _ _dirname + '/../../db/' )
const { Captchas , Ratelimits } = require ( _ _dirname + '/../../db/' )
, { secureCookies , rateLimitCost , captchaOptions } = require ( _ _dirname + '/../../configs/main.js' )
, { secureCookies , rateLimitCost , captchaOptions } = require ( _ _dirname + '/../../configs/main.js' )
, generateCaptcha = require ( _ _dirname + ` /../../helpers/captcha/generators/ ${ captchaOptions . type } .js ` )
, generateCaptcha = require ( _ _dirname + ` /../../helpers/captcha/generators/ ${ captchaOptions . type } .js ` )
, production = process . env . NODE _ENV === 'production' ;
, production = process . env . NODE _ENV === 'production' ;
@ -12,6 +12,7 @@ module.exports = async (req, res, next) => {
}
}
let captchaId ;
let captchaId ;
let maxAge = 5 * 60 * 1000 ;
try {
try {
if ( ! res . locals . tor ) {
if ( ! res . locals . tor ) {
const ratelimit = await Ratelimits . incrmentQuota ( res . locals . ip . single , 'captcha' , rateLimitCost . captcha ) ;
const ratelimit = await Ratelimits . incrmentQuota ( res . locals . ip . single , 'captcha' , rateLimitCost . captcha ) ;
@ -19,7 +20,15 @@ module.exports = async (req, res, next) => {
return res . status ( 429 ) . redirect ( '/file/ratelimit.png' ) ;
return res . status ( 429 ) . redirect ( '/file/ratelimit.png' ) ;
}
}
}
}
const { id } = await generateCaptcha ( ) ;
let id ;
if ( ( await Captchas . db . estimatedDocumentCount ( ) ) >= captchaOptions . generateLimit ) {
//TODOs: round robin sample? store in redis? only sample random with longer than x expiry?
const randomCaptcha = await Captchas . randomSample ( ) ;
id = randomCaptcha . _id ;
maxAge = Math . abs ( ( randomCaptcha . expireAt . getTime ( ) + maxAge ) - Date . now ( ) ) ; //abs in case mongo hasn't pruned, and will not be too big since it can't be too far away from pruning anyway
} else {
( { id } = await generateCaptcha ( ) ) ;
}
captchaId = id ;
captchaId = id ;
} catch ( err ) {
} catch ( err ) {
return next ( err ) ;
return next ( err ) ;
@ -27,9 +36,9 @@ module.exports = async (req, res, next) => {
return res
return res
. cookie ( 'captchaid' , captchaId . toString ( ) , {
. cookie ( 'captchaid' , captchaId . toString ( ) , {
'maxAge' : 5 * 60 * 1000 , //5 minute cookie
'secure' : production && secureCookies ,
'secure' : production && secureCookies ,
'sameSite' : 'strict'
'sameSite' : 'strict' ,
maxAge ,
} )
} )
. redirect ( ` /captcha/ ${ captchaId } .jpg ` ) ;
. redirect ( ` /captcha/ ${ captchaId } .jpg ` ) ;