1+ import { Request , Response } from 'express'
2+ import { createLogger } from '../../factories/logger-factory'
3+ import { getRemoteAddress } from '../../utils/http'
4+ import { IController } from '../../@types/controllers'
5+ import { IRateLimiter } from '../../@types/utils'
6+ import { IUserRepository } from '../../@types/repositories'
7+ import { path } from 'ramda'
8+ import { Settings } from '../../@types/settings'
9+
10+ const debug = createLogger ( 'get-admission-check-controller' )
11+
12+ export class GetSubmissionCheckController implements IController {
13+ public constructor (
14+ private readonly userRepository : IUserRepository ,
15+ private readonly settings : ( ) => Settings ,
16+ private readonly rateLimiter : ( ) => IRateLimiter ,
17+ ) { }
18+
19+ public async handleRequest ( request : Request , response : Response ) : Promise < void > {
20+ const currentSettings = this . settings ( )
21+
22+ const limited = await this . isRateLimited ( request , currentSettings )
23+ if ( limited ) {
24+ response
25+ . status ( 429 )
26+ . setHeader ( 'content-type' , 'text/plain; charset=utf8' )
27+ . send ( 'Too many requests' )
28+ return
29+ }
30+
31+ const pubkey = request . params . pubkey
32+ const user = await this . userRepository . findByPubkey ( pubkey )
33+
34+ let userAdmitted = false
35+
36+ const minBalance = currentSettings . limits ?. event ?. pubkey ?. minBalance
37+ if ( user && user . isAdmitted && ( ! minBalance || user . balance >= minBalance ) ) {
38+ userAdmitted = true
39+ }
40+
41+ response
42+ . status ( 200 )
43+ . setHeader ( 'content-type' , 'application/json; charset=utf8' )
44+ . send ( { userAdmitted } )
45+
46+ return
47+ }
48+
49+ public async isRateLimited ( request : Request , settings : Settings ) {
50+ const rateLimits = path ( [ 'limits' , 'admissionCheck' , 'rateLimits' ] , settings )
51+ if ( ! Array . isArray ( rateLimits ) || ! rateLimits . length ) {
52+ return false
53+ }
54+
55+ const ipWhitelist = path ( [ 'limits' , 'admissionCheck' , 'ipWhitelist' ] , settings )
56+ const remoteAddress = getRemoteAddress ( request , settings )
57+
58+ let limited = false
59+ if ( Array . isArray ( ipWhitelist ) && ! ipWhitelist . includes ( remoteAddress ) ) {
60+ const rateLimiter = this . rateLimiter ( )
61+ for ( const { rate, period } of rateLimits ) {
62+ if ( await rateLimiter . hit ( `${ remoteAddress } :admission-check:${ period } ` , 1 , { period, rate } ) ) {
63+ debug ( 'rate limited %s: %d in %d milliseconds' , remoteAddress , rate , period )
64+ limited = true
65+ }
66+ }
67+ }
68+ return limited
69+ }
70+ }
0 commit comments