@@ -9,6 +9,54 @@ const Generators = app.get('Generators');
99const Snippet = require ( './models/Snippet' ) ;
1010const Version = require ( './models/Version' ) ;
1111
12+ const abuseLimit = 20 ;
13+ let abuseCache = { } ;
14+ let timeout = { } ;
15+
16+ function checkAbuse ( id ) {
17+ // abuse is considered <abuseLimit> requests per second from same socket
18+ // Block further requests until until 5 seconds have passed without another barrage
19+
20+ if ( ! ( id in abuseCache ) ) {
21+ abuseCache [ id ] = {
22+ firstAccess : new Date ( ) . getTime ( ) ,
23+ lastAccess : new Date ( ) . getTime ( ) ,
24+ total : 1
25+ } ;
26+
27+ // Update current stats
28+ } else {
29+ abuseCache [ id ] . lastAccess = new Date ( ) . getTime ( ) ;
30+ abuseCache [ id ] . total ++ ;
31+ }
32+
33+ // Check for abuse
34+ if ( abuseCache [ id ] && abuseCache [ id ] . total > abuseLimit && abuseCache [ id ] . lastAccess - abuseCache [ id ] . firstAccess < 1000 ) {
35+ timeout [ id ] = new Date ( ) . getTime ( ) ; // time they were placed into time out
36+ return true ;
37+ }
38+
39+ if ( id in timeout ) {
40+ return true ;
41+ }
42+ return false ;
43+ }
44+
45+ function checkTimeout ( ) {
46+ _ . each ( timeout , ( a , b ) => {
47+ if ( new Date ( ) . getTime ( ) - a > 1000 ) {
48+ delete timeout [ b ] ;
49+ }
50+ } ) ;
51+ }
52+
53+ // Reset abuse cache every second
54+ setInterval ( ( ) => {
55+ abuseCache = { } ;
56+ } , 1000 ) ;
57+
58+ setInterval ( checkTimeout , 2500 ) ;
59+
1260// Attach the user's session to the socket object
1361// If user isn't logged in, set session to null for front page demo
1462io . use ( ( socket , next ) => {
@@ -27,8 +75,11 @@ io.use((socket, next) => {
2775} ) ;
2876
2977io . on ( 'connection' , socket => {
78+
3079 // Search
3180 socket . on ( 'search' , msg => {
81+ if ( checkAbuse ( socket . id ) ) return socket . emit ( 'abuse' ) ;
82+
3283 let tags = _ . uniq ( msg . query . slice ( 0 , 255 ) . split ( ',' ) . map ( tag => tag . trim ( ) ) . filter ( tag => tag !== "" ) ) . filter ( tag => tag . match ( / ^ ( [ a - z A - Z 0 - 9 _ \- \. + \[ \] \{ \} \( \) ] { 1 , 32 } ) $ / g) !== null ) ;
3384 Snippet . search ( tags ) . then ( data => {
3485 let obj = data . reduce ( function ( o , v , i ) {
@@ -41,11 +92,27 @@ io.on('connection', socket => {
4192
4293 // Snippet info
4394 socket . on ( 'snippet' , msg => {
44- Version . getCond ( { snippetID : msg . id } ) . then ( snippet => socket . emit ( 'snippetResults' , snippet ) ) ;
95+ if ( checkAbuse ( socket . id ) ) return socket . emit ( 'abuse' ) ;
96+
97+ Version . getCond ( { snippetID : msg . id } ) . then ( snippet => {
98+ Snippet . getCond ( { [ 's.id' ] : snippet . snippetID } ) . then ( orig => {
99+ if ( snippet === null ) {
100+ socket . emit ( 'snippetResults' , null ) ;
101+ } else if ( snippet . published === 0 ) {
102+ Version . getVersion ( orig . ref , snippet . version - 1 ) . then ( ver => {
103+ socket . emit ( 'snippetResults' , ver )
104+ } ) ;
105+ } else {
106+ socket . emit ( 'snippetResults' , snippet )
107+ }
108+ } ) ;
109+ } ) ;
45110 } ) ;
46111
47112 // Generators
48113 socket . on ( 'lintCode' , msg => {
114+ if ( checkAbuse ( socket . id ) ) return socket . emit ( 'abuse' ) ;
115+
49116 msg . code = String ( msg . code ) . slice ( 0 , 8192 ) ;
50117 let shortest = Math . floor ( Math . random ( ) * Generators . realtime . length ) ;
51118 for ( let i = 0 ; i < Generators . realtime . length ; i ++ ) {
@@ -68,6 +135,8 @@ io.on('connection', socket => {
68135 } ) ;
69136
70137 socket . on ( 'lintDemoCode' , msg => {
138+ if ( checkAbuse ( socket . id ) ) return socket . emit ( 'abuse' ) ;
139+
71140 msg . code = String ( msg . code ) . slice ( 0 , 8192 ) ;
72141 let shortest = Math . floor ( Math . random ( ) * Generators . demo . length ) ;
73142 for ( let i = 0 ; i < Generators . demo . length ; i ++ ) {
@@ -90,6 +159,8 @@ io.on('connection', socket => {
90159 } ) ;
91160
92161 socket . on ( 'lintSnippetCode' , msg => {
162+ if ( checkAbuse ( socket . id ) ) return socket . emit ( 'abuse' ) ;
163+
93164 msg . code = String ( msg . code ) . slice ( 0 , 8192 ) ;
94165 let shortest = Math . floor ( Math . random ( ) * Generators . realtime . length ) ;
95166 for ( let i = 0 ; i < Generators . realtime . length ; i ++ ) {
0 commit comments